added uniterm

note: currently broken, download another commit if you're just testing
This commit is contained in:
Productive2 2021-02-19 14:11:25 +01:00
parent 0390de150a
commit 2453283ad9
4 changed files with 87 additions and 34 deletions

View File

@ -1,13 +1,13 @@
import strformat
import strutils
import tables
import terminal
import line
import multiline
import keycodes
import event
import renderer
import uniterm
type
JaleEvent* = enum
@ -73,12 +73,12 @@ proc reset(editor: LineEditor) =
editor.lastKeystroke = -1
editor.forceRedraw = false
proc render(editor: LineEditor, line: int = -1, hscroll: bool = true) =
proc render(editor: LineEditor, wr: var TermWriter, line: int = -1, hscroll: bool = true) =
var y = line
if y == -1:
y = editor.content.Y
renderLine(
wr.renderLine(
(
if y == 0:
editor.prompt
@ -89,49 +89,52 @@ proc render(editor: LineEditor, line: int = -1, hscroll: bool = true) =
0
)
proc clearLine =
write stdout, "\r" & " ".repeat(terminalWidth())
proc clearLine(wr: var TermWriter) =
wr.clearLine()
proc fullRender(editor: LineEditor) =
proc fullRender(editor: LineEditor, wr: var TermWriter) =
# from the top cursor pos, it draws the entire multiline prompt, then
# moves cursor to current y
for i in countup(0, editor.content.high()):
editor.render(i, false)
editor.render(wr, i, false)
if i < editor.rendered:
cursorDown(1)
wr.down(1)
else:
write stdout, "\n"
inc editor.rendered
var extraup = 0
while editor.content.len() < editor.rendered:
clearLine()
cursorDown(1)
wr.clearLine()
wr.down(1)
dec editor.rendered
inc extraup
cursorUp(editor.content.len() - editor.content.Y + extraup)
wr.up(editor.content.len() - editor.content.Y + extraup)
proc moveCursorToEnd(editor: LineEditor) =
proc moveCursorToEnd(editor: LineEditor, wr: var TermWriter) =
# only called when read finished
if editor.content.high() > editor.content.Y:
cursorDown(editor.content.high() - editor.content.Y)
write stdout, "\n"
wr.down(editor.content.high() - editor.content.Y)
wr.lf()
proc read*(editor: LineEditor): string =
editor.state = esTyping
editor.events.call(jePreRead)
var buffer: TermWriter
# starts at the top, full render moves it into the right y
editor.fullRender()
editor.fullRender(buffer)
while editor.state == esTyping:
# refresh current line every time
editor.render()
setCursorXPos(editor.content.X + editor.prompt.len())
editor.render(buffer)
buffer.setCursorX(editor.content.X + editor.prompt.len())
# get key (with escapes)
buffer.flush()
let key = getKey()
# record y pos
let preY = editor.content.Y
@ -143,16 +146,17 @@ proc read*(editor: LineEditor): string =
if editor.forceRedraw or preY != editor.content.Y:
# move to the top
if preY > 0:
cursorUp(preY)
buffer.up(preY)
# move to the right y
editor.fullRender()
editor.fullRender(buffer)
if editor.forceRedraw:
editor.forceRedraw = false
editor.events.call(jePostRead)
# move cursor to end
editor.moveCursorToEnd()
editor.moveCursorToEnd(buffer)
buffer.flush()
if editor.state == esFinishing:
result = editor.content.getContent()
editor.reset()

View File

@ -21,17 +21,19 @@ proc bindTerminate*(editor: LineEditor) =
editor.quit()
proc populateDefaults*(editor: LineEditor, enterSubmits = true, shiftForVerticalMove = true) =
proc populateDefaults*(editor: LineEditor, enterSubmits = true, ctrlForVerticalMove = true) =
editor.bindInput()
editor.bindTerminate()
editor.bindKey("left"):
editor.content.left()
editor.bindKey("right"):
editor.content.right()
if shiftForVerticalMove:
editor.bindKey("shiftup"):
if ctrlForVerticalMove:
editor.bindKey("ctrlup"):
editor.content.up()
editor.bindKey("shiftdown"):
editor.bindKey("ctrldown"):
if editor.content.Y() == editor.content.high():
editor.content.insertline()
editor.content.down()
editor.bindKey("ctrlpageup"):
editor.content.vhome()
@ -55,8 +57,6 @@ proc populateDefaults*(editor: LineEditor, enterSubmits = true, shiftForVertical
editor.bindKey("delete"):
editor.content.delete()
if enterSubmits:
editor.bindKey("ctrldown"):
editor.content.enter()
editor.bindKey("enter"):
editor.finish()
else:

View File

@ -2,20 +2,21 @@
#
# a terminal renderer for readline-like libraries
import terminal
import strutils
import uniterm
proc renderLine*(prompt: string, content: string, hscroll: int = 0) =
proc renderLine*(wr: var TermWriter, prompt: string, content: string, hscroll: int = 0) =
wr.cr()
var content = prompt & content
if content.len() < terminalWidth():
content &= " ".repeat(terminalWidth() - content.len())
if content.len() > terminalWidth():
if content.len() < wr.terminalWidth():
content &= " ".repeat(wr.terminalWidth() - content.len())
if content.len() > wr.terminalWidth():
var lower = hscroll
var upper = hscroll + terminalWidth() - 1
var upper = hscroll + wr.terminalWidth() - 1
if upper > content.high():
upper = content.high()
content = content[lower..upper]
write stdout, "\r" & content
wr &= content

View File

@ -3,6 +3,9 @@
# source: https://github.com/h3rald/nimline/blob/master/nimline.nim
# lines 42-56 (modified)
import strutils
import terminal
when defined(windows):
proc putchr(c: cint): cint {.discardable, header: "<conio.h>", importc: "_putch".}
proc getchr(): cint {.header: "<conio.h>", importc: "_getch".}
@ -15,7 +18,6 @@ when defined(windows):
getchr().int
else:
import terminal
proc uniPutChr*(c: char) =
## Prints an ASCII character to stdout.
stdout.write(c)
@ -24,3 +26,49 @@ else:
## Retrieves an ASCII character from stdin.
return getch().int
type TermWriter* = distinct string
proc `&=`*(wr: var TermWriter, str: string) =
wr = TermWriter(string(wr) & str)
proc lf*(wr: var TermWriter) =
wr &= "\n"
proc cr*(wr: var TermWriter) =
when defined(windows):
wr &= ($27.char & "[0G")
else:
wr &= "\r"
proc up*(wr: var TermWriter, count: int) =
if count == 0:
return
wr &= ($27.char & "[" & $count & "A")
proc down*(wr: var TermWriter, count: int) =
if count == 0:
return
wr &= ($27.char & "[" & $count & "B")
proc clearLine*(wr: var TermWriter) =
when defined(windows):
wr &= ($27.char & "[1M" & $27.char & "[1L")
else:
wr &= ($27.char & "[2K")
proc setCursorX*(wr: var TermWriter, x: int) =
when defined(windows):
wr &= ($27.char & "[" & $x & "G")
else:
if x == 0:
wr &= "\r"
else:
wr &= ("\r" & $27.char & "[" & $x & "C")
proc terminalWidth*(wr: var TermWriter): int =
terminalWidth()
proc flush*(wr: var TermWriter) =
stdout.write(cast[string](wr))
wr = cast[TermWriter]("")