diff options
| author | user <user@clank> | 2026-08-14 16:46:42 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-14 16:46:42 +0200 |
| commit | 18e96314d5a4ea62b16ae0c9cb1558985d270800 (patch) | |
| tree | 76be4a915fef5e16beb1dc36eb8fe67ab7b5824d /src | |
| parent | sl0ppty: the status line counts this tab's panes (diff) | |
| download | slosh-18e96314d5a4ea62b16ae0c9cb1558985d270800.tar.gz slosh-18e96314d5a4ea62b16ae0c9cb1558985d270800.tar.xz slosh-18e96314d5a4ea62b16ae0c9cb1558985d270800.zip | |
sl0ppty: the status line says which pane, not just how many
A bare count answered "how big is this tab" and left "where am I in it" to be
worked out by counting frames — which is exactly the question you have once a
tab has collapsed into a list and only one pane is open, and exactly when
counting frames stops working. It reads `pane 2/5` now.
It also stops looking like the session count in the opposite corner. Two
numbers in two corners, both rendered "N panes" and disagreeing, was a puzzle
the reader had to solve once and then remember.
Both bars also take a `status_pad` for how far they are held off the left and
right edges. They were using `gap * gap_aspect`, which is the space around the
*panes*: the two match at the defaults and there was never a reason they had to
be the same number.
The count is kept as a fallback for when nothing is focused, which should not
happen but says something true if it does.
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.c | 31 | ||||
| -rw-r--r-- | src/config.c | 5 | ||||
| -rw-r--r-- | src/config.h | 4 |
3 files changed, 32 insertions, 8 deletions
@@ -270,7 +270,8 @@ size_t app_toast_count(app_t *a) { return a->ntoasts; } -static size_t count_leaves(node_t *n); /* defined with the layout */ +static size_t count_leaves(node_t *n); /* both defined with the layout */ +static size_t collect_leaves(node_t *n, node_t **out, size_t cap, size_t k); /* The line along the bottom: what you are looking at, rather than what you * could switch to. The strip along the top already answers "which tab" and @@ -283,8 +284,9 @@ static size_t count_leaves(node_t *n); /* defined with the layout */ static void draw_status_line(app_t *a, screen_t *s) { if (!CFG.status_line || s->rows < 3) return; uint16_t y = (uint16_t)(s->rows - CFG.gap - 1); - uint16_t x = (uint16_t)(CFG.gap * CFG.gap_aspect); - uint16_t right = (uint16_t)(s->cols > x ? s->cols - x : 0); + uint16_t x = CFG.status_pad; + uint16_t right = + (uint16_t)(s->cols > CFG.status_pad ? s->cols - CFG.status_pad : 0); if (right <= x) return; node_t *f = a->ntabs ? cur(a)->focus : NULL; @@ -298,9 +300,21 @@ static void draw_status_line(app_t *a, screen_t *s) { * a thing that does not. This count is *this tab's*; the strip above counts * the whole session, which is why they can disagree. */ if (a->ntabs && cur(a)->root) { - char cnt[32]; - size_t np = count_leaves(cur(a)->root); - snprintf(cnt, sizeof cnt, "%zu pane%s", np, np == 1 ? "" : "s"); + /* Which of this tab's panes, out of how many — the count alone answers + * "how big is this tab" and leaves "where am I in it" to be worked out by + * counting frames, which is the question you actually have when a tab has + * collapsed into a list and only one of them is open. */ + node_t *leaves[64]; + size_t nl = collect_leaves(cur(a)->root, leaves, 64, 0); + size_t idx = 0; + for (size_t i = 0; i < nl; i++) + if (leaves[i] == f) idx = i + 1; + + char cnt[40]; + if (idx) + snprintf(cnt, sizeof cnt, "pane %zu/%zu", idx, nl); + else /* nothing focused: still say how many there are */ + snprintf(cnt, sizeof cnt, "%zu pane%s", nl, nl == 1 ? "" : "s"); uint16_t cw = (uint16_t)strlen(cnt); if (right > x + cw + 2) { screen_text(s, (uint16_t)(right - cw), y, cnt, FRAME_IDLE, NO_COLOR, 0); @@ -1876,12 +1890,13 @@ static void draw_cb(node_t *n, void *ud) { } static void draw_tab_strip(app_t *a, screen_t *s) { - uint16_t x = (uint16_t)(CFG.gap * CFG.gap_aspect); + uint16_t x = CFG.status_pad; uint16_t y = CFG.gap; /* Right side first, so a long tab list can never eat the indicators — the * same budgeting rule as the split button and the OSC buttons. */ - uint16_t right = (uint16_t)(s->cols - CFG.gap * CFG.gap_aspect); + uint16_t right = (uint16_t)(s->cols > CFG.status_pad ? s->cols - CFG.status_pad + : s->cols); char info[64]; size_t np = app_pane_count(a); snprintf(info, sizeof info, "%zu pane%s", np, np == 1 ? "" : "s"); diff --git a/src/config.c b/src/config.c index e0a40fe..142776c 100644 --- a/src/config.c +++ b/src/config.c @@ -179,6 +179,9 @@ void config_defaults(config_t *c) { c->double_click_ms = 400; c->status_bar = true; c->status_line = true; + /* Matches gap * gap_aspect at the defaults, so the strip lines up with the + * panes' outer edge until you say otherwise. */ + c->status_pad = 2; c->focus_follows_mouse = true; c->default_fg = rgb(0xff, 0xff, 0xff); @@ -297,6 +300,8 @@ bool config_load(config_t *c, const char *path, char *err, size_t errcap) { c->status_bar = kdl_arg_bool(kdl_child(root, "status_bar"), 0, c->status_bar); c->status_line = kdl_arg_bool(kdl_child(root, "status_line"), 0, c->status_line); + c->status_pad = + (uint16_t)kdl_arg_int(kdl_child(root, "status_pad"), 0, c->status_pad); c->focus_follows_mouse = kdl_arg_bool(kdl_child(root, "focus_follows_mouse"), 0, c->focus_follows_mouse); diff --git a/src/config.h b/src/config.h index a85a204..9d0b022 100644 --- a/src/config.h +++ b/src/config.h @@ -112,6 +112,10 @@ typedef struct { size_t state_n[PSTATE_COUNT]; bool status_bar; /* the strip along the top: tabs, prefix, pane count */ bool status_line; /* the line along the bottom: what you are looking at */ + /* How far the strip and the line are held off the left and right edges. + * Separate from `gap`, which is the space around the *panes*: the two happen + * to match by default and there is no reason they must. */ + uint16_t status_pad; bool focus_follows_mouse; /* What a cell's "terminal default" colour resolves to when a shader has to |
