summaryrefslogtreecommitdiff
path: root/examples/acmefs/pardesctl
diff options
context:
space:
mode:
Diffstat (limited to 'examples/acmefs/pardesctl')
-rwxr-xr-xexamples/acmefs/pardesctl158
1 files changed, 0 insertions, 158 deletions
diff --git a/examples/acmefs/pardesctl b/examples/acmefs/pardesctl
deleted file mode 100755
index 0a7bc1a4..00000000
--- a/examples/acmefs/pardesctl
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env bash
-# A tiny command line over the pardes acme filesystem. bash and coreutils only:
-# every subcommand below is one or two ordinary file operations, which is the
-# point of serving the editor as a filesystem in the first place.
-#
-# WHAT IT DEMONSTRATES
-#
-# panes read `index` -- five %11d numbers (id, tag length, body length,
-# isdir, dirty) then the tag text, one line per pane
-# body read `<id>/body` tag read `<id>/tag`
-# send APPEND to `<id>/body` -- a body write ignores its offset, so there
-# is no such thing as a partial overwrite by accident
-# exec write an `X`/`x` event record, which makes the editor perform the
-# action as though nobody had been listening. This is the remote
-# control door: it runs pardes builtins and shell commands alike.
-# new LOOKUP under `new/`, which is what creates a pane
-# del ctl verb `del`
-#
-# TWO RULES THIS SCRIPT FOLLOWS, AND YOU SHOULD TOO
-#
-# Always `>>`, never `>`. A plain `>` opens O_TRUNC, which is a setattr with
-# size 0 -- a truncate request against a control file. Appending is what every
-# writable file here actually wants; the offset is ignored anyway.
-#
-# `ctl` and `new/ctl` reads carry no trailing newline (acme prints fields, not
-# lines), so `read` returns non-zero at end of file even though it has already
-# assigned the fields. Hence the `|| :` on those reads.
-#
-# HOW `exec` RUNS ARBITRARY TEXT
-#
-# An event write is only `origin type q0 q1` -- no text. The action is named by
-# a range of the pane's own text, lowercase type for the tag and uppercase for
-# the body. So to run a command that is not on screen yet, this script appends
-# it to the tag (a tag write appends to the editable tail), measures where it
-# landed, and executes exactly that range. The command text stays visible in
-# the tag afterwards, which is also how acme leaves it, and means the user can
-# click it again.
-#
-# USAGE: run with no arguments.
-set -u
-
-self=${0##*/}
-mount=${PARDES_FS:-}
-
-usage() {
- cat >&2 <<EOF
-$self -- drive pardes through its acme filesystem
-
-usage: $self [-m mountdir] command [args]
-
- panes one line per pane: id, dirty flag, body size, tag
- body <id> print the pane's text
- tag <id> print the pane's tag
- send <id> <text...> append a line of text to the pane's body
- exec <id> <cmd...> make the editor run <cmd> (builtin or shell command)
- new [file] create a pane, optionally loading <file>; prints its id
- del <id> delete the pane (refused if it has unsaved changes)
-
-The mount directory comes from \$PARDES_FS, which pardes sets in every pane
-shell when started with --fs, or from -m. \$PARDES_PANE is the id of the pane
-a shell is running in, so "$self send \$PARDES_PANE hello" talks to itself.
-EOF
- exit 2
-}
-
-die() { printf '%s: %s\n' "$self" "$*" >&2; exit 1; }
-
-if [ "${1:-}" = "-m" ]; then
- [ $# -ge 2 ] || usage
- mount=$2
- shift 2
-fi
-[ $# -ge 1 ] || usage
-[ -n "$mount" ] || die "no mount point: set \$PARDES_FS or pass -m <dir>"
-[ -d "$mount" ] || die "$mount is not a directory (has pardes exited?)"
-
-cmd=$1
-shift
-
-# Every pane file lives under <mount>/<id>/. Sets $d rather than printing it:
-# inside a command substitution `die` would exit only the subshell and the
-# caller would sail on with an empty path. Refuses anything that is not a plain
-# number, so a typo cannot wander out of the mount.
-pane_dir() {
- case ${1:-} in
- "" | *[!0-9]*) die "expected a pane id (see: $self panes)" ;;
- esac
- [ -d "$mount/$1" ] || die "no pane $1 (see: $self panes)"
- d="$mount/$1"
-}
-
-case $cmd in
-panes)
- printf '%6s %5s %8s %s\n' ID DIRTY BYTES TAG
- while read -r id taglen bodylen isdir dirty tag; do
- [ -n "${id:-}" ] || continue
- printf '%6s %5s %8s %s\n' \
- "$id" "$([ "${dirty:-0}" = 0 ] && echo - || echo '*')" \
- "${bodylen:-0}" "${tag:-}"
- done <"$mount/index"
- ;;
-body)
- pane_dir "${1:-}"
- cat -- "$d/body"
- ;;
-tag)
- # A tag read carries no trailing newline, so supply one for the terminal.
- pane_dir "${1:-}"
- printf '%s\n' "$(cat -- "$d/tag")"
- ;;
-send)
- pane_dir "${1:-}"
- shift
- [ $# -ge 1 ] || die "send: nothing to send"
- printf '%s\n' "$*" >>"$d/body" || die "send: pane went away"
- ;;
-exec)
- pane_dir "${1:-}"
- shift
- [ $# -ge 1 ] || die "exec: no command"
- text=$*
- # Where the command will land: byte length of the whole tag, plus the one
- # space we prefix so it cannot merge with the word before it. Byte length,
- # not character length, because addresses are byte offsets -- ${#text}
- # would count characters and mis-address any non-ASCII command.
- q0=$(($(wc -c <"$d/tag") + 1))
- q1=$((q0 + $(printf '%s' "$text" | wc -c)))
- printf ' %s' "$text" >>"$d/tag" || die "exec: pane went away"
- # Lowercase 'x' is a tag exec; origin 'M' reports it as the mouse action
- # this stands in for. The editor now runs it.
- printf 'Mx%d %d\n' "$q0" "$q1" >>"$d/event" || die "exec: pane refused the event"
- ;;
-new)
- # The lookup itself creates the pane; the ctl read names it.
- read -r id _ <"$mount/new/ctl" || :
- case ${id:-} in
- "" | *[!0-9]*) die "new: unexpected new/ctl contents" ;;
- esac
- if [ $# -ge 1 ] && [ -n "$1" ]; then
- # `name` then `get`: one all-or-nothing ctl write, so the pane is
- # never left named after a file it did not load.
- printf 'name %s\nget\n' "$1" >>"$mount/$id/ctl" ||
- die "new: cannot load $1 into pane $id"
- fi
- printf '%s\n' "$id"
- ;;
-del)
- pane_dir "${1:-}"
- printf 'del\n' >>"$d/ctl" ||
- die "del: pane $1 refused (unsaved changes; save it, or use: $self exec $1 Delete)"
- ;;
--h | --help | help)
- usage
- ;;
-*)
- die "unknown command: $cmd (run with no arguments for usage)"
- ;;
-esac