work on multiline, horizontal scroll
This commit is contained in:
parent
d2001bb458
commit
2fffb11a69
|
@ -49,8 +49,10 @@ proc read*(ed: EditorState): (EditorResult, string) =
|
|||
ed.history.add(ed.textBuffer)
|
||||
ed.historyIndex = ed.history.high()
|
||||
|
||||
var scroll: Scroll = new(Scroll)
|
||||
|
||||
while true:
|
||||
render(ed.textBuffer, ed.termBuffer, ed.prompt)
|
||||
render(ed.textBuffer, ed.termBuffer, ed.prompt, scroll)
|
||||
let (getKeyResult, key) = getKey()
|
||||
case getKeyResult:
|
||||
of gkChar:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import editor
|
||||
import terminal
|
||||
|
||||
let e = newEditor(">>> ")
|
||||
|
||||
|
@ -6,5 +7,9 @@ while true:
|
|||
let (res, text) = e.read()
|
||||
if res in {erCtrlC, erCtrlD} or text == "quit":
|
||||
break
|
||||
elif text == "clear":
|
||||
eraseScreen()
|
||||
setCursorPos(0, 0)
|
||||
continue
|
||||
if text.len() > 0:
|
||||
echo text
|
54
renderer.nim
54
renderer.nim
|
@ -2,26 +2,66 @@
|
|||
# when render() is called, rewrites the terminal buffer completely as a function of
|
||||
# of the text buffer
|
||||
|
||||
import strutils
|
||||
|
||||
import textBuffer
|
||||
import terminalUtils/buffer
|
||||
import terminalUtils/terminalGetInfo
|
||||
|
||||
proc render*(textBuffer: TextBuffer, termBuffer: Buffer, prompt: string) =
|
||||
type Scroll* = ref object
|
||||
x, y: int
|
||||
|
||||
proc render*(textBuffer: TextBuffer, termBuffer: Buffer, prompt: string, scroll: Scroll) =
|
||||
# we are free to "redraw" everything everytime
|
||||
# since termBuffer double buffers
|
||||
|
||||
# resizing the buffer if needed
|
||||
let lineCount = textBuffer.getLineCount()
|
||||
let termWidth = termGetWidth()
|
||||
let termHeight = termGetHeight() # TODO
|
||||
let termHeight = termGetHeight()
|
||||
|
||||
let (bufWidth, bufHeight) = termBuffer.getSize()
|
||||
|
||||
|
||||
termBuffer.clearLine()
|
||||
termBuffer.write(prompt)
|
||||
termBuffer.write(textBuffer.getLine())
|
||||
if bufWidth != termWidth or bufHeight != min(lineCount, termHeight):
|
||||
termBuffer.resize(termWidth, min(lineCount, termHeight))
|
||||
|
||||
termBuffer.clear()
|
||||
|
||||
let (x, y) = textBuffer.getCursorPos()
|
||||
termBuffer.setCursorPos(x + prompt.len(), y)
|
||||
|
||||
let lines = textBuffer.lines()
|
||||
let promptLen = prompt.len()
|
||||
let maxTextLen = termWidth - promptLen
|
||||
if maxTextLen < 1:
|
||||
termBuffer.redraw()
|
||||
return # nothing will fit anyways
|
||||
|
||||
for i in 0..lines.high():
|
||||
let line = lines[i]
|
||||
if i == 0:
|
||||
termBuffer.write(prompt)
|
||||
else:
|
||||
termBuffer.write(" ".repeat(promptLen))
|
||||
|
||||
let lineLen = line.len()
|
||||
if lineLen < maxTextLen - 1:
|
||||
scroll.x = 0
|
||||
termBuffer.write(line)
|
||||
else:
|
||||
const scrollOffset = 2
|
||||
# horizontal scroll
|
||||
# right scroll
|
||||
if x - scroll.x >= maxTextLen - scrollOffset:
|
||||
scroll.x = x - maxTextLen + scrollOffset
|
||||
# left scroll
|
||||
if x - scroll.x < 0:
|
||||
scroll.x = x
|
||||
# left scroll
|
||||
# keep what's in range
|
||||
let fromPos = scroll.x
|
||||
let toPos = min(scroll.x+maxTextLen-2, line.high())
|
||||
termBuffer.write(line[fromPos..toPos])
|
||||
termBuffer.newLine()
|
||||
termBuffer.setCursorPos(x + promptLen - scroll.x, y - scroll.y)
|
||||
termBuffer.redraw()
|
||||
|
||||
|
|
|
@ -104,6 +104,9 @@ proc write*(buf: Buffer, text: string) =
|
|||
let runes = text.toRunes()
|
||||
buf.write(runes)
|
||||
|
||||
proc newLine*(buf: Buffer) =
|
||||
buf.bufferY += 1
|
||||
buf.bufferX = 0
|
||||
|
||||
proc redraw*(buf: Buffer, force: bool = false) =
|
||||
var toPrint = ""
|
||||
|
@ -144,17 +147,36 @@ proc redraw*(buf: Buffer, force: bool = false) =
|
|||
func getSize*(buf: Buffer): (int, int) =
|
||||
(buf.width, buf.height)
|
||||
|
||||
proc resize*(buf: Buffer, newX, newY: int) =
|
||||
proc resize*(buf: Buffer, newWidth, newHeight: int) =
|
||||
# shrinking X
|
||||
if newX < buf.width:
|
||||
if newWidth < buf.width:
|
||||
# dropping cells outside the screen
|
||||
var i = 0
|
||||
|
||||
buf.buffered.keepItIf(i mod buf.width < newWidth)
|
||||
i = 0
|
||||
buf.displayed.keepItIf(i mod buf.width < newWidth)
|
||||
# increasing X
|
||||
elif newWidth > buf.width:
|
||||
let extra = newWidth - buf.width
|
||||
let extraCells = Cell(text: Rune(0)).repeat(extra)
|
||||
for i in 0..buf.height-1:
|
||||
let pos = i * newWidth + buf.width
|
||||
buf.buffered.insert(extraCells, pos)
|
||||
buf.displayed.insert(extraCells, pos)
|
||||
|
||||
|
||||
# shrinking Y
|
||||
if newHeight < buf.height:
|
||||
buf.buffered.setLen(newHeight * newWidth)
|
||||
buf.displayed.setLen(newHeight * newWidth)
|
||||
# increasing Y
|
||||
elif newHeight > buf.height:
|
||||
let extra = newHeight - buf.height
|
||||
let extraCells = Cell(text: Rune(0)).repeat(extra * newWidth)
|
||||
buf.buffered &= extraCells
|
||||
buf.displayed &= extraCells
|
||||
|
||||
buf.width = newX
|
||||
buf.height = newY
|
||||
buf.width = newWidth
|
||||
buf.height = newHeight
|
||||
|
||||
func getPosition*(buf: Buffer): (int, int) =
|
||||
(buf.positionX, buf.positionY)
|
||||
|
|
|
@ -67,6 +67,10 @@ proc moveCursor*(buf: TextBuffer, dx, dy: int) =
|
|||
buf.cursorY = 0
|
||||
elif buf.cursorY > buf.content.high():
|
||||
buf.cursorY = buf.content.high()
|
||||
|
||||
if buf.cursorX > buf.cline().len():
|
||||
buf.cursorX = buf.cline().len()
|
||||
|
||||
|
||||
proc getCursorPos*(buf: TextBuffer): (int, int) =
|
||||
(buf.cursorX, buf.cursorY)
|
||||
|
@ -98,4 +102,7 @@ proc newLine*(buf: TextBuffer) =
|
|||
buf.cursorX = 0
|
||||
|
||||
proc getLineCount*(buf: TextBuffer): int =
|
||||
buf.content.len()
|
||||
buf.content.len()
|
||||
|
||||
proc lines*(buf: TextBuffer): seq[seq[Rune]] =
|
||||
buf.content
|
Loading…
Reference in New Issue