From 58280baabea3acf9e3662ae1df09c7da5806beb6 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 1 Aug 2023 10:33:26 +0100 Subject: [PATCH] Add syndex_card --- Tuprules.tup | 2 + src/syndex_card.nim | 138 +++++++++++++++++++++++++++++++++++++++++ syndicate_utils.nimble | 6 +- 3 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/syndex_card.nim diff --git a/Tuprules.tup b/Tuprules.tup index f902ead..b67953c 100644 --- a/Tuprules.tup +++ b/Tuprules.tup @@ -1,2 +1,4 @@ include ../syndicate-nim/depends.tup NIM_FLAGS += --path:$(TUP_CWD)/../syndicate-nim/src +NIM_FLAGS += --path:$(TUP_CWD)/../nimble/illwill +NIM_GROUPS += $(TUP_CWD)/../nimble/ diff --git a/src/syndex_card.nim b/src/syndex_card.nim new file mode 100644 index 0000000..e9d38ae --- /dev/null +++ b/src/syndex_card.nim @@ -0,0 +1,138 @@ +# 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 = + let pat = inputPattern() + + if stdout.is_a_TTY: + illwillInit() + hideCursor() + + discard bootDataspace("syndex_card") do (ds: Cap; turn: var Turn): + connect(turn, unixSocketPath(), envStep()) do (turn: var Turn; ds: Cap): + 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): + connect(turn, unixSocketPath(), envStep()) do (turn: var Turn; ds: Cap): + discard observe(turn, ds, pat, entity) + +main() diff --git a/syndicate_utils.nimble b/syndicate_utils.nimble index 14bf1e4..430f9d7 100644 --- a/syndicate_utils.nimble +++ b/syndicate_utils.nimble @@ -1,13 +1,13 @@ # Package -version = "20230726" +version = "20230801" author = "Emery Hemingway" description = "Utilites for Syndicated Actors and Synit" license = "unlicense" srcDir = "src" -bin = @["json_socket_translator", "json_translator", "msg", "net_mapper", "preserve_process_environment"] +bin = @["json_socket_translator", "json_translator", "msg", "net_mapper", "preserve_process_environment", "syndex_card"] # Dependencies -requires "nim >= 1.6.6", "syndicate >= 20230518" +requires "nim >= 1.6.6", "illwill", "syndicate >= 20230518"