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
|
|
|
|
import syndicate, syndicate/[actors, capabilities, dataspaces, durings, patterns]
|
|
|
|
import illwill
|
|
|
|
|
|
|
|
proc unixSocketPath: Unix =
|
|
|
|
result.path = getEnv("SYNDICATE_SOCK")
|
|
|
|
if result.path == "":
|
|
|
|
result.path = getEnv("XDG_RUNTIME_DIR", "/run/user/1000") / "dataspace"
|
|
|
|
|
|
|
|
proc envStep: Assertion =
|
|
|
|
var s = getEnv("SYNDICATE_STEP")
|
|
|
|
if s != "": parsePreserves(s, Cap)
|
|
|
|
else: capabilities.mint().toPreserve(Cap)
|
|
|
|
|
|
|
|
proc exitProc() {.noconv.} =
|
|
|
|
illwillDeinit()
|
|
|
|
showCursor()
|
|
|
|
quit QuitSuccess
|
|
|
|
|
|
|
|
setControlCHook(exitProc)
|
|
|
|
|
|
|
|
proc parsePattern(pr: Assertion): Pattern =
|
|
|
|
let
|
|
|
|
dropSigil = initRecord("lit", "_".toSymbol(Cap))
|
|
|
|
grabSigil = initRecord("lit", "?".toSymbol(Cap))
|
|
|
|
var pr = grab(pr).toPreserve(Cap)
|
|
|
|
apply(pr) do (pr: var Assertion):
|
|
|
|
if pr == dropSigil:
|
|
|
|
pr = initRecord[Cap]("_")
|
|
|
|
elif pr == grabSigil:
|
|
|
|
pr = initRecord("bind", initRecord[Cap]("_"))
|
|
|
|
doAssert result.fromPreserve(pr)
|
|
|
|
|
|
|
|
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:
|
|
|
|
var pr: Assertion
|
|
|
|
try: pr = decodePreserves(input, Cap)
|
|
|
|
except ValueError: discard
|
|
|
|
try: pr = parsePreserves(input, Cap)
|
|
|
|
except ValueError: discard
|
|
|
|
if pr.isFalse:
|
|
|
|
quit "failed to parse Preserves argument"
|
|
|
|
result = parsePattern(pr)
|
|
|
|
|
|
|
|
type TermEntity {.final.} = ref object of Entity
|
|
|
|
pattern: Pattern
|
|
|
|
value: Assertion
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
setControlCHook:
|
|
|
|
illwillDeinit()
|
|
|
|
showCursor()
|
|
|
|
quit()
|
|
|
|
|
|
|
|
proc main =
|
2023-08-16 09:57:14 +00:00
|
|
|
let
|
|
|
|
unix = unixSocketPath()
|
|
|
|
step = envStep()
|
|
|
|
pat = inputPattern()
|
2023-08-01 09:33:26 +00:00
|
|
|
|
|
|
|
if stdout.is_a_TTY:
|
|
|
|
illwillInit()
|
|
|
|
hideCursor()
|
|
|
|
|
|
|
|
discard bootDataspace("syndex_card") do (ds: Cap; turn: var Turn):
|
2023-08-16 09:57:14 +00:00
|
|
|
connect(turn, unix, step) 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-08-16 09:57:14 +00:00
|
|
|
connect(turn, unix, step) do (turn: var Turn; ds: Cap):
|
2023-08-01 09:33:26 +00:00
|
|
|
discard observe(turn, ds, pat, entity)
|
|
|
|
|
|
|
|
main()
|