diff options
| author | user <user@clank> | 2026-09-22 14:49:40 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-22 14:49:40 +0200 |
| commit | 9f751ab432ae74d4462fb4c3fefbd85415f47c86 (patch) | |
| tree | e6a648f5a973b3817d416dbb07dabfa0786aca40 | |
| parent | sidebar: the tab number at the far edge (tab_bar_index) (diff) | |
| download | slosh-9f751ab432ae74d4462fb4c3fefbd85415f47c86.tar.gz slosh-9f751ab432ae74d4462fb4c3fefbd85415f47c86.tar.xz slosh-9f751ab432ae74d4462fb4c3fefbd85415f47c86.zip | |
sidebar: align the numbers by default
The knob landed defaulting to "prefix" on the grounds that it is what the
strip has always drawn -- but the strip is not what this is about. A sidebar
row is wider than the name on it, and `1:api` spends the first two or three
cells of every row (three or four once you have ten tabs) on a number nobody
reads until they reach for C-a 2, pushing the names in by a distance that
depends on how many tabs are open. Right-aligned, the names start where the
statuses under them start and the numbers make a column of their own.
`tab_bar_index "prefix"` is still there and unchanged, and the top strip is
unaffected either way -- it ignores the setting, having no far end to align
against.
The tests that used `1:` as the anchor for "where a tab's name starts" now
anchor on the name, which is what they were about; two new ones cover the
default and the prefix form explicitly, so neither mode is tested only by
being the default.
| -rw-r--r-- | config/config.kdl | 19 | ||||
| -rw-r--r-- | docs/panes.md | 14 | ||||
| -rw-r--r-- | docs/slosh.5 | 6 | ||||
| -rw-r--r-- | src/config.c | 6 | ||||
| -rw-r--r-- | tests/test_tab_bar.py | 67 |
5 files changed, 74 insertions, 38 deletions
diff --git a/config/config.kdl b/config/config.kdl index 47473f0..acb4366 100644 --- a/config/config.kdl +++ b/config/config.kdl @@ -283,13 +283,18 @@ bell_mark "[!]" // The one-row bar with tabs, the new-tab button and the pane count. status_bar true -// Where a tab's number sits. "prefix" writes it against the name (`1:api`); -// "right" puts it at the far end of the row, so every name starts in the same -// column and the numbers line up in one of their own -- which a sidebar has -// room for and the top strip has not, a tab there being exactly as wide as -// its label. Sidebars only for that reason, and a row too narrow to spare the -// columns keeps the prefix: the name is the part you came for. -tab_bar_index "prefix" +// Where a tab's number sits in a *sidebar*. The default, "right", puts it at +// the far end of the row, so every name starts in the same column and the +// numbers line up in one of their own -- a list with a shape rather than a +// column of digits in front of the words you are reading. "prefix" is the +// older form, `1:api`, the number against the name. +// +// Sidebars only, and not by omission: a tab in the top strip is exactly as +// wide as its label, so there is no far end to align against, and the setting +// is ignored there rather than half-honoured. A sidebar row too narrow to +// spare the columns also keeps the prefix -- the name is the part you came +// for. +tab_bar_index "right" // The line along the bottom: which session and tab you are in, what the // focused pane calls itself, and whether it is in a state worth knowing about diff --git a/docs/panes.md b/docs/panes.md index 3a28046..7f11fcd 100644 --- a/docs/panes.md +++ b/docs/panes.md @@ -55,7 +55,7 @@ The strip of tabs sits along the top by default. It does not have to: ```kdl tab_bar_side "left" // or "right"; "top" is the default tab_bar_width 18 // columns the sidebar takes -tab_bar_index "right" // the tab number at the far end, not against the name +tab_bar_index "right" // the tab number at the far end; "prefix" is 1:name tab_bar_pad 0 // blank rows above the first tab tab_gap 0 // ...and between one tab and the next tab_bar_chrome true // frame it like a pane @@ -127,9 +127,9 @@ yours wins; the band is unset by default, which leaves a translucent terminal's own background alone. The top strip has one row and no room for any of this, which is half of why the sidebar exists. -**The tab number can sit at the far end of the row.** `tab_bar_index "right"` -draws `api` on the left and `3` hard against the right edge, instead of the -default `3:api`: +**A sidebar's tab numbers sit at the far end of the row**, `api` on the left +and `3` hard against the right edge, rather than as the `3:api` the top strip +writes. `tab_bar_index "prefix"` puts them back: ``` │ tests 1 │ │ 1:tests │ @@ -137,9 +137,9 @@ default `3:api`: │ api 3 │ │ 3:api │ ``` -Every name then starts in the same column and the numbers line up in one of -their own, which is worth a column of a sidebar and is not available to the top -strip at all — a tab there is exactly as wide as its label, so it has no far end +Every name starts in the same column and the numbers line up in one of their +own, which is worth a column of a sidebar and is not available to the top strip +at all — a tab there is exactly as wide as its label, so it has no far end to align against, and the setting is ignored. A row too narrow to spare the columns goes back to the prefix, because the name is the part you came for, and a name long enough to reach the number always stops one cell short of it: diff --git a/docs/slosh.5 b/docs/slosh.5 index ff8b386..3a467e5 100644 --- a/docs/slosh.5 +++ b/docs/slosh.5 @@ -136,9 +136,9 @@ keeps the full width. A terminal too narrow to give up the columns falls back to \fBtop\fR until it grows. .TP .BI tab_bar_index\ where -Where a tab's number sits: \fBprefix\fR (the default) writes it against the -name, \fB1:api\fR, and \fBright\fR puts it at the far end of the row so the -names all start in one column and the numbers line up in another. +Where a tab's number sits: \fBright\fR (the default) puts it at the far end +of the row, so the names all start in one column and the numbers line up in +another, and \fBprefix\fR writes it against the name, \fB1:api\fR. Sidebars only \(em a tab in the top strip is as wide as its label, so there is no far end to align against \(em and a row too narrow to spare the columns keeps the prefix, since the name is the part you came for. diff --git a/src/config.c b/src/config.c index 1297856..a1d8880 100644 --- a/src/config.c +++ b/src/config.c @@ -951,7 +951,7 @@ void config_defaults(config_t *c) { c->modal_scrim = 120; c->status_bar = true; c->tab_bar_side = TAB_BAR_TOP; - c->tab_bar_index = TAB_INDEX_PREFIX; + c->tab_bar_index = TAB_INDEX_RIGHT; /* Wide enough for " 12:a-real-name " plus a bell; narrow enough that a * 100-column terminal keeps a working layout beside it. */ c->tab_bar_width = 18; @@ -1711,8 +1711,8 @@ char *config_render(const config_t *c) { : c->tab_bar_side == TAB_BAR_RIGHT ? "right" : "top"); cb_add(&b, - "tab_bar_index \"%s\" // 1:name, or the number at the sidebar's far " - "edge\n", + "tab_bar_index \"%s\" // the sidebar's number at its far edge, or " + "1:name\n", c->tab_bar_index == TAB_INDEX_RIGHT ? "right" : "prefix"); cb_add(&b, "tab_bar_width %u // columns a sidebar takes\n", c->tab_bar_width); diff --git a/tests/test_tab_bar.py b/tests/test_tab_bar.py index fca4742..b2220b2 100644 --- a/tests/test_tab_bar.py +++ b/tests/test_tab_bar.py @@ -158,14 +158,17 @@ def _status(s, text): s.settle(30) +# The sidebar's default. LEFT would do as well -- the point of these is the +# alignment, so they say which mode they mean rather than leaning on it. RIGHT_IDX = _cfg(f'tab_bar_side "left"\ntab_bar_width {W}\ntab_bar_index "right"\n') +PREFIX_IDX = _cfg(f'tab_bar_side "left"\ntab_bar_width {W}\ntab_bar_index "prefix"\n') -def test_the_index_can_sit_at_the_far_end(): - """`tab_bar_index "right"`: names all start in one column, numbers line up - in another. A sidebar row is wider than the name on it, and the prefix - spends the start of every row on a number nobody reads until they want to - press it.""" +def test_the_index_sits_at_the_far_end(): + """The sidebar's default: names all start in one column, numbers line up in + another. A sidebar row is wider than the name on it, and a prefix spends + the start of every row on a number nobody reads until they want to press + it.""" with Session(SH, cols=90, rows=20, config=RIGHT_IDX) as s: s.settle(30) s.api("new-tab", name="api") @@ -246,15 +249,29 @@ def test_the_whole_row_is_still_one_door(): ) +def test_the_prefix_is_still_there_for_anyone_who_wants_it(): + """`1:name`, which is what the top strip draws and what the sidebar drew + before the alignment existed.""" + with Session(SH, cols=90, rows=20, config=PREFIX_IDX) as s: + s.settle(30) + row = _row(s.snapshot(), Y0) + check("the number is in front of the name", row.strip() == "1:tests", repr(row)) + + +def test_the_sidebar_aligns_by_default(): + with Session(SH, cols=90, rows=20, config=LEFT) as s: + s.settle(30) + row = _row(s.snapshot(), Y0) + check("no config asked for it", row.rstrip()[-1] == "1", repr(row)) + check("...and no prefix came with it", "1:" not in row, repr(row)) + + def test_a_bad_index_mode_is_a_line_and_no_more(): bad = _cfg(f'tab_bar_side "left"\ntab_bar_width {W}\ntab_bar_index "middle"\n') with Session(SH, cols=90, rows=20, config=bad) as s: s.settle(30) - check( - "the session runs, with the default", - "1:tests" in s.snapshot().screen(), - _row(s.snapshot(), Y0), - ) + row = _row(s.snapshot(), Y0) + check("the session runs, with the default", row.rstrip()[-1] == "1", repr(row)) def test_every_tab_sits_on_a_plate(): @@ -367,8 +384,8 @@ def test_status_rows_are_told_apart_by_the_slant_not_by_an_indent(): # starts in. Three columns of indent is a fifth of this sidebar. check( "a status is not indented under its label", - status.index("building") == label.index("1:"), - f"{status.index('building')} vs {label.index('1:')}", + status.index("building") == label.index("tests"), + f"{status.index('building')} vs {label.index('tests')}", ) st = snap.style_at(CX + 1, Y0 + 1) check("it is italic instead", "italic" in st["attrs"], str(st)) @@ -729,7 +746,11 @@ def test_an_unnamed_tab_borrows_its_directory(): with Session(cd, cols=90, rows=20, config=LEFT) as s: s.settle(60) row = _row(s.snapshot(), Y0) - check("the label is the focused pane's dir", "1:tmp" in row, repr(row)) + check( + "the label is the focused pane's dir", + row.split() == ["tmp", "1"], + repr(row), + ) def test_a_real_name_beats_the_derived_one(): @@ -739,17 +760,25 @@ def test_a_real_name_beats_the_derived_one(): with Session(SH, cols=90, rows=20, config=LEFT, layout=lay.name) as s: s.settle(60) row = _row(s.snapshot(), Y0) - check("a declared name is not second-guessed", "1:api" in row, repr(row)) + check( + "a declared name is not second-guessed", + row.split() == ["api", "1"], + repr(row), + ) def test_the_borrowed_name_follows_a_cd(): loop = ["/bin/sh", "-c", 'cd /tmp && while IFS= read -r l; do eval "$l"; done'] with Session(loop, cols=90, rows=20, config=LEFT) as s: - s.until(lambda snap: "1:tmp" in snap.line(Y0)) + s.until(lambda snap: "tmp" in snap.line(Y0)) s.send(r"cd /home\n") - s.until(lambda snap: "1:home" in snap.line(Y0)) + s.until(lambda snap: "home" in snap.line(Y0)) row = _row(s.snapshot(), Y0) - check("the kernel's answer moves the label", "1:home" in row, repr(row)) + check( + "the kernel's answer moves the label", + row.split() == ["home", "1"], + repr(row), + ) def test_the_sidebar_is_framed_like_a_pane(): @@ -957,7 +986,9 @@ if __name__ == "__main__": test_sidebar_rows_click_like_the_strip() test_right_sidebar_takes_the_other_edge() test_pad_pushes_the_list_down() - test_the_index_can_sit_at_the_far_end() + test_the_index_sits_at_the_far_end() + test_the_prefix_is_still_there_for_anyone_who_wants_it() + test_the_sidebar_aligns_by_default() test_a_long_name_stops_short_of_the_number() test_a_narrow_row_keeps_the_prefix() test_the_top_strip_ignores_it() |
