diff --git a/editor.nim b/editor.nim index a87f9aa..cc439d0 100644 --- a/editor.nim +++ b/editor.nim @@ -17,20 +17,40 @@ type termBuffer: Buffer history: seq[TextBuffer] # past texts historyIndex: int # where are we in history + scroll: Scroll + active: bool + + # screen properties passed to renderer + width, height: int + cursorY: int EditorResult* = enum - erEnter, erCtrlC, erCtrlD, erError + erError, erEnter, erCtrlC, erCtrlD # for editors var editors: seq[EditorState] +proc redraw*(ed: EditorState): int = + render(ed.textBuffer, ed.termBuffer, ed.prompt, ed.scroll, ed.width, ed.height, ed.cursorY) + # resize support onSignal(28): - discard + let nh = termGetHeight() + let nw = termGetWidth() + for ed in editors: + ed.width = nw + ed.height = nh + if ed.active: + discard ed.redraw() proc newEditor*(prompt: string = "> "): EditorState = new(result) + let (_, cursorY) = termGetCursorPos(stdout) + result.cursorY = cursorY + result.width = termGetWidth() + result.height = termGetHeight() result.prompt = prompt + result.active = false editors.add(result) proc destroyEditor*(oldEditor: EditorState) = @@ -43,23 +63,23 @@ proc destroyEditor*(oldEditor: EditorState) = proc read*(ed: EditorState): (EditorResult, string) = var editorResult = erError - let (_, cursorY) = termGetCursorPos(stdout) - ed.termBuffer = newBuffer(0, cursorY, termGetWidth(), 1, stdout) + ed.termBuffer = newBuffer(0, ed.cursorY, termGetWidth(), 1, stdout) ed.textBuffer = newTextBuffer() ed.history.add(ed.textBuffer) ed.historyIndex = ed.history.high() - - var scroll: Scroll = new(Scroll) + ed.scroll = new(Scroll) + ed.active = true + var lastRenderLines = 0 template moveInHistory(delta: int) = let newHistoryIndex = min(max(ed.historyIndex + delta, 0), ed.history.high()) if newHistoryIndex != ed.historyIndex: ed.textBuffer = ed.history[newHistoryIndex] - scroll.reset() + ed.scroll.reset() ed.historyIndex = newHistoryIndex while true: - render(ed.textBuffer, ed.termBuffer, ed.prompt, scroll) + lastRenderLines = ed.redraw() let (getKeyResult, key) = getKey() case getKeyResult: of gkChar: @@ -114,14 +134,23 @@ proc read*(ed: EditorState): (EditorResult, string) = else: discard # not implemented + # stop redraws on resize + ed.active = false + # return val, strip final newline (due to how double enter is how you enter) let cont = ed.textBuffer.getContent() + if editorResult == erError: + raise newException(Defect, "Editor loop quit without setting editor result.") result = (editorResult, cont) # cleanup stdout.write("\n") + ed.cursorY = min(ed.height-1, ed.cursorY + lastRenderLines) # don't add empty lines to history if ed.history[ed.history.high()].getContent() == "": ed.history.del(ed.history.high()) - \ No newline at end of file + +proc updateCursorPos*(ed: EditorState) = + let (_, cursorY) = termGetCursorPos(stdout) + ed.cursorY = cursorY diff --git a/example.nim b/example.nim index 5fe04b8..e03f6b0 100644 --- a/example.nim +++ b/example.nim @@ -10,6 +10,10 @@ while true: elif text == "clear": eraseScreen() setCursorPos(0, 0) + e.updateCursorPos() continue if text.len() > 0: - echo text \ No newline at end of file + echo text + e.updateCursorPos() + +e.destroyEditor() \ No newline at end of file diff --git a/renderer.nim b/renderer.nim index a21e16c..82ea683 100644 --- a/renderer.nim +++ b/renderer.nim @@ -15,16 +15,19 @@ proc reset*(scroll: Scroll) = scroll.x = 0 scroll.y = 0 -proc render*(textBuffer: TextBuffer, termBuffer: Buffer, prompt: string, scroll: Scroll) = +proc render*(textBuffer: TextBuffer, termBuffer: Buffer, prompt: string, scroll: Scroll, width, height: int, edCursorY: int): int = # we are free to "redraw" everything everytime # since termBuffer double buffers + # returns how many lines were drawn # GET INFO let (x, y) = textBuffer.getCursorPos() let lines = textBuffer.lines() let lineCount = lines.len() - let termWidth = termGetWidth() - let termHeight = termGetHeight() + #let termWidth = termGetWidth() + let termWidth = width + #let termHeight = termGetHeight() + let termHeight = height let promptLen = prompt.len() let maxTextLen = termWidth - promptLen @@ -101,3 +104,5 @@ proc render*(textBuffer: TextBuffer, termBuffer: Buffer, prompt: string, scroll: termBuffer.setCursorPos(x + promptLen - scroll.x, y - scroll.y) termBuffer.redraw() + return termBuffer.getHeight() + diff --git a/terminalUtils/buffer.nim b/terminalUtils/buffer.nim index 6d028ab..b9d4583 100644 --- a/terminalUtils/buffer.nim +++ b/terminalUtils/buffer.nim @@ -158,6 +158,9 @@ proc redraw*(buf: Buffer, force: bool = false) = func getSize*(buf: Buffer): (int, int) = (buf.width, buf.height) +func getHeight*(buf: Buffer): int = + buf.height + proc resize*(buf: Buffer, newWidth, newHeight: int, terminalWidth, terminalHeight: int) = # assert sizes diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..26024af --- /dev/null +++ b/todo.txt @@ -0,0 +1,11 @@ +Short term goals: +- fixing TODOs in code +- finding a better way to do getCursorPos +- fix resizing +- fix erasing in buffer + +Long term goals: +- tab autocomplete +- syntax highlighting +- more fancy looks +- windows support \ No newline at end of file