2023-08-01 09:33:26 +00:00
|
|
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
|
|
|
|
## This was all Tony's idea, except for the silly name.
|
|
|
|
|
|
|
|
import std/[asyncdispatch, os, terminal]
|
|
|
|
import preserves
|
2023-10-21 18:03:11 +00:00
|
|
|
import syndicate, syndicate/[durings, relays]
|
2023-08-01 09:33:26 +00:00
|
|
|
import illwill
|
|
|
|
|
|
|
|
proc exitProc() {.noconv.} =
|
|
|
|
illwillDeinit()
|
|
|
|
showCursor()
|
|
|
|
quit QuitSuccess
|
|
|
|
|
|
|
|
setControlCHook(exitProc)
|
|
|
|
|
2023-12-25 23:11:54 +00:00
|
|
|
proc parsePattern(pr: Value): Pattern =
|
2023-08-01 09:33:26 +00:00
|
|
|
let
|
2023-12-25 23:11:54 +00:00
|
|
|
dropSigil = initRecord("lit", "_".toSymbol)
|
|
|
|
grabSigil = initRecord("lit", "?".toSymbol)
|
|
|
|
var pr = grab(pr).toPreserves
|
|
|
|
apply(pr) do (pr: var Value):
|
2023-08-01 09:33:26 +00:00
|
|
|
if pr == dropSigil:
|
2023-12-25 23:11:54 +00:00
|
|
|
pr = initRecord("_")
|
2023-08-01 09:33:26 +00:00
|
|
|
elif pr == grabSigil:
|
2023-12-25 23:11:54 +00:00
|
|
|
pr = initRecord("bind", initRecord("_"))
|
|
|
|
doAssert result.fromPreserves(pr)
|
2023-08-01 09:33:26 +00:00
|
|
|
|
|
|
|
proc inputPattern: Pattern =
|
|
|
|
var args = commandLineParams()
|
|
|
|
if args.len != 1:
|
|
|
|
quit "expected a single pattern argument"
|
|
|
|
else:
|
|
|
|
var input = pop args
|
|
|
|
if input == "":
|
|
|
|
quit "expected Preserves Pattern on stdin"
|
|
|
|
else:
|
2023-12-25 23:11:54 +00:00
|
|
|
var pr: Value
|
|
|
|
try: pr = decodePreserves(input)
|
2023-08-01 09:33:26 +00:00
|
|
|
except ValueError: discard
|
2023-12-25 23:11:54 +00:00
|
|
|
try: pr = parsePreserves(input)
|
2023-08-01 09:33:26 +00:00
|
|
|
except ValueError: discard
|
|
|
|
if pr.isFalse:
|
|
|
|
quit "failed to parse Preserves argument"
|
|
|
|
result = parsePattern(pr)
|
|
|
|
|
|
|
|
type TermEntity {.final.} = ref object of Entity
|
|
|
|
pattern: Pattern
|
2023-12-25 23:11:54 +00:00
|
|
|
value: Value
|
2023-08-01 09:33:26 +00:00
|
|
|
|
|
|
|
method publish(te: TermEntity; turn: var Turn; v: AssertionRef; h: Handle) =
|
|
|
|
te.value = v.value
|
|
|
|
var termBuf = newTerminalBuffer(terminalWidth(), terminalHeight())
|
|
|
|
var y = 1
|
|
|
|
termBuf.write(1, y, $te.pattern, styleBright)
|
|
|
|
inc(y)
|
|
|
|
termBuf.drawHorizLine(0, termBuf.width(), y)
|
|
|
|
inc(y)
|
|
|
|
termBuf.write(0, y, $h, styleBright)
|
|
|
|
for i, e in te.value.sequence:
|
|
|
|
inc(y)
|
|
|
|
termBuf.write(1, y, $e)
|
|
|
|
termBuf.display()
|
|
|
|
|
|
|
|
method retract(te: TermEntity; turn: var Turn; h: Handle) =
|
|
|
|
var termBuf = newTerminalBuffer(terminalWidth(), terminalHeight())
|
|
|
|
var y = 1
|
|
|
|
termBuf.write(1, y, $te.pattern, styleDim)
|
|
|
|
inc y
|
|
|
|
termBuf.drawHorizLine(0, termBuf.width(), y, true)
|
|
|
|
inc(y)
|
|
|
|
termBuf.write(0, y, $h, styleBright)
|
|
|
|
if te.value.isSequence:
|
|
|
|
for i, e in te.value.sequence:
|
|
|
|
inc(y)
|
|
|
|
termBuf.write(1, y, $e)
|
|
|
|
else:
|
|
|
|
inc(y)
|
|
|
|
termBuf.write(1, y, $te.value)
|
|
|
|
termBuf.display()
|
|
|
|
|
|
|
|
type DumpEntity {.final.} = ref object of Entity
|
|
|
|
discard
|
|
|
|
|
|
|
|
method publish(dump: DumpEntity; turn: var Turn; ass: AssertionRef; h: Handle) =
|
|
|
|
stdout.writeLine($ass.value)
|
|
|
|
stdout.flushFile()
|
|
|
|
|
|
|
|
method message*(dump: DumpEntity; turn: var Turn; ass: AssertionRef) =
|
|
|
|
stdout.writeLine($ass.value)
|
|
|
|
stdout.flushFile()
|
|
|
|
|
2023-10-19 17:24:28 +00:00
|
|
|
proc exit {.noconv.} =
|
2023-08-01 09:33:26 +00:00
|
|
|
illwillDeinit()
|
|
|
|
showCursor()
|
|
|
|
quit()
|
|
|
|
|
2023-10-19 17:24:28 +00:00
|
|
|
setControlCHook(exit)
|
|
|
|
|
2023-08-01 09:33:26 +00:00
|
|
|
proc main =
|
2023-08-16 09:57:14 +00:00
|
|
|
let
|
2023-10-21 18:03:11 +00:00
|
|
|
route = envRoute()
|
2023-08-16 09:57:14 +00:00
|
|
|
pat = inputPattern()
|
2023-08-01 09:33:26 +00:00
|
|
|
|
|
|
|
if stdout.is_a_TTY:
|
|
|
|
illwillInit()
|
|
|
|
hideCursor()
|
|
|
|
|
2023-10-21 18:03:11 +00:00
|
|
|
discard bootDataspace("syndex_card") do (turn: var Turn; root: Cap):
|
|
|
|
resolve(turn, root, route) do (turn: var Turn; ds: Cap):
|
2023-08-01 09:33:26 +00:00
|
|
|
var termBuf = newTerminalBuffer(terminalWidth(), terminalHeight())
|
|
|
|
termBuf.write(1, 1, $pat, styleBright)
|
|
|
|
termBuf.drawHorizLine(1, termBuf.width(), 2)
|
|
|
|
termBuf.display()
|
|
|
|
|
|
|
|
discard observe(turn, ds, pat, TermEntity(pattern: pat))
|
|
|
|
|
|
|
|
while true:
|
|
|
|
try: poll()
|
|
|
|
except CatchableError:
|
|
|
|
illwillDeinit()
|
|
|
|
showCursor()
|
|
|
|
quit getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
else:
|
|
|
|
let entity = DumpEntity()
|
|
|
|
runActor("syndex_card") do (root: Cap; turn: var Turn):
|
2023-10-21 18:03:11 +00:00
|
|
|
resolve(turn, root, route) do (turn: var Turn; ds: Cap):
|
2023-08-01 09:33:26 +00:00
|
|
|
discard observe(turn, ds, pat, entity)
|
|
|
|
|
|
|
|
main()
|