added getcursor pos, undone forced fullscreen
This commit is contained in:
parent
4e1ee4d089
commit
a013c34fc4
16
editor.nim
16
editor.nim
|
@ -1,12 +1,11 @@
|
|||
import unicode
|
||||
import strutils
|
||||
import terminal
|
||||
import strformat
|
||||
import posix
|
||||
|
||||
import termBuffer/buffer
|
||||
|
||||
import keycodes
|
||||
import terminalUtils/buffer
|
||||
import terminalUtils/terminalGetInfo
|
||||
import terminalUtils/keycodes
|
||||
|
||||
type
|
||||
EditorState* = ref object
|
||||
|
@ -44,7 +43,6 @@ proc newEditor*(prompt: string = "> ", multiline: bool = true): EditorState =
|
|||
result.prompt = prompt
|
||||
result.maxRowsGoal = if multiline: 0 else: 1
|
||||
result.buffer.add("")
|
||||
result.screenBuffer = newBuffer(0, 0, terminalWidth(), terminalHeight(), stdout)
|
||||
editors.add(result)
|
||||
|
||||
proc destroyEditor*(oldEditor: EditorState) =
|
||||
|
@ -63,13 +61,11 @@ proc render(ed: EditorState) =
|
|||
template cline(ed: EditorState): var string =
|
||||
ed.buffer[ed.y]
|
||||
|
||||
proc print*(ed: EditorState, text: string) =
|
||||
ed.screenBuffer.print(text)
|
||||
ed.screenBuffer.redraw()
|
||||
|
||||
proc read*(ed: EditorState): (EditorResult, string) =
|
||||
|
||||
var editorResult = erError
|
||||
let (_, cursorY) = termGetCursorPos(stdout)
|
||||
ed.screenBuffer = newBuffer(0, cursorY, termGetWidth(), termGetHeight() - cursorY, stdout)
|
||||
|
||||
ed.render()
|
||||
while true:
|
||||
|
@ -126,8 +122,10 @@ proc read*(ed: EditorState): (EditorResult, string) =
|
|||
result = (editorResult, ed.buffer.join("\n"))
|
||||
|
||||
# cleanup
|
||||
stdout.write("\n")
|
||||
ed.history.add(ed.buffer)
|
||||
ed.buffer = @[""]
|
||||
ed.y = 0
|
||||
ed.x = 0
|
||||
ed.screenBuffer = nil
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import editor
|
||||
|
||||
let e = newEditor("> ", false)
|
||||
let e = newEditor(">>> ", false)
|
||||
|
||||
while true:
|
||||
let (res, text) = e.read()
|
||||
if res in {erCtrlC, erCtrlD} or text == "quit":
|
||||
e.print("")
|
||||
break
|
||||
e.print(text)
|
||||
if text.len() > 0:
|
||||
echo text
|
|
@ -1,14 +0,0 @@
|
|||
# list of functions to generate escape sequences
|
||||
|
||||
import strformat
|
||||
import strutils
|
||||
|
||||
func escCursorPos*(x, y: int): string =
|
||||
&"\e[{y+1};{x+1}H"
|
||||
|
||||
func escAttributes*(attributes: seq[uint8]): string =
|
||||
let joined = attributes.join(";")
|
||||
&"\e[{joined}m"
|
||||
|
||||
func escEraseCharacters*(n: int): string =
|
||||
&"\e[{n}X"
|
|
@ -100,22 +100,7 @@ proc write*(buf: Buffer, text: string) =
|
|||
for i in fromPos..toPos:
|
||||
buf.buffered[i] = Cell(text: runes[i-fromPos], attributes: buf.cursorAttributes)
|
||||
|
||||
buf.bufferX += runes.len()
|
||||
|
||||
proc print*(buf: Buffer, text: string) =
|
||||
# write, but makes sure it's on its own line
|
||||
if buf.bufferX > 0:
|
||||
# TODO scroll implementation
|
||||
buf.bufferX = 0
|
||||
if buf.bufferY < buf.height - 1:
|
||||
buf.bufferY += 1
|
||||
|
||||
buf.write(text)
|
||||
|
||||
# TODO scroll implementation
|
||||
if text.len() > 0 and buf.bufferY < buf.height - 1:
|
||||
buf.bufferY += 1
|
||||
|
||||
buf.bufferX += runes.len()
|
||||
|
||||
proc redraw*(buf: Buffer, force: bool = false) =
|
||||
var toPrint = ""
|
||||
|
@ -130,7 +115,7 @@ proc redraw*(buf: Buffer, force: bool = false) =
|
|||
let y = i div buf.width
|
||||
let x = i mod buf.width
|
||||
# go to given place
|
||||
toPrint &= escCursorPos(x+buf.positionX, y+buf.positionY)
|
||||
toPrint &= escSetCursorPos(x+buf.positionX, y+buf.positionY)
|
||||
|
||||
# get the right attributes
|
||||
# first reset
|
||||
|
@ -149,7 +134,7 @@ proc redraw*(buf: Buffer, force: bool = false) =
|
|||
|
||||
# finish
|
||||
toPrint &= escAttributes(@[fsReset.uint8])
|
||||
toPrint &= escCursorPos(buf.bufferX + buf.positionX, buf.bufferY + buf.positionY)
|
||||
toPrint &= escSetCursorPos(buf.bufferX + buf.positionX, buf.bufferY + buf.positionY)
|
||||
buf.stdout.write(toPrint)
|
||||
|
||||
|
||||
|
@ -157,6 +142,7 @@ func getSize*(buf: Buffer): (int, int) =
|
|||
(buf.width, buf.height)
|
||||
|
||||
proc resize*(buf: Buffer, newX, newY: int) =
|
||||
# TODO
|
||||
raise newException(Defect, "Not implemented")
|
||||
|
||||
func getPosition*(buf: Buffer): (int, int) =
|
|
@ -0,0 +1,45 @@
|
|||
# list of functions to generate escape sequences
|
||||
# in the future, this can be expanded to support more platforms
|
||||
|
||||
import strformat
|
||||
import strutils
|
||||
import terminal
|
||||
|
||||
func escSetCursorPos*(x, y: int): string =
|
||||
&"\e[{y+1};{x+1}H"
|
||||
|
||||
const escGetCursorPos* = "\e[6n"
|
||||
|
||||
type InvalidResponseError* = object of CatchableError
|
||||
|
||||
proc termGetCursorPos*(ouput: File): (int, int) =
|
||||
|
||||
ouput.write(escGetCursorPos)
|
||||
|
||||
var response = ""
|
||||
if getch() != '\e':
|
||||
raise newException(InvalidResponseError, "Unsupported terminal - can't get cursor position.")
|
||||
if getch() != '[':
|
||||
raise newException(InvalidResponseError, "Can't parse response in getCursorPos")
|
||||
var newChar = getch()
|
||||
while newChar != ';':
|
||||
response &= newChar
|
||||
newChar = getch()
|
||||
let y = parseInt(response) - 1
|
||||
response = ""
|
||||
newChar = getch()
|
||||
while newChar != 'R':
|
||||
response &= newChar
|
||||
newChar = getch()
|
||||
let x = parseInt(response) - 1
|
||||
|
||||
return (x, y)
|
||||
|
||||
|
||||
|
||||
func escAttributes*(attributes: seq[uint8]): string =
|
||||
let joined = attributes.join(";")
|
||||
&"\e[{joined}m"
|
||||
|
||||
func escEraseCharacters*(n: int): string =
|
||||
&"\e[{n}X"
|
|
@ -0,0 +1,34 @@
|
|||
import terminal
|
||||
import strutils
|
||||
|
||||
import escapeSequences
|
||||
|
||||
proc termGetCursorPos*(ouput: File): (int, int) =
|
||||
|
||||
ouput.write(escGetCursorPos)
|
||||
|
||||
var response = ""
|
||||
if getch() != '\e':
|
||||
raise newException(InvalidResponseError, "Unsupported terminal - can't get cursor position.")
|
||||
if getch() != '[':
|
||||
raise newException(InvalidResponseError, "Can't parse response in getCursorPos")
|
||||
var newChar = getch()
|
||||
while newChar != ';':
|
||||
response &= newChar
|
||||
newChar = getch()
|
||||
let y = parseInt(response) - 1
|
||||
response = ""
|
||||
newChar = getch()
|
||||
while newChar != 'R':
|
||||
response &= newChar
|
||||
newChar = getch()
|
||||
let x = parseInt(response) - 1
|
||||
|
||||
return (x, y)
|
||||
|
||||
proc termGetWidth*: int =
|
||||
terminalWidth()
|
||||
|
||||
proc termGetHeight*: int =
|
||||
terminalHeight()
|
||||
|
Loading…
Reference in New Issue