mirror of https://github.com/japl-lang/jale.git
parent
c913d4657d
commit
ed00e87415
|
@ -1,3 +1,4 @@
|
|||
examples/interactive
|
||||
examples/editor
|
||||
examples/interactive_basic
|
||||
examples/interactive_history
|
||||
getkey
|
||||
|
|
19
editor.nim
19
editor.nim
|
@ -13,6 +13,9 @@ type
|
|||
JaleEvent* = enum
|
||||
jeKeypress, jeQuit, jeFinish, jePreRead, jePostRead
|
||||
|
||||
EditorState = enum
|
||||
esOutside, esTyping, esFinishing, esQuitting
|
||||
|
||||
LineEditor* = ref object
|
||||
# permanents
|
||||
keystrokes*: Event[int]
|
||||
|
@ -25,22 +28,22 @@ type
|
|||
content*: Multiline
|
||||
lastKeystroke*: int
|
||||
# per-read internals
|
||||
finished: bool
|
||||
state: EditorState
|
||||
rendered: int # how many lines were printed last full refresh
|
||||
forceRedraw: bool
|
||||
|
||||
# getter/setter sorts
|
||||
|
||||
proc unfinish*(le: LineEditor) =
|
||||
le.finished = false
|
||||
le.state = esTyping
|
||||
|
||||
proc finish*(le: LineEditor) =
|
||||
le.finished = true
|
||||
le.state = esFinishing
|
||||
# can be overwritten to false, inside the event
|
||||
le.events.call(jeFinish)
|
||||
|
||||
proc quit*(le: LineEditor) =
|
||||
le.finished = true
|
||||
le.state = esQuitting
|
||||
le.events.call(jeQuit)
|
||||
|
||||
proc forceRedraw*(le: LineEditor) =
|
||||
|
@ -57,11 +60,14 @@ proc newLineEditor*: LineEditor =
|
|||
result.rendered = 0
|
||||
result.lastKeystroke = -1
|
||||
result.forceRedraw = false
|
||||
result.state = esOutside
|
||||
|
||||
# priv/pub methods
|
||||
|
||||
proc reset(editor: LineEditor) =
|
||||
editor.unfinish()
|
||||
## Resets state to outside, resets internal rendering details
|
||||
## resets last keystroke, creates new contents
|
||||
editor.state = esOutside
|
||||
editor.rendered = 0
|
||||
editor.content = newMultiline()
|
||||
editor.lastKeystroke = -1
|
||||
|
@ -114,12 +120,13 @@ proc moveCursorToEnd(editor: LineEditor) =
|
|||
|
||||
proc read*(editor: LineEditor): string =
|
||||
|
||||
editor.state = esTyping
|
||||
editor.events.call(jePreRead)
|
||||
|
||||
# starts at the top, full render moves it into the right y
|
||||
editor.fullRender()
|
||||
|
||||
while not editor.finished:
|
||||
while editor.state == esTyping:
|
||||
|
||||
# refresh current line every time
|
||||
editor.render()
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import ../plugin/defaults
|
||||
import ../plugin/history
|
||||
import ../plugin/editor_history
|
||||
import ../editor
|
||||
import ../strutils
|
||||
import ../templates
|
||||
|
||||
var keep = true
|
||||
|
||||
let e = newLineEditor()
|
||||
|
||||
e.bindEvent(jeQuit):
|
||||
keep = false
|
||||
|
||||
e.prompt = "> "
|
||||
e.populateDefaults()
|
||||
let h = e.plugHistory()
|
||||
e.bindHistory(h)
|
||||
|
||||
while keep:
|
||||
let input = e.read()
|
||||
echo "output:<" & input.replace("\n", "\\n") & ">"
|
||||
|
|
@ -1,5 +1,55 @@
|
|||
import history
|
||||
import ../editor
|
||||
import ../multiline
|
||||
import ../templates
|
||||
|
||||
import options
|
||||
|
||||
proc plugHistory*(ed: LineEditor): History =
|
||||
# adds hooks to events
|
||||
# after reading finished, it adds to history
|
||||
# before reading, it adds the temporary input to the history
|
||||
let hist = newHistory()
|
||||
ed.bindEvent(jeFinish):
|
||||
hist.clean()
|
||||
hist.newEntry(ed.content)
|
||||
|
||||
ed.bindEvent(jePreRead):
|
||||
hist.newEntry(ed.content, temp = true)
|
||||
discard hist.toEnd()
|
||||
|
||||
return hist
|
||||
|
||||
|
||||
proc bindHistory*(ed: LineEditor, h: History, useShift: bool = false) =
|
||||
## Adds history keybindings to editor (up, down, pg up/down)
|
||||
## Works with the history provided
|
||||
## if useShift is true, then the up/down keys and page up/down
|
||||
## will remain free, and shift+up/down and ctrl+pg up/down
|
||||
## will be used
|
||||
|
||||
let upkey = if useShift: "shiftup" else: "up"
|
||||
let downkey = if useShift: "shiftdown" else: "down"
|
||||
let homekey = if useShift: "ctrlpageup" else: "pageup"
|
||||
let endkey = if useShift: "ctrlpagedown" else: "pagedown"
|
||||
|
||||
ed.bindKey(upkey):
|
||||
let res = h.delta(-1)
|
||||
if res.isSome():
|
||||
ed.content = res.get()
|
||||
|
||||
ed.bindKey(downkey):
|
||||
let res = h.delta(1)
|
||||
if res.isSome():
|
||||
ed.content = res.get()
|
||||
|
||||
ed.bindKey(homekey):
|
||||
let res = h.toStart()
|
||||
if res.isSome():
|
||||
ed.content = res.get()
|
||||
|
||||
ed.bindKey(endKey):
|
||||
let res = h.toStart()
|
||||
if res.isSome():
|
||||
ed.content = res.get()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import ../multiline
|
||||
|
||||
import os
|
||||
import options
|
||||
|
||||
type HistoryElement* = ref object
|
||||
original*: Multiline
|
||||
|
@ -20,20 +21,38 @@ proc newHistory*: History =
|
|||
result.lowestTouchedIndex = 0
|
||||
result.elements = @[]
|
||||
|
||||
proc delta*(h: History, amt: int): Multiline =
|
||||
template newIndex(h: History): Option[Multiline] =
|
||||
if h.lowestTouchedIndex > h.index:
|
||||
h.lowestTouchedIndex = h.index
|
||||
|
||||
some(h.elements[h.index].current)
|
||||
|
||||
proc delta*(h: History, amt: int): Option[Multiline] =
|
||||
# move up/down in history and return reference to current
|
||||
# also update lowest touched index
|
||||
if h.elements.len() == 0:
|
||||
return none[Multiline]()
|
||||
|
||||
if h.index + amt <= 0:
|
||||
h.index = 0
|
||||
elif h.index + amt >= h.elements.high():
|
||||
h.index = h.elements.high()
|
||||
else:
|
||||
h.index += amt
|
||||
h.newIndex()
|
||||
|
||||
if h.lowestTouchedIndex > h.index:
|
||||
h.lowestTouchedIndex = h.index
|
||||
|
||||
h.elements[h.index]
|
||||
proc toEnd*(h: History): Option[Multiline] =
|
||||
if h.elements.len() == 0:
|
||||
return none[Multiline]()
|
||||
h.index = h.elements.high()
|
||||
h.newIndex()
|
||||
|
||||
proc toStart*(h: History): Option[Multiline] =
|
||||
if h.elements.len() == 0:
|
||||
return none[Multiline]()
|
||||
h.index = 0
|
||||
h.newIndex()
|
||||
|
||||
proc clean*(h: History) =
|
||||
# restore originals to current
|
||||
|
@ -49,7 +68,7 @@ proc clean*(h: History) =
|
|||
h.lowestTouchedIndex = h.elements.len()
|
||||
|
||||
proc newEntry*(h: History, ml: Multiline, temp: bool = false) =
|
||||
h.elements.add(History(original: ml, current: ml.copy(), temp: temp))
|
||||
h.elements.add(HistoryElement(original: ml, current: ml.copy(), temp: temp))
|
||||
|
||||
proc save*(h: History, path: string) =
|
||||
# discards currents and temps, only saves originals
|
||||
|
|
Loading…
Reference in New Issue