added uniterm
note: currently broken, download another commit if you're just testing
This commit is contained in:
parent
0390de150a
commit
2453283ad9
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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]("")
|
||||
|
||||
|
|
Loading…
Reference in New Issue