From a959565fb5ccd9db1d3054617d7780cc33b3ff55 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 18 Mar 2022 19:22:31 -0500 Subject: [PATCH] New protocol and configuration from Tony The uri_matcher now makes a proper relay over stdio to the dataspace shared with xdg_open. Fix https://git.syndicate-lang.org/ehmry/xdg_open_ng/issues/3 --- README.md | 2 ++ protocol.prs | 8 +++----- src/protocol.nim | 28 ++++++++++++++++++---------- src/uri_runner.nim | 38 ++++++++++++++------------------------ src/xdg_open.nim | 8 +++----- uri_runner.pr | 13 +++++++------ xdg_open_ng.nimble | 2 +- 7 files changed, 48 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index e6d6460..a9426f8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ An `xdg-open` replacement that uses Syndicate and PCRE pattern matching to open There are two utilites, `uri_runner` and `xdg-open`; both expect to be able to connect to a shared Syndicate dataspace via a UNIX socket at `$SYNDICATE_SOCK` otherwise `$XDG_RUNTIME_DIR/dataspace`. The `xdg-open` component has no other configuration. The `uri_runner` component is intended to be managed by the [Syndicate server](https://git.syndicate-lang.org/syndicate-lang/syndicate-rs) thru which it receives configuration, see [uri_runner.pr](./uri_runner.pr) as an example. +The [protocol.nim](./src/protocol.nim) file is generated from the [protocol.prs](./protocol.prs) schema, a [Tupfile](https://gittup.org/tup/) file is provided to do this. + ## TODO - Pattern back-references in commands - Fallback commands? diff --git a/protocol.prs b/protocol.prs index 6ef2e2f..3d1b7bb 100644 --- a/protocol.prs +++ b/protocol.prs @@ -2,8 +2,6 @@ version 1 . XdgOpen = . -Action = [@pat string @cmd [string ...] ] . - -Attrs = { actions: [Action ...] } . - -UriRunnerConfig = . +UriRunnerConfig = ListenOn / ActionHandler . +ListenOn = . +ActionHandler = . diff --git a/src/protocol.nim b/src/protocol.nim index cba88b3..1316823 100644 --- a/src/protocol.nim +++ b/src/protocol.nim @@ -4,26 +4,34 @@ import type XdgOpen* {.preservesRecord: "xdg-open".} = object - `data`*: seq[string] + `uris`*: seq[string] - Attrs*[E] {.preservesDictionary.} = ref object - `actions`*: seq[Action] + UriRunnerConfigKind* {.pure.} = enum + `ListenOn`, `ActionHandler` + `UriRunnerConfig`*[E] {.preservesOr.} = ref object + case orKind*: UriRunnerConfigKind + of UriRunnerConfigKind.`ListenOn`: + `listenon`*: ListenOn[E] - UriRunnerConfig*[E] {.preservesRecord: "config".} = ref object - `attrs`*: Attrs[E] + of UriRunnerConfigKind.`ActionHandler`: + `actionhandler`*: ActionHandler - Action* {.preservesTuple.} = object + + ListenOn*[E] {.preservesRecord: "listen-on".} = ref object + `dataspace`*: Preserve[E] + + ActionHandler* {.preservesRecord: "action-handler".} = object `pat`*: string `cmd`*: seq[string] -proc `$`*[E](x: Attrs[E] | UriRunnerConfig[E]): string = +proc `$`*[E](x: UriRunnerConfig[E] | ListenOn[E]): string = `$`(toPreserve(x, E)) -proc encode*[E](x: Attrs[E] | UriRunnerConfig[E]): seq[byte] = +proc encode*[E](x: UriRunnerConfig[E] | ListenOn[E]): seq[byte] = encode(toPreserve(x, E)) -proc `$`*(x: XdgOpen | Action): string = +proc `$`*(x: XdgOpen | ActionHandler): string = `$`(toPreserve(x)) -proc encode*(x: XdgOpen | Action): seq[byte] = +proc encode*(x: XdgOpen | ActionHandler): seq[byte] = encode(toPreserve(x)) diff --git a/src/uri_runner.nim b/src/uri_runner.nim index 5c835b1..15ecd06 100644 --- a/src/uri_runner.nim +++ b/src/uri_runner.nim @@ -1,37 +1,27 @@ -# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway +# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway # SPDX-License-Identifier: Unlicense -import std/[asyncdispatch, deques, re, streams, strutils, os, osproc] +import std/[asyncdispatch, deques, re, streams, strutils, osproc] import preserves -import syndicate, syndicate/capabilities +import syndicate import ./protocol -proc unixSocketPath: string = - result = getEnv("SYNDICATE_SOCK") - if result == "": - result = getEnv("XDG_RUNTIME_DIR", "/run/user/1000") / "dataspace" - -proc mintCap: SturdyRef = - var key: array[16, byte] - mint(key, "syndicate") - -bootDataspace("main") do (ds: Ref; turn: var Turn): +bootDataspace("main") do (root: Ref; turn: var Turn): var actions: seq[tuple[regex: Regex; cmd: string; args: seq[string]]] children: Deque[Process] - connectStdio(ds, turn) + connectStdio(root, turn) - onPublish(turn, ds, ?UriRunnerConfig[Ref]) do (cfg: seq[Action]): - actions.setLen 0 - for act in cfg: - if act.cmd.len < 2: - stderr.writeLine "ignoring ", act - else: - actions.add (re(act.pat, {reIgnoreCase, reStudy}), act.cmd[0], act.cmd[1..act.cmd.high]) - stderr.writeLine "actions updated" + onPublish(turn, root, ?ActionHandler) do (pat: string; cmd: seq[string]): + # TODO: during + if cmd.len < 2: + stderr.writeLine "ignoring ", $cmd, " for ", pat + else: + var act = (re(pat, {reIgnoreCase, reStudy}), cmd[0], cmd[1..cmd.high],) + actions.add act - connectUnix(turn, unixSocketPath(), mintCap()) do (turn: var Turn; a: Assertion) -> TurnAction: + onPublish(turn, root, ?ListenOn[Ref]) do (a: Assertion): let ds = unembed a onMessage(turn, ds, ?XdgOpen) do (uris: seq[string]): while children.len > 0 and not children.peekFirst.running: @@ -52,6 +42,6 @@ bootDataspace("main") do (ds: Ref; turn: var Turn): command = act.cmd, args = args, options = {}) children.addLast child if not matched: - stderr.writeLine "no patterns matched for ", uri + stderr.writeLine "no actions matched for ", uri runForever() diff --git a/src/xdg_open.nim b/src/xdg_open.nim index 61210df..ed30d8f 100644 --- a/src/xdg_open.nim +++ b/src/xdg_open.nim @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway +# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[asyncdispatch, os] @@ -15,14 +15,12 @@ proc mintCap: SturdyRef = var key: array[16, byte] mint(key, "syndicate") -type XdgOpen {.preservesRecord: "xdg-open".} = object - args: seq[string] - bootDataspace("main") do (ds: Ref; turn: var Turn): let mainFacet = turn.facet connectUnix(turn, unixSocketPath(), mintCap()) do (turn: var Turn; a: Assertion) -> TurnAction: let ds = unembed a - message(turn, ds, XdgOpen(args: commandLineParams())) + message(turn, ds, XdgOpen(uris: commandLineParams())) + stop(turn, mainFacet) for i in 0..7: poll(20) # A hack to exit diff --git a/uri_runner.pr b/uri_runner.pr index 0bf5736..7bfbc8b 100644 --- a/uri_runner.pr +++ b/uri_runner.pr @@ -11,10 +11,11 @@ let ?root_ds = dataspace }> ? ?cap> [ - $cap + $cap [ + + + + + + ] ] diff --git a/xdg_open_ng.nimble b/xdg_open_ng.nimble index bdb346a..6a2f6ae 100644 --- a/xdg_open_ng.nimble +++ b/xdg_open_ng.nimble @@ -1,6 +1,6 @@ # Package -version = "0.1.0" +version = "0.2.0" author = "Emery" description = "A better xdg-open" license = "Unlicense"