parent
2ab8dd5fb9
commit
f94473d4a6
@ -1,21 +1,14 @@
|
||||
# xdg-open-ng
|
||||
|
||||
An `xdg-open` replacement that uses Syndicate and PCRE pattern matching to open URIs.
|
||||
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.
|
||||
|
||||
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 as 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, `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.
|
||||
|
||||
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
|
||||
- Fallback commands?
|
||||
Matching patterns to actions is done with `action-handler` records:
|
||||
```preserves
|
||||
<action-handler "foo://(.*):(.*)" $entity <krempel ["--host=$1" "--port=$2"]> >
|
||||
```
|
||||
|
||||
## Examples
|
||||
In the preceding example the URI `foo://bar:42` would cause the message `<krempel ["--host=bar" "--port=42"]>` to be sent to `$entity`.
|
||||
|
||||
| Type | Rule |
|
||||
|-|-|
|
||||
| Bittorrent | <code><action-handler "magnet:?.*xt=urn:btih.*" ["transmission-remote-gtk" 0]></code> |
|
||||
| Gemini | <code><action-handler "gemini://.*|file:///.*.gmi" ["/run/current-system/sw/bin/lagrange" 0]></code> |
|
||||
| PDF | <code><action-handler "file://(.*.pdf)" ["mupdf" 1]></code> |
|
||||
| Tox | <code><action-handler "tox:.*|uri:tox:.*", ["/nix/store/hix5jibhdzx0a2qbq5cqihac060zz10b-qtox-1.17.6/bin/qtox" 0]></code> |
|
||||
| Twatter | <code><action-handler "https://twitter.com/(.*)" ["firefox" "--new-tab" "https://nitter.net/$1"]></code> |
|
||||
| Video | <code><action-handler ".*\\.avi|.*\\.mkv|.*mp4|.*ogg|.*youtu.*|.*\\.m3u8|.*webm" ["mpv" "--no-terminal" "--force-window=immediate" "--loop-playlist" "--ytdl-format=best" 0]></code> |
|
||||
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.
|
||||
|
@ -1,23 +0,0 @@
|
||||
; Copied from ../syndicate-rs/syndicate-server/protocols/schemas/externalServices.prs
|
||||
version 1 .
|
||||
|
||||
Exec = <exec @argv CommandLine @restartPolicy RestartPolicy> .
|
||||
|
||||
CommandLine = @shell string / @full FullCommandLine .
|
||||
FullCommandLine = [@program string @args string ...] .
|
||||
|
||||
RestartPolicy =
|
||||
/ ; Whether the process terminates normally or abnormally, restart it
|
||||
; without affecting any peer processes within the service.
|
||||
=always
|
||||
/ ; If the process terminates normally, leave everything alone; if it
|
||||
; terminates abnormally, restart it without affecting peers.
|
||||
@onError =on-error
|
||||
/ ; If the process terminates normally, leave everything alone; if it
|
||||
; terminates abnormally, restart the whole daemon (all processes
|
||||
; within the daemon).
|
||||
=all
|
||||
/ ; Treat both normal and abnormal termination as normal termination; that is, never restart,
|
||||
; and enter state "complete" even if the process fails.
|
||||
=never
|
||||
.
|
@ -1,32 +0,0 @@
|
||||
|
||||
import
|
||||
std/typetraits, preserves
|
||||
|
||||
type
|
||||
CommandLineKind* {.pure.} = enum
|
||||
`shell`, `full`
|
||||
CommandLineShell* = string
|
||||
`CommandLine`* {.preservesOr.} = object
|
||||
case orKind*: CommandLineKind
|
||||
of CommandLineKind.`shell`:
|
||||
`shell`*: CommandLineShell
|
||||
|
||||
of CommandLineKind.`full`:
|
||||
`full`*: FullCommandLine
|
||||
|
||||
|
||||
Exec* {.preservesRecord: "exec".} = object
|
||||
`argv`*: CommandLine
|
||||
`restartPolicy`*: RestartPolicy
|
||||
|
||||
`RestartPolicy`* {.preservesOr, pure.} = enum
|
||||
`always`, `onError`, `all`, `never`
|
||||
FullCommandLine* {.preservesTuple.} = object
|
||||
`program`*: string
|
||||
`args`* {.preservesTupleTail.}: seq[string]
|
||||
|
||||
proc `$`*(x: CommandLine | Exec | FullCommandLine): string =
|
||||
`$`(toPreserve(x))
|
||||
|
||||
proc encode*(x: CommandLine | Exec | FullCommandLine): seq[byte] =
|
||||
encode(toPreserve(x))
|
@ -1,50 +1,68 @@
|
||||
; Expose a dataspace over a unix socket
|
||||
let ?root_ds = dataspace
|
||||
let ?socketspace = dataspace
|
||||
<require-service <relay-listener <unix "/run/user/1000/dataspace"> $gatekeeper>>
|
||||
<bind "syndicate" #x"" $root_ds>
|
||||
<bind "syndicate" #x"" $socketspace>
|
||||
|
||||
<require-service <daemon uri_runner>>
|
||||
; Create a new dataspace for receiving "exec" messages
|
||||
; from the uri_runner
|
||||
let ?execspace = dataspace
|
||||
$execspace ?? <exec ?argv> $config [
|
||||
let ?id = timestamp
|
||||
let ?facet = facet
|
||||
let ?d = <uri_runner-exec $id $argv>
|
||||
<run-service <daemon $d>>
|
||||
<daemon $d {
|
||||
argv: $argv,
|
||||
env: { WAYLAND_DISPLAY: "wayland-1" DISPLAY: ":0" XDG_CACHE_HOME: "/home/cache" }
|
||||
readyOnStart: #f,
|
||||
restart: =never,
|
||||
}>
|
||||
? <service-state <daemon $d> complete> [$facet ! stop]
|
||||
? <service-state <daemon $d> failed> [$facet ! stop]
|
||||
]
|
||||
|
||||
; Start the uri_runner
|
||||
<require-service <daemon uri_runner>>
|
||||
<daemon uri_runner {
|
||||
argv: "uri_runner"
|
||||
protocol: text/syndicate
|
||||
}>
|
||||
|
||||
? <service-object <daemon uri_runner> ?cap> [
|
||||
? <service-object <daemon uri_runner> ?cap> $cap [
|
||||
|
||||
; send configuration to uri_runner
|
||||
$cap [
|
||||
<listen-on $root_ds>
|
||||
<listen-on $socketspace>
|
||||
|
||||
; Here the "0" argument is replaced with the whole URI asserted by xdg-open.
|
||||
<action-handler "http://.*|https://.*|.*html", ["/run/current-system/sw/bin/librewolf" 0]>
|
||||
; When http* is matched send a message to $execspace
|
||||
; that indicates the Syndicate server should start Firefox.
|
||||
<action-handler "(http://.*|https://.*|.*html)" $execspace
|
||||
<exec ["/bin/firefox" "--new-tab" "$1"]>>
|
||||
|
||||
; An argument can be a reference to a capture.
|
||||
<action-handler "(tox:.*)|uri:(tox:.*)", ["/run/current-system/sw/bin/qtox" 1]>
|
||||
; Capture a pattern within a pattern
|
||||
<action-handler "https://twitter.com/(.*)" $execspace
|
||||
<exec ["/bin/firefox" "--new-tab" "https://nitter.net/$1"]>>
|
||||
|
||||
; An argument can contain a reference to a capture using the $i notation.
|
||||
<action-handler "https://twitter.com/(.*)" ["/run/current-system/sw/bin/librewolf" "https://nitter.net/$1"]>
|
||||
; Local file-system paths should always be prefixed
|
||||
; by file:// but that can be removed after matching
|
||||
<action-handler "file://(.*.pdf)" $execspace
|
||||
<exec ["/bin/mupdf" "$1"]>>
|
||||
|
||||
<action-handler "gemini://.*|file:///.*.gmi" ["/run/current-system/sw/bin/kristall" 0]>
|
||||
<action-handler ".*\\.avi|.*\\.mkv|.*\\.mp4|.*\\.ogg|.*\\.opus", ["/run/current-system/sw/bin/mpv" 0]>
|
||||
<action-handler "(magnet:?.*xt=urn:btih.*)" $execspace
|
||||
<exec ["/bin/transmission-remote-gtk" "$1"]>>
|
||||
|
||||
; filesystem paths are always prefixed with file://
|
||||
<action-handler "file://(.*.pdf)" ["/run/current-system/sw/bin/mupdf" 1]>
|
||||
]
|
||||
<action-handler "(tox:.*)|uri:(tox:.*)" $execspace
|
||||
<exec ["/bin/qtox" "$1"]>>
|
||||
|
||||
<action-handler "(gemini://.*|file:///.*.gmi)" $execspace
|
||||
<exec ["/bin/lagrange" "$1"]>>
|
||||
|
||||
<action-handler "(https://.*\\.twitch.tv/.*)" $execspace
|
||||
<exec ["/bin/streamlink" "-p" "mpv" "$1"]>>
|
||||
|
||||
; uri_runner sends messages to the server to start handler applications
|
||||
$cap ?? <exec ?argv ?restartPolicy> [
|
||||
let ?id = timestamp
|
||||
let ?facet = facet
|
||||
let ?d = <uri_runner-exec $id $argv>
|
||||
$config <run-service <daemon $d>>
|
||||
$config <daemon $d {
|
||||
argv: $argv,
|
||||
readyOnStart: #f,
|
||||
restart: $restartPolicy,
|
||||
}>
|
||||
$config ? <service-state <daemon $d> complete> [$facet ! stop]
|
||||
$config ? <service-state <daemon $d> failed> [$facet ! stop]
|
||||
; when the mpv-transator is available send it commands directly
|
||||
$config ? <service-object <daemon mpv-translator> ?mpv> $mpv [
|
||||
$cap <action-handler "(.*\\.avi|.*\\.mkv|.*mp4|.*ogg|.*youtu.*|.*\\.m3u8|.*webm)" $mpv
|
||||
<mpv 1 { "command": ["loadfile" "$1" "append-play"] }>>
|
||||
]
|
||||
|
||||
]
|
||||
|
Loading…
Reference in new issue