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.prompt = ""
|
||||||
e.populateDefaults(enterSubmits = false, ctrlForVerticalMove = false)
|
e.populateDefaults(enterSubmits = false, ctrlForVerticalMove = false)
|
||||||
|
e.scrollMode = sbAllScroll
|
||||||
let result = e.read()
|
let result = e.read()
|
||||||
if save and paramCount() > 0:
|
if save and paramCount() > 0:
|
||||||
writeFile(paramStr(1), result)
|
writeFile(paramStr(1), result)
|
||||||
|
|
|
@ -16,11 +16,15 @@ type
|
||||||
EditorState = enum
|
EditorState = enum
|
||||||
esOutside, esTyping, esFinishing, esQuitting
|
esOutside, esTyping, esFinishing, esQuitting
|
||||||
|
|
||||||
|
ScrollBehavior* = enum
|
||||||
|
sbSingleScroll, sbAllScroll, sbWrap
|
||||||
|
|
||||||
LineEditor* = ref object
|
LineEditor* = ref object
|
||||||
# permanents
|
# permanents
|
||||||
keystrokes*: Event[int]
|
keystrokes*: Event[int]
|
||||||
events*: Event[JaleEvent]
|
events*: Event[JaleEvent]
|
||||||
prompt*: string
|
prompt*: string
|
||||||
|
scrollMode*: ScrollBehavior
|
||||||
|
|
||||||
# permanent internals: none
|
# permanent internals: none
|
||||||
|
|
||||||
|
@ -31,6 +35,7 @@ type
|
||||||
state: EditorState
|
state: EditorState
|
||||||
rendered: int # how many lines were printed last full refresh
|
rendered: int # how many lines were printed last full refresh
|
||||||
forceRedraw: bool
|
forceRedraw: bool
|
||||||
|
hscroll: int
|
||||||
|
|
||||||
# getter/setter sorts
|
# getter/setter sorts
|
||||||
|
|
||||||
|
@ -61,6 +66,8 @@ proc newLineEditor*: LineEditor =
|
||||||
result.lastKeystroke = -1
|
result.lastKeystroke = -1
|
||||||
result.forceRedraw = false
|
result.forceRedraw = false
|
||||||
result.state = esOutside
|
result.state = esOutside
|
||||||
|
result.scrollMode = sbSingleScroll
|
||||||
|
result.hscroll = 0
|
||||||
|
|
||||||
# priv/pub methods
|
# priv/pub methods
|
||||||
|
|
||||||
|
@ -72,20 +79,31 @@ proc reset(editor: LineEditor) =
|
||||||
editor.content = newMultiline()
|
editor.content = newMultiline()
|
||||||
editor.lastKeystroke = -1
|
editor.lastKeystroke = -1
|
||||||
editor.forceRedraw = false
|
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
|
var y = line
|
||||||
if y == -1:
|
if y == -1:
|
||||||
y = editor.content.Y
|
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())
|
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) =
|
proc fullRender(editor: LineEditor) =
|
||||||
# from the top cursor pos, it draws the entire multiline prompt, then
|
# from the top cursor pos, it draws the entire multiline prompt, then
|
||||||
# moves cursor to current y
|
# moves cursor to current y
|
||||||
for i in countup(0, editor.content.high()):
|
for i in countup(0, editor.content.high()):
|
||||||
editor.render(i, false)
|
editor.render(i)
|
||||||
if i < editor.rendered:
|
if i < editor.rendered:
|
||||||
cursorDown(1)
|
cursorDown(1)
|
||||||
else:
|
else:
|
||||||
|
@ -118,7 +136,7 @@ proc read*(editor: LineEditor): string =
|
||||||
while editor.state == esTyping:
|
while editor.state == esTyping:
|
||||||
|
|
||||||
# refresh current line every time
|
# 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)
|
# get key (with escapes)
|
||||||
let key = getKey()
|
let key = getKey()
|
||||||
# record y pos
|
# record y pos
|
||||||
|
@ -127,6 +145,20 @@ proc read*(editor: LineEditor): string =
|
||||||
editor.lastKeystroke = key
|
editor.lastKeystroke = key
|
||||||
editor.keystrokes.call(key)
|
editor.keystrokes.call(key)
|
||||||
editor.events.call(jeKeypress)
|
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
|
# redraw everything if y changed
|
||||||
if editor.forceRedraw or preY != editor.content.Y:
|
if editor.forceRedraw or preY != editor.content.Y:
|
||||||
# move to the top
|
# move to the top
|
||||||
|
|
|
@ -5,16 +5,18 @@
|
||||||
import strutils
|
import strutils
|
||||||
import terminal
|
import terminal
|
||||||
|
|
||||||
proc renderLine*(prompt: string, content: string, hscroll: int = 0) =
|
proc renderLine*(prompt: string, text: string, hscroll: int = 0) =
|
||||||
|
eraseLine()
|
||||||
setCursorXPos(0)
|
setCursorXPos(0)
|
||||||
var content = prompt & content
|
var lower = hscroll
|
||||||
if content.len() < terminalWidth():
|
var upper = hscroll + terminalWidth() - prompt.len() - 1
|
||||||
content &= " ".repeat(terminalWidth() - content.len() - 1)
|
if upper > text.high():
|
||||||
if content.len() > terminalWidth():
|
upper = text.high()
|
||||||
var lower = hscroll
|
if lower < -1:
|
||||||
var upper = hscroll + terminalWidth() - 1
|
raise newException(Defect, "negative hscroll submitted to renderLine")
|
||||||
if upper > content.high():
|
if lower > text.high():
|
||||||
upper = content.high()
|
write stdout, prompt
|
||||||
content = content[lower..upper]
|
else:
|
||||||
write stdout, content
|
let content = prompt & text[lower..upper]
|
||||||
|
write stdout, content
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue