Added horizontal scrolling (for single/all line)
This commit is contained in:
parent
0d8a66b57e
commit
36b32c5a23
|
@ -22,6 +22,7 @@ e.bindKey("ctrl+s"):
|
|||
|
||||
e.prompt = ""
|
||||
e.populateDefaults(enterSubmits = false, ctrlForVerticalMove = false)
|
||||
e.scrollMode = sbAllScroll
|
||||
let result = e.read()
|
||||
if save and paramCount() > 0:
|
||||
writeFile(paramStr(1), result)
|
||||
|
|
|
@ -16,11 +16,15 @@ type
|
|||
EditorState = enum
|
||||
esOutside, esTyping, esFinishing, esQuitting
|
||||
|
||||
ScrollBehavior* = enum
|
||||
sbSingleScroll, sbAllScroll, sbWrap
|
||||
|
||||
LineEditor* = ref object
|
||||
# permanents
|
||||
keystrokes*: Event[int]
|
||||
events*: Event[JaleEvent]
|
||||
prompt*: string
|
||||
scrollMode*: ScrollBehavior
|
||||
|
||||
# permanent internals: none
|
||||
|
||||
|
@ -31,6 +35,7 @@ type
|
|||
state: EditorState
|
||||
rendered: int # how many lines were printed last full refresh
|
||||
forceRedraw: bool
|
||||
hscroll: int
|
||||
|
||||
# getter/setter sorts
|
||||
|
||||
|
@ -61,6 +66,8 @@ proc newLineEditor*: LineEditor =
|
|||
result.lastKeystroke = -1
|
||||
result.forceRedraw = false
|
||||
result.state = esOutside
|
||||
result.scrollMode = sbSingleScroll
|
||||
result.hscroll = 0
|
||||
|
||||
# priv/pub methods
|
||||
|
||||
|
@ -72,20 +79,31 @@ proc reset(editor: LineEditor) =
|
|||
editor.content = newMultiline()
|
||||
editor.lastKeystroke = -1
|
||||
editor.forceRedraw = false
|
||||
editor.hscroll = 0
|
||||
|
||||
proc render(editor: LineEditor, line: int = -1, hscroll: bool = true) =
|
||||
proc render(editor: LineEditor, line: int = -1) =
|
||||
## Assumes that the cursor is already on the right line then
|
||||
## proceeds to render the line-th line of the editor (if -1, will check
|
||||
## the y).
|
||||
var y = line
|
||||
if y == -1:
|
||||
y = editor.content.Y
|
||||
|
||||
|
||||
# the prompt's length is assumed to be always padded
|
||||
let prompt = if y == 0: editor.prompt else: " ".repeat(editor.prompt.len())
|
||||
renderLine(prompt, editor.content.getLine(y), 0)
|
||||
let content = editor.content.getLine(y)
|
||||
|
||||
if editor.scrollMode == sbAllScroll or
|
||||
(editor.scrollMode == sbSingleScroll and y == editor.content.Y):
|
||||
renderLine(prompt, content, editor.hscroll)
|
||||
else:
|
||||
renderLine(prompt, content, 0)
|
||||
|
||||
proc fullRender(editor: LineEditor) =
|
||||
# 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(i)
|
||||
if i < editor.rendered:
|
||||
cursorDown(1)
|
||||
else:
|
||||
|
@ -118,7 +136,7 @@ proc read*(editor: LineEditor): string =
|
|||
while editor.state == esTyping:
|
||||
|
||||
# refresh current line every time
|
||||
setCursorXPos(editor.content.X + editor.prompt.len())
|
||||
setCursorXPos(editor.content.X - editor.hscroll + editor.prompt.len())
|
||||
# get key (with escapes)
|
||||
let key = getKey()
|
||||
# record y pos
|
||||
|
@ -127,6 +145,20 @@ proc read*(editor: LineEditor): string =
|
|||
editor.lastKeystroke = key
|
||||
editor.keystrokes.call(key)
|
||||
editor.events.call(jeKeypress)
|
||||
# autoscroll horizontally based on current scroll and x pos
|
||||
|
||||
# last x rendered
|
||||
let lastX = terminalWidth() - editor.prompt.len() + editor.hscroll - 1
|
||||
# first x rendered
|
||||
let firstX = editor.hscroll
|
||||
|
||||
# x squished into boundaries
|
||||
let boundX = min(max(firstX, editor.content.X), lastX)
|
||||
if editor.content.X != boundX:
|
||||
editor.hscroll += editor.content.X - boundX
|
||||
if editor.scrollMode == sbAllScroll:
|
||||
editor.forceRedraw = true
|
||||
|
||||
# redraw everything if y changed
|
||||
if editor.forceRedraw or preY != editor.content.Y:
|
||||
# move to the top
|
||||
|
|
|
@ -5,16 +5,18 @@
|
|||
import strutils
|
||||
import terminal
|
||||
|
||||
proc renderLine*(prompt: string, content: string, hscroll: int = 0) =
|
||||
proc renderLine*(prompt: string, text: string, hscroll: int = 0) =
|
||||
eraseLine()
|
||||
setCursorXPos(0)
|
||||
var content = prompt & content
|
||||
if content.len() < terminalWidth():
|
||||
content &= " ".repeat(terminalWidth() - content.len() - 1)
|
||||
if content.len() > terminalWidth():
|
||||
var lower = hscroll
|
||||
var upper = hscroll + terminalWidth() - 1
|
||||
if upper > content.high():
|
||||
upper = content.high()
|
||||
content = content[lower..upper]
|
||||
write stdout, content
|
||||
var lower = hscroll
|
||||
var upper = hscroll + terminalWidth() - prompt.len() - 1
|
||||
if upper > text.high():
|
||||
upper = text.high()
|
||||
if lower < -1:
|
||||
raise newException(Defect, "negative hscroll submitted to renderLine")
|
||||
if lower > text.high():
|
||||
write stdout, prompt
|
||||
else:
|
||||
let content = prompt & text[lower..upper]
|
||||
write stdout, content
|
||||
|
||||
|
|
Loading…
Reference in New Issue