syndicated-open/src/uri_runner.nim

48 lines
1.5 KiB
Nim

# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[asyncdispatch, deques, re, streams, strutils, osproc]
import preserves
import syndicate
import ./protocol
bootDataspace("main") do (root: Ref; turn: var Turn):
var
actions: seq[tuple[regex: Regex; cmd: string; args: seq[string]]]
children: Deque[Process]
connectStdio(root, turn)
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
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:
var child = children.popFirst()
if child.peekExitCode != 0:
stderr.writeLine child.errorStream.readAll
close child
# TODO check children on a timer?
for uri in uris:
var matched: bool
for act in actions:
if match(uri, act.regex):
matched = true
var args = newSeq[string](act.args.len)
for i, arg in act.args:
args[i] = replace(arg, "\\1", uri)
var child = startProcess(
command = act.cmd, args = args, options = {})
children.addLast child
if not matched:
stderr.writeLine "no actions matched for ", uri
runForever()