From 523379031588ce6be0216154c81a3d5d6ebd5ae0 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Sun, 9 Aug 2026 16:11:31 +0800 Subject: [PATCH] Re-index tab numbers when a tab closes via its last pane exiting Herdr only emits tab.closed for explicit tab closes. When a tab dies because its last shell exits, Herdr reports pane.exited instead, so the plugin never re-synchronised and later tabs kept stale position numbers. Subscribe to pane.closed and pane.exited and treat both as workspace re-sync events, mirroring tab.closed and tab.moved. --- README.md | 2 +- plugins/tab-numbers/README.md | 2 +- plugins/tab-numbers/herdr-plugin.toml | 10 +++++++++- plugins/tab-numbers/package.json | 2 +- .../tab-numbers/src/application/tab-numbers-plugin.ts | 2 +- .../tests/application/tab-numbers-plugin.test.ts | 2 +- .../tests/architecture/module-aliases.test.ts | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1603f40..8b54f4e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Herdr previews each plugin and its build and runtime commands before confirming ![Herdr tabs labelled Dashboard 1, Editor 2, and Tests 3](docs/images/tab-numbers.png) -The `sync` action re-indexes all named tabs. Creation, rename, move, and close events keep the numbers contiguous afterwards. See the [Tab Numbers documentation](plugins/tab-numbers) for behaviour and cleanup details. +The `sync` action re-indexes all named tabs. Creation, rename, move, close, and pane-exit events keep the numbers contiguous afterwards. See the [Tab Numbers documentation](plugins/tab-numbers) for behaviour and cleanup details. ### Tmux Keybindings diff --git a/plugins/tab-numbers/README.md b/plugins/tab-numbers/README.md index 62b362e..200634a 100644 --- a/plugins/tab-numbers/README.md +++ b/plugins/tab-numbers/README.md @@ -21,7 +21,7 @@ herdr plugin action invoke oullin.tab-numbers.sync | ------ | ---------------------------------------------------- | --------------------------------------------------------- | | Sync | `herdr plugin action invoke oullin.tab-numbers.sync` | Re-index every named tab using its current display order. | -The `tab.created`, `tab.renamed`, `tab.closed`, and `tab.moved` hooks keep the sequence contiguous after the initial synchronisation. +The `tab.created`, `tab.renamed`, `tab.closed`, `tab.moved`, `pane.closed`, and `pane.exited` hooks keep the sequence contiguous after the initial synchronisation. The pane hooks cover tabs that close because their last shell exits, which Herdr reports without a `tab.closed` event. ## Behaviour diff --git a/plugins/tab-numbers/herdr-plugin.toml b/plugins/tab-numbers/herdr-plugin.toml index df26917..de8b9e5 100644 --- a/plugins/tab-numbers/herdr-plugin.toml +++ b/plugins/tab-numbers/herdr-plugin.toml @@ -1,6 +1,6 @@ id = "oullin.tab-numbers" name = "Tab Numbers" -version = "0.1.7" +version = "0.1.8" min_herdr_version = "0.7.0" description = "Show contiguous position numbers in named Herdr tab labels" platforms = ["linux", "macos", "windows"] @@ -39,3 +39,11 @@ command = ["node", "index.ts"] [[events]] on = "tab.moved" command = ["node", "index.ts"] + +[[events]] +on = "pane.closed" +command = ["node", "index.ts"] + +[[events]] +on = "pane.exited" +command = ["node", "index.ts"] diff --git a/plugins/tab-numbers/package.json b/plugins/tab-numbers/package.json index 0389787..1cddb55 100644 --- a/plugins/tab-numbers/package.json +++ b/plugins/tab-numbers/package.json @@ -1,6 +1,6 @@ { "name": "@oullin/herdr-tab-numbers", - "version": "0.1.7", + "version": "0.1.8", "description": "Show contiguous position numbers in named Herdr tab labels.", "license": "MIT", "repository": { diff --git a/plugins/tab-numbers/src/application/tab-numbers-plugin.ts b/plugins/tab-numbers/src/application/tab-numbers-plugin.ts index e1122b4..d7bf198 100644 --- a/plugins/tab-numbers/src/application/tab-numbers-plugin.ts +++ b/plugins/tab-numbers/src/application/tab-numbers-plugin.ts @@ -6,7 +6,7 @@ export type { Environment } from '@oullin/herdr-plugin-core'; export class TabNumbersPlugin { private static readonly singleTabEvents: ReadonlySet = new Set(['tab.created', 'tab.renamed']); - private static readonly workspaceTabEvents: ReadonlySet = new Set(['tab.closed', 'tab.moved']); + private static readonly workspaceTabEvents: ReadonlySet = new Set(['tab.closed', 'tab.moved', 'pane.closed', 'pane.exited']); private readonly synchroniser: TabNumberSynchroniser; diff --git a/plugins/tab-numbers/tests/application/tab-numbers-plugin.test.ts b/plugins/tab-numbers/tests/application/tab-numbers-plugin.test.ts index 6343549..d95a01d 100644 --- a/plugins/tab-numbers/tests/application/tab-numbers-plugin.test.ts +++ b/plugins/tab-numbers/tests/application/tab-numbers-plugin.test.ts @@ -38,7 +38,7 @@ describe('TabNumbersPlugin', () => { expect(client.renameCalls).toEqual([['w1:t7', 'new label ยท 3']]); }); - it.each(['tab.closed', 'tab.moved'])('reindexes the affected workspace for %s', (event) => { + it.each(['tab.closed', 'tab.moved', 'pane.closed'])('reindexes the affected workspace for %s', (event) => { const client = new FakeHerdrClient({ tabsByWorkspace: new Map([ [ diff --git a/plugins/tab-numbers/tests/architecture/module-aliases.test.ts b/plugins/tab-numbers/tests/architecture/module-aliases.test.ts index ab00cfb..c92e2f8 100644 --- a/plugins/tab-numbers/tests/architecture/module-aliases.test.ts +++ b/plugins/tab-numbers/tests/architecture/module-aliases.test.ts @@ -82,7 +82,7 @@ describe('module aliases', () => { 'utf8', ); - expect(packageJson.version).toBe('0.1.7'); + expect(packageJson.version).toBe('0.1.8'); expect(manifest).toContain(`version = "${packageJson.version}"`); }); });