Every workspace split into real panes: 19 panes across 7 workspaces, one program per panel

This commit is contained in:
Sam
2026-11-10 16:29:27 +11:00
parent 2640049f1f
commit 32fa2752af
19 changed files with 972 additions and 58 deletions

View File

@@ -41,16 +41,38 @@ def pages(cfg, folder):
proj = cfg["paperclip"]["project"]
task = pj.watch_task(cfg)
# (pane name, workspace name, command). The workspace is what a person reads
# on the rail, so it is capitalised and says what the page is for; the pane
# keeps the program's own name. Written Workspace>pane when talking about it.
# on the rail; the pane keeps its own name. Written Workspace>pane.
# Each workspace holds several real panes, not one program drawing panels.
b = shlex.quote(bin_path)
f = shlex.quote(folder)
def pane(name, panel, extra):
return "%s -screen %s -panel %s -folder %s %s" % (b, name, panel, f, extra)
return task, [
("shell", "Shell", "exec zsh -i"),
("board", "Board", "%s -screen board -project %s -folder %s" % (shlex.quote(bin_path), proj, shlex.quote(folder))),
("work", "Work", "%s -screen work -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
("reply", "Reply", "%s -screen reply -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
("new", "New task", "%s -screen new -project %s" % (shlex.quote(bin_path), proj)),
("project", "Project", "%s -screen project -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
("repair", "Repair", "%s -screen repair -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
("tasks", "Board", pane("board", "tasks", "-project " + shlex.quote(proj))),
("detail", "Board", pane("board", "detail", "-project " + shlex.quote(proj))),
("needs", "Board", pane("board", "needs", "-project " + shlex.quote(proj))),
("runs", "Work", pane("work", "runs", "")),
("change", "Work", pane("work", "change", "")),
("facts", "Work", pane("work", "facts", "")),
("task", "Reply", pane("reply", "task", "")),
("thread", "Reply", pane("reply", "thread", "")),
("replybox", "Reply", pane("reply", "reply", "")),
("form", "New task", pane("new", "form", "-project " + shlex.quote(proj))),
("guidance", "New task", pane("new", "guidance", "-project " + shlex.quote(proj))),
("preview", "New task", pane("new", "preview", "-project " + shlex.quote(proj))),
("facts-p", "Project", pane("project", "facts", "")),
("costs", "Project", pane("project", "costs", "")),
("settings", "Project", pane("project", "settings", "")),
("health", "Repair", pane("repair", "health", "")),
("layout", "Repair", pane("repair", "layout", "")),
("rebuild-log", "Repair", pane("repair", "log", "")),
]
@@ -75,15 +97,28 @@ def main():
if tuios.close_pane(name, session):
h.say(" closed %s" % name)
# Group the panes by the workspace they belong to, in first-seen order, so a
# workspace is claimed once and all of its panes are made inside it.
order = []
groups = {}
for name, workspace, command in page_list:
result, ident, ws = tuios.open_pane(
name, workspace, folder, command, session,
adopt_existing=(name == "shell"),
)
h.say(" %-9s %-8s workspace %s" % (name, result, ws))
if workspace not in groups:
groups[workspace] = []
order.append(workspace)
groups[workspace].append((name, command))
for workspace in order:
number = tuios.claim(workspace, session)
for name, command in groups[workspace]:
if any((w.get("custom_name") or "") == name for w in tuios.windows(session)):
h.say(" %-11s adopted %s" % (name, workspace))
continue
tuios.new_window(name, number, folder, command, session)
h.say(" %-11s created %s" % (name, workspace))
# Number the workspaces in the order a person reads them.
for number, name in tuios.arrange([(p[0], p[1]) for p in page_list], session):
h.say(" placed %-8s workspace %s" % (name, number))
h.say(" placed %-11s workspace %s" % (name, number))
in_use = [w for w in tuios.workspaces(session) if (w.get("window_count") or 0) > 0]
h.say("workspaces in use: %d" % len(in_use))

Binary file not shown.

View File

@@ -133,30 +133,51 @@ def open_pane(name, workspace_name, cwd, command, session=None, adopt_existing=F
def arrange(order, session=None):
"""Put these panes on workspaces 1..N in this order, and name the workspaces.
"""Put these panes on their workspaces, in this order, and name the workspaces.
`order` is a list of (pane name, workspace name) pairs. The pane keeps its
own name; the workspace gets the name a person reads on the rail.
TUIOS numbering follows the order panes land in, and closing panes renumbers
the rest, so a rebuild can scatter the pages. Moving each pane once, at the
end, is what makes the rail readable and stable.
`order` is a list of (pane name, workspace name). Panes that name the same
workspace are put in that same workspace, so one workspace can hold several
panes. Workspaces are numbered in the order they first appear.
"""
names = []
for _pane, workspace in order:
if workspace not in names:
names.append(workspace)
moved = []
for number, (pane, workspace) in enumerate(order, start=1):
win = next((w for w in windows(session) if (w.get("custom_name") or "") == pane), None)
if win is None:
continue
if win.get("workspace") != number:
subprocess.run(
["tuios", "move-window", str(number), "-w", win["window_id"], "-s", session or SESSION],
capture_output=True, text=True, timeout=30, check=False,
)
for number, workspace in enumerate(names, start=1):
for pane, ws in order:
if ws != workspace:
continue
win = next((w for w in windows(session) if (w.get("custom_name") or "") == pane), None)
if win is None:
continue
if win.get("workspace") != number:
subprocess.run(
["tuios", "move-window", str(number), "-w", win["window_id"], "-s", session or SESSION],
capture_output=True, text=True, timeout=30, check=False,
)
_name_workspace(number, workspace, session)
moved.append((number, workspace))
return moved
def new_window(name, workspace_number, cwd, command, session=None):
"""Create one pane in a workspace that has already been claimed."""
subprocess.run(
[
"tuios", "new-window", name,
"-s", session or SESSION,
"--workspace", str(workspace_number),
"--cwd", cwd,
"--no-focus", "--keep-open",
"--", "/bin/sh", "-c", command,
],
capture_output=True, text=True, timeout=60, check=False,
)
return name
def close_pane(name, session=None):
for w in windows(session):
if (w.get("custom_name") or "") == name: