aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-22 15:12:02 +0200
committeruser <user@clank>2026-09-22 15:12:02 +0200
commit720aa48e249c0c962e8f73372ceded6092414a6e (patch)
treedb713dc86f1333dab0f509e633077384005562c3 /include
parentsidebar: air inside it, the way panes have padding (tab_bar_padding) (diff)
downloadslosh-720aa48e249c0c962e8f73372ceded6092414a6e.tar.gz
slosh-720aa48e249c0c962e8f73372ceded6092414a6e.tar.xz
slosh-720aa48e249c0c962e8f73372ceded6092414a6e.zip
osc 5577: `busy`, and a sidebar that shows it (busy_mark)
A status is a line of text, and a line of text cannot say whether it is still true. "building 3/7" reads exactly the same while it builds and ten minutes after it stopped, which is the one thing somebody reading it from another tab wants to know -- and the only workaround available to a program was to write the answer into the words and keep rewriting them. So `busy`: printf '\033]5577;1;status;make test\033\\' printf '\033]5577;1;busy;1\033\\' ... printf '\033]5577;1;busy;0\033\\' A flag of its own rather than a field of `status`, because a status is the *whole* payload after the verb -- `status;a;b;c` has always been the text "a;b;c" -- so anything added to that line would change what every existing sender means, including the five pi extensions D1 promises byte compatibility to. Orthogonal, so a program can leave one line up and toggle the other; anything but 0/false/no/off is on; `clear` takes both; and a pane whose program has gone is never busy, whatever it last claimed, because a spinner turning under a dead tab is a lie you keep looking at. In a sidebar the row turns `tab_status_busy` -- the theme's accent, derived like the other status colours, so no theme needs a line -- and takes a spinner in the column `tab_bar_padding` was already holding blank, so nothing reflows when a program starts or stops working. `busy_mark` is the frames, separated by spaces: one frame is a static mark and costs nothing, several make it turn, and only then does the session keep a frame clock -- via the same `animating` flag an animated shader uses, so the cost lands only while such a row is actually composed, and `""` drops the mark entirely and leaves the colour to say it. The frame is a pure function of the clock, like every other pulse here, so two clients attached to one session show the same one. `panes` now reports `status` and `busy`, which is the scriptable half of the same fact: what a pane says about itself, without reading its screen.
Diffstat (limited to 'include')
-rw-r--r--include/app_internal.h1
-rw-r--r--include/config.h17
-rw-r--r--include/slosh.h5
3 files changed, 23 insertions, 0 deletions
diff --git a/include/app_internal.h b/include/app_internal.h
index 7948b13..1af9163 100644
--- a/include/app_internal.h
+++ b/include/app_internal.h
@@ -412,6 +412,7 @@ extern config_t CFG;
#define TAB_COUNT (CFG.tab_count)
#define TAB_STATUS_FG (CFG.tab_status_fg)
#define TAB_STATUS_BG (CFG.tab_status_bg)
+#define TAB_STATUS_BUSY (CFG.tab_status_busy)
#define TAB_STATUS_STRIPE (CFG.tab_status_stripe)
#define STATUS_C (CFG.status)
#define STATUS_STATE (CFG.status_state)
diff --git a/include/config.h b/include/config.h
index 47e48a7..40a5ace 100644
--- a/include/config.h
+++ b/include/config.h
@@ -235,6 +235,17 @@ typedef struct {
* terminals while chrome here is booked as one — so the default is narrow
* and anyone who knows their terminal can say otherwise. */
char bell_mark[32];
+ /* What a pane that says it is *busy* looks like in the sidebar: the frames
+ * of a spinner, separated by spaces. One frame is a static mark and costs
+ * nothing; several make it turn, and only then does the session keep a
+ * frame clock -- and only while such a row is actually on screen. Empty
+ * draws no mark at all and leaves the colour to say it. */
+ char busy_mark[64];
+ /* Milliseconds a spinner frame is held. Its own knob rather than anim_ms,
+ * which is how often the session repaints while something animates: this is
+ * how fast the thing being repainted moves, and a spinner stepping at the
+ * repaint rate is a blur. */
+ uint16_t busy_ms;
/* Which dead panes stay, showing what they printed and offering to run
* again, and which just go.
*
@@ -530,6 +541,12 @@ typedef struct {
* none leaves the terminal's own background alone, which is what a
* translucent one wants. */
color_t tab_status_fg, tab_status_bg;
+ /* A status whose program says it is still happening. Brighter than the
+ * ambient one, because "running" and "finished" are the two states worth
+ * telling apart from another tab, and the difference between them should
+ * not be something you have to read the words to work out. Derived from the
+ * theme, like tab_status_fg. */
+ color_t tab_status_busy;
/* The other stripe. With wrapped statuses, where one pane's rows end and
* the next one's begin is no longer obvious from the shape -- both are
* just italic text down the same column -- so alternate panes sit on
diff --git a/include/slosh.h b/include/slosh.h
index beec697..b8c8849 100644
--- a/include/slosh.h
+++ b/include/slosh.h
@@ -313,6 +313,11 @@ const char *pane_name(const pane_t *p);
/* "" clears the name and gives the pane back to the program's title. */
void pane_set_name(pane_t *p, const char *name);
const char *pane_status(const pane_t *p);
+/* Whether the program says what its status describes is still happening
+ * (`busy` over OSC 5577). Never true of a pane whose program has gone: a
+ * status left behind by something that exited is a description of the past,
+ * whatever it last claimed. */
+bool pane_status_busy(const pane_t *p);
size_t pane_buttons(const pane_t *p, const pane_button_t **out);
void pane_click_button(pane_t *p, const char *id);
void pane_set_osc_handler(pane_t *p, pane_osc_fn fn, void *ud);