aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-22 14:49:40 +0200
committeruser <user@clank>2026-09-22 14:49:40 +0200
commit9f751ab432ae74d4462fb4c3fefbd85415f47c86 (patch)
treee6a648f5a973b3817d416dbb07dabfa0786aca40
parentsidebar: the tab number at the far edge (tab_bar_index) (diff)
downloadslosh-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.kdl19
-rw-r--r--docs/panes.md14
-rw-r--r--docs/slosh.56
-rw-r--r--src/config.c6
-rw-r--r--tests/test_tab_bar.py67
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()