jale-prod2/src/jale/editor.nim

119 lines
2.7 KiB
Nim

# editor.nim
import types/event
import types/multiline
import terminal
import keycodes
import sequtils
when defined(posix):
import posix
type
JaleState = enum
jsInactive, jsActive, jsFinishing, jsQuitting
HorizontalScrollBehavior* = enum
hsbSingleScroll, hsbAllScroll, hsbWrap
LineEditorObj* = object
# permanent across reads
evtTable*: EventTable
prompt*: string
horizontalScrollMode*: HorizontalScrollBehavior
# change across every read() call
content*: Multiline
lastKeystroke*: int # TODO potentially deprecate
state: JaleState
hscroll*: int
vscroll*: int
vmax: int # maximum amount of vertical screen space
# TODO remove the need for these through events
rendered*: int # how many lines were printed last full refresh
forceRedraw*: bool
LineEditor* = ref LineEditorObj
# weak list of references
var editors: seq[ptr LineEditorObj]
# constructors and related code
proc reset*(le: LineEditor) =
# called when read() is over
le.state = jsInactive
le.rendered = 0 # TODO deprecate
le.content = newMultiline()
le.lastKeystroke = -1 # TODO deprecate
le.forceRedraw = false # TODO deprecate
le.hscroll = 0
le.vscroll = 0
proc finalizer (inst: LineEditor) =
editors = editors.filterIt(cast[ptr LineEditorObj](inst) != it)
proc newLineEditor*: LineEditor =
new(result, finalizer)
result.reset()
result.evtTable = newEventTable()
result.prompt = ""
result.horizontalScrollMode = hsbSingleScroll
result.vmax = 0
editors.add(cast[ptr LineEditorObj](result))
# resize event firing
when defined(posix):
onSignal(28):
for ed in editors:
discard ed.evtTable.callRaw(jeResize, @[])
# getters/setters
proc getVmax*(le: LineEditor): int =
if le.vmax <= 0:
terminalHeight() + le.vmax
else:
le.vmax
proc setVmax*(le: LineEditor, val: int) =
le.vmax = val
# methods
proc unfinish*(le: LineEditor) =
le.state = jsActive
proc finish*(le: LineEditor) =
le.state = jsFinishing
discard le.evtTable.callRaw(jeFinish, @[])
proc quit*(le: LineEditor) =
le.state = jsQuitting
discard le.evtTable.callRaw(jeQuit, @[])
# TODO: deprecate
proc redraw*(le: LineEditor) =
le.forceRedraw = true
proc read*(le: LineEditor): string =
le.state = jsActive
discard le.evtTable.callRaw(jePreRead, @[])
while le.state == jsActive:
discard le.evtTable.callRaw(jePreKeypress, @[])
let key = getKey()
le.lastKeystroke = key # TODO deprecate
discard le.evtTable.callRaw(jeKeypress, @[JaleObject(kind: jkInt, intVal: key)])
discard le.evtTable.callRaw(jePostKeypress, @[])
discard le.evtTable.callRaw(jePostRead, @[])
if le.state == jsFinishing:
result = le.content.getContent()
le.reset()