Screens 1 and 4 running as TUIOS panes: reply screen, adopt-or-create launcher, layout script
This commit is contained in:
83
bin/screen
Executable file
83
bin/screen
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
# Open one screen as a TUIOS pane, or adopt the pane that already runs it.
|
||||
#
|
||||
# One screen, one workspace, named after the screen. The pane runs a shell that
|
||||
# starts the program and returns to the shell when the program exits, so the
|
||||
# pane never closes by itself; a workspace that loses its last pane is deleted
|
||||
# by TUIOS and the rest renumber, which is the failure this avoids.
|
||||
#
|
||||
# bin/screen tree
|
||||
# bin/screen reply AUD-162
|
||||
#
|
||||
# Run it twice and the second run focuses the existing pane. Print "created" or
|
||||
# "adopted" so the caller can tell which happened.
|
||||
set -euo pipefail
|
||||
|
||||
# The session is named, never taken from where the caller happens to be.
|
||||
# TUIOS_SESSION is the session of the pane you are typing in, which is not
|
||||
# necessarily this project's session; using it once put a screen in the wrong
|
||||
# place.
|
||||
SESSION="${PAPERCLIP_HARNESS_SESSION:-paperclip-harness}"
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BIN="$ROOT/bin/harness"
|
||||
|
||||
screen="${1:-}"
|
||||
case "$screen" in
|
||||
tree) args=(-screen tree -project "${2:-spike-2026-11-10}") ;;
|
||||
reply) args=(-screen reply -issue "${2:?reply needs a task, for example AUD-162}") ;;
|
||||
*) echo "usage: $(basename "$0") tree [project] | reply <task>" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
if [ ! -x "$BIN" ] || [ -n "$(find "$ROOT/tui" -name '*.go' -newer "$BIN" -print -quit 2>/dev/null)" ]; then
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
echo "no harness binary and no Go to build one" >&2
|
||||
exit 1
|
||||
fi
|
||||
( cd "$ROOT/tui" && go build -o "$BIN" . )
|
||||
fi
|
||||
|
||||
# Workspaces and windows are resolved by name every time. A number is never
|
||||
# remembered, because closing a pane renumbers the rest.
|
||||
state="$(python3 - "$SESSION" "$screen" <<'PY'
|
||||
import json, subprocess, sys
|
||||
session, want = sys.argv[1], sys.argv[2]
|
||||
|
||||
def call(*args):
|
||||
out = subprocess.run(["tuios", *args, "--json"], capture_output=True, text=True)
|
||||
if out.returncode != 0:
|
||||
sys.exit("tuios " + " ".join(args) + " failed: " + out.stderr.strip())
|
||||
return json.loads(out.stdout)
|
||||
|
||||
ws = call("list-workspaces", "-s", session)["workspaces"]
|
||||
win = call("list-windows", "-s", session)["windows"]
|
||||
|
||||
for w in win:
|
||||
# custom_name is the name we gave the pane. It survives the program
|
||||
# exiting and a shell taking over the title, so it is what adoption reads.
|
||||
if w.get("custom_name") == want:
|
||||
print("adopt", w["window_id"]); sys.exit()
|
||||
|
||||
named = next((w["workspace"] for w in ws if w.get("name") == want), None)
|
||||
if named is not None:
|
||||
print("create", named); sys.exit()
|
||||
|
||||
free = next((w["workspace"] for w in ws if w.get("window_count") == 0), None)
|
||||
if free is None:
|
||||
sys.exit("no empty workspace in session %r; close a pane or add a workspace" % session)
|
||||
print("create", free)
|
||||
PY
|
||||
)"
|
||||
|
||||
action="$(echo "$state" | awk '{print $1}')"
|
||||
where="$(echo "$state" | awk '{print $2}')"
|
||||
|
||||
if [ "$action" = "adopt" ]; then
|
||||
tuios focus-window "$where" -s "$SESSION" >/dev/null
|
||||
echo "adopted $screen ($where) in session $SESSION"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
tuios new-window "$screen" -s "$SESSION" --workspace "$where" --cwd "$ROOT" \
|
||||
--no-focus --keep-open -- /bin/sh -c "$BIN ${args[*]}; exec zsh -i" >/dev/null
|
||||
tuios set-workspace-name "$where" "$screen" -s "$SESSION" >/dev/null
|
||||
echo "created $screen on workspace $where of session $SESSION"
|
||||
Reference in New Issue
Block a user