diff options
| author | user <user@clank> | 2026-08-15 13:13:34 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-15 13:13:34 +0200 |
| commit | d9dee7f725b68332982f34ab6c52da0552b821d3 (patch) | |
| tree | 950f8293a6d6b6fd5a39acee5625c64813ab0160 /src/app.h | |
| parent | sl0ppty: let the cheatsheet breathe (diff) | |
| download | slosh-d9dee7f725b68332982f34ab6c52da0552b821d3.tar.gz slosh-d9dee7f725b68332982f34ab6c52da0552b821d3.tar.xz slosh-d9dee7f725b68332982f34ab6c52da0552b821d3.zip | |
sl0ppty: write the session back out as a layout, and a loop that uses it
Dogfooding this while building it has one sharp edge: a running session keeps
the binary it started with. `reload` re-reads the config, it cannot re-read
the code, so every build you want to try means losing your screen.
The only thing worth carrying across a restart is the shape, and sl0ppty
already knows how to read one -- it just could not write one. `dump-layout`
is the inverse of `--layout`: tabs with their names and purposes, how the
panes are split, in what proportion, in which directory, running what, which
tab was active and which pane had focus.
Two details make it worth trusting. The directory is where the shell *is*,
read from /proc, not where the pane was started -- after any amount of `cd`
those differ and only one of them is useful. And a pane running the session's
default shell is dumped with no `command`, so it comes back as a shell rather
than as a shell wrapped in a shell, one layer deeper every restart.
contrib/sl0ppty-dev is the loop: attach, and when the session ends because you
asked for a restart, come straight back with the layout. It is two halves
because it has to be -- `restart` runs inside the session, and the moment the
session ends so does the shell it was typed in, so it leaves the layout and a
note and the loop outside picks them up.
What does not come back is what was running *inside* a program. A shell
returns as a shell, in the right directory, with an empty history. That is the
limit of restoring a layout rather than a session, and the script says so
rather than implying otherwise.
Three bugs found by the round-trip test, all the same kind -- a dump that
loads without complaint and rebuilds something subtly different:
- `split=` belongs on the node that *has* the children, not on the children.
Written the other way it parses fine and gives the wrong tree.
- a split's weight was never restored, because the edit meant to read it
silently matched nothing and was never applied.
- `active=true` landed on the wrong tab: the index is recorded while the new
tabs sit after the old ones, and `replace` then moves them to the front.
Which is why the test asserts that a dump of a reload is byte-identical to
the first dump. Anything the dumper loses shows up there at once, where
reading it and nodding would not.
Diffstat (limited to 'src/app.h')
| -rw-r--r-- | src/app.h | 8 |
1 files changed, 8 insertions, 0 deletions
@@ -126,6 +126,14 @@ bool app_shade_add(app_t *a, uint32_t pane_id, const char *kind, color_t color, void app_shade_clear(app_t *a, uint32_t pane_id); size_t app_shade_count(app_t *a, uint32_t pane_id); +/* The session written back out as a layout file: tabs, splits, proportions, + * directories and commands. The inverse of app_apply_layout_text(), and what + * makes "quit, rebuild, come back to the same screen" possible. Caller frees. + * + * The shape is restorable; what is running inside a program is not, and this + * does not pretend otherwise. */ +char *app_dump_layout(app_t *a); + /* State as JSON, for the control API and the harness. Caller frees. */ char *app_panes_json(app_t *a); char *app_tabs_json(app_t *a); |
