From 509970a2d2517de4f11468aa977a47a9c3cda623 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 30 Jun 2023 15:26:22 +0100 Subject: [PATCH] Rename to "open", decompose URIs in assertions --- README.md | 6 ++--- handlers-example.pr | 6 +++-- protocol.prs | 8 +++++- src/Tupfile | 7 ++--- src/common.nim | 48 ++++++++++++++++++++++++++++++++++ src/{xdg_open.nim => open.nim} | 18 ++++++------- src/protocol.nim | 22 +++++++++++++--- src/uri_runner.nim | 13 +++------ syndicated_open.nimble | 13 +++++++++ uri_runner.pr | 8 +++--- xdg_open_ng.nimble | 13 --------- 11 files changed, 113 insertions(+), 49 deletions(-) create mode 100644 src/common.nim rename src/{xdg_open.nim => open.nim} (60%) create mode 100644 syndicated_open.nimble delete mode 100644 xdg_open_ng.nimble diff --git a/README.md b/README.md index d8a8b9b..ca3f72b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# xdg-open-ng +# Syndicated Open -An [xdg-open](https://portland.freedesktop.org/doc/xdg-open.html) replacement that uses [Syndicate](http://syndicate-lang.org/) and PCRE pattern matching to open URIs. +An [open command](https://en.wikipedia.org/wiki/Open_(process)) implementation that uses [Syndicate](http://syndicate-lang.org/) and PCRE pattern matching to open URIs. -There are two utilites, `xdg-open` and `uri_runner`. The former connects to a shared Syndicate dataspace via a UNIX socket at `$SYNDICATE_SOCK` otherwise `$XDG_RUNTIME_DIR/dataspace` and 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. +There are two utilites, `open` and `uri_runner`. The former connects to a shared Syndicate dataspace via a UNIX socket at `$SYNDICATE_SOCK` otherwise `$XDG_RUNTIME_DIR/dataspace` and 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. Matching patterns to actions is done with `action-handler` records: ```preserves diff --git a/handlers-example.pr b/handlers-example.pr index 3aaf6da..9b97c65 100644 --- a/handlers-example.pr +++ b/handlers-example.pr @@ -16,9 +16,11 @@ > - > + > + > ] ; when mpv is available send it commands directly diff --git a/protocol.prs b/protocol.prs index 4960834..0c30b8f 100644 --- a/protocol.prs +++ b/protocol.prs @@ -1,6 +1,12 @@ version 1 . -XdgOpen = . +Authority = [ @username any @password any @host any @port any ] . + +; Uniform Resource Identifier https://datatracker.ietf.org/doc/html/rfc3986 +Uri = . + +; Broadcast this to open a URI. +Open = . UriRunnerConfig = { handlerspace: #!any diff --git a/src/Tupfile b/src/Tupfile index 861ac6e..c2981cb 100644 --- a/src/Tupfile +++ b/src/Tupfile @@ -1,5 +1,6 @@ include_rules -: foreach ../*.prs |> !preserves_schema_nim |> | {schema} -: uri_runner.nim | $(SYNDICATE_PROTOCOL) {schema} |> !nim_bin |> {bin} -: xdg_open.nim | $(SYNDICATE_PROTOCOL) {schema} |> !nim_bin |> $(BIN_DIR)/xdg-open {bin} +: foreach ../*.prs |> !preserves_schema_nim |> | {common} +: common.nim |> !nim_check |> {common} +: uri_runner.nim | $(SYNDICATE_PROTOCOL) {common} |> !nim_bin |> {bin} +: open.nim | $(SYNDICATE_PROTOCOL) {common} |> !nim_bin |> {bin} : foreach {bin} |> !assert_built |> diff --git a/src/common.nim b/src/common.nim new file mode 100644 index 0000000..eb0639f --- /dev/null +++ b/src/common.nim @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: ☭ Emery Hemingway +# SPDX-License-Identifier: Unlicense + +import std/uri +import preserves + +proc toPreserveOrNull(s: string; E: typedesc): Preserve[E] = + if s != "": result = toPreserve(s, E) + +proc toPreserveHook*(u: Uri; E: typedesc): Preserve[E] = + ## Best-effort preservation of the `Uri` type. + runnableExamples: + from std/unittest import check + import std/uri + import preserves + var u = parseUri"https://bidstonobservatory.org" + check $(u.toPreserve) == """""" + initRecord("uri", + u.scheme.toPreserve(E), + toPreserve([ + u.username.toPreserveOrNull(E), + u.password.toPreserveOrNull(E), + u.hostname.toPreserveOrNull(E), + u.port.toPreserveOrNull(E), + ]), + u.path.toPreserveOrNull(E), + u.query.toPreserveOrNull(E), + u.anchor.toPreserveOrNull(E), + ) + +proc fromPreserveHook*[E](u: var Uri; pr: Preserve[E]): bool = + ## Best-effort preservation of the `Uri` type. + runnableExamples: + import std/uri + import preserves + var u: Uri + doAssert fromPreserveHook(u, parsePreserves"""""") + if pr.isRecord("uri", 5): + result = fromPreserve(u.scheme, pr[0]) + if result: + if pr[1].isSequence and pr[1].sequence.len == 4: + discard fromPreserve(u.username, pr[1][0]) + discard fromPreserve(u.password, pr[1][1]) + discard fromPreserve(u.hostname, pr[1][2]) + discard fromPreserve(u.port, pr[1][3]) + discard fromPreserve(u.path, pr[2]) + discard fromPreserve(u.query, pr[3]) + discard fromPreserve(u.anchor, pr[4]) diff --git a/src/xdg_open.nim b/src/open.nim similarity index 60% rename from src/xdg_open.nim rename to src/open.nim index ac5f073..4b161c5 100644 --- a/src/xdg_open.nim +++ b/src/open.nim @@ -1,19 +1,17 @@ # SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense -## Facsimile of xdg-open from xdg-utils. -## https://portland.freedesktop.org/doc/xdg-open.html - -import std/[asyncdispatch, os] +import std/[asyncdispatch, os, uri] import preserves, syndicate, syndicate/capabilities -import ./protocol +import ./protocol, ./common proc publishUri(turn: var Turn; ds: Ref) = for arg in commandLineParams(): - var xo = XdgOpen(uri: arg) - if fileExists(xo.uri): - xo.uri = "file://" & absolutePath(arg) - message(turn, ds, xo) + if fileExists(arg): + message(turn, ds, Open(uri: protocol.Uri( + scheme: "file", path: arg.absolutePath.toPreserve))) + else: + message(turn, ds, initRecord("open", arg.parseUri.toPreserve)) stop(turn) proc unixSocketPath: Unix = @@ -21,7 +19,7 @@ proc unixSocketPath: Unix = if result.path == "": result.path = getEnv("XDG_RUNTIME_DIR", "/run/user/1000") / "dataspace" -discard bootDataspace("xdg-open") do (root: Ref; turn: var Turn): +discard bootDataspace("open") do (root: Ref; turn: var Turn): let cap = mint().toPreserve(Ref) connect(turn, unixSocketPath(), cap, publishUri) diff --git a/src/protocol.nim b/src/protocol.nim index c7313e3..86465eb 100644 --- a/src/protocol.nim +++ b/src/protocol.nim @@ -3,20 +3,34 @@ import preserves type - XdgOpen* {.preservesRecord: "xdg-open".} = object - `uri`*: string + Open* {.preservesRecord: "open".} = object + `uri`*: Uri UriRunnerConfig* {.preservesDictionary.} = object `handlerspace`* {.preservesEmbedded.}: Preserve[void] `urispace`* {.preservesEmbedded.}: Preserve[void] + Authority* {.preservesTuple.} = object + `username`*: Preserve[void] + `password`*: Preserve[void] + `host`*: Preserve[void] + `port`*: Preserve[void] + + Uri* {.preservesRecord: "uri".} = object + `scheme`*: string + `auth`*: Authority + `path`*: Preserve[void] + `query`*: Preserve[void] + `fragment`*: Preserve[void] + ActionHandler* {.preservesRecord: "action-handler".} = object `pat`*: string `entity`* {.preservesEmbedded.}: Preserve[void] `action`*: Preserve[void] -proc `$`*(x: XdgOpen | UriRunnerConfig | ActionHandler): string = +proc `$`*(x: Open | UriRunnerConfig | Authority | Uri | ActionHandler): string = `$`(toPreserve(x)) -proc encode*(x: XdgOpen | UriRunnerConfig | ActionHandler): seq[byte] = +proc encode*(x: Open | UriRunnerConfig | Authority | Uri | ActionHandler): seq[ + byte] = encode(toPreserve(x)) diff --git a/src/uri_runner.nim b/src/uri_runner.nim index d0ffb72..9b271c3 100644 --- a/src/uri_runner.nim +++ b/src/uri_runner.nim @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense -import std/[re, tables] +import std/[re, tables, uri] import preserves, syndicate, syndicate/patterns -import ./protocol +import ./protocol, ./common # importing std/re doesn't actually link against PCRE {.passC: staticExec("pkg-config --cflags libpcre").} @@ -22,12 +22,6 @@ runActor("main") do (root: Ref; turn: var Turn): var handlers: Table[Handle, RegexAction] during(turn, root, ?UriRunnerConfig) do (handlerspace: Ref, urispace: Ref): - # sanity chek - onMessage(turn, handlerspace, ?XdgOpen) do (uri: string): - raiseAssert "got a message in the wrong dataspace!" - onPublish(turn, urispace, ?ActionHandler) do (pat: string; entity: Ref; act: Assertion): - raiseAssert "got an assertion in the wrong dataspace!" - during(turn, handlerspace, dropType(ActionHandler)) do: during(turn, handlerspace, ?ActionHandler) do (pat: string; entity: Ref; act: Assertion): @@ -36,7 +30,8 @@ runActor("main") do (root: Ref; turn: var Turn): do: del(handlers, duringHandle) - onMessage(turn, urispace, ?XdgOpen) do (uri: string): + onMessage(turn, urispace, Open ? {0:grab()}) do (u: uri.Uri): + let uri = $u assert len(handlers) > 0 var matched = false for handler in handlers.values: diff --git a/syndicated_open.nimble b/syndicated_open.nimble new file mode 100644 index 0000000..687a3c6 --- /dev/null +++ b/syndicated_open.nimble @@ -0,0 +1,13 @@ +# Package + +version = "20230630" +author = "Emery" +description = "Syndicated open command" +license = "Unlicense" +srcDir = "src" +bin = @[ "open", "uri_runner"] + + +# Dependencies + +requires "nim >= 1.6.4", "syndicate >= 20230630" diff --git a/uri_runner.pr b/uri_runner.pr index 65e5246..b5ae443 100644 --- a/uri_runner.pr +++ b/uri_runner.pr @@ -10,12 +10,12 @@ }> ] -; grab a dataspace for observing messages +; grab a dataspace for observing messages ? [ - ; log xdg-open messages - $socketspace ?? [ - $log ! }> + ; log open messages + $socketspace ?? [ + $log ! }> ] ; configure the uri_runner diff --git a/xdg_open_ng.nimble b/xdg_open_ng.nimble deleted file mode 100644 index 1bff504..0000000 --- a/xdg_open_ng.nimble +++ /dev/null @@ -1,13 +0,0 @@ -# Package - -version = "20230630" -author = "Emery" -description = "A better xdg-open" -license = "Unlicense" -srcDir = "src" -bin = @[ "uri_runner", "xdg_open"] - - -# Dependencies - -requires "nim >= 1.6.4", "syndicate >= 20230518"