mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
feat(tui): leave an attach with ONE key, F12, and no modifier
Three beta rounds died on tmux's native way out, and the last one died on the
instruction rather than the mechanism: "press Ctrl+B, release Ctrl, then d" is,
in the tester's words, very unclear, and holding the modifier through both keys
silently does nothing.
So the way out stops being a chord. The attach claims F12 in tmux's prefix-less
`root` table for its own duration, and the bar reads "press F12 to get back to
the codeman dashboard" — one keystroke, nothing to hold, nothing to release,
no order to get right. F12 because stock tmux ships an empty root table apart
from mouse bindings, and none of the CLIs that run in these panes want the key.
⚠️ The bar names the one key ONLY when the claim succeeded, and falls back to
the chord wording otherwise. A bar advertising a key that does nothing is the
bug this whole series started with, and it must not come back in a new costume.
Same claim rules as the prefix alias: taken only when tmux reports the key
unbound, given back only while it still means `detach-client`.
The chord and the held-Ctrl alias both keep working; they are simply no longer
what the user is told to press.
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
confirmKillStep,
|
||||
detachChord,
|
||||
heldCtrlAlias,
|
||||
ONE_KEY_DETACH,
|
||||
nextSessionName,
|
||||
footerKeysFor,
|
||||
formatPrefixKey,
|
||||
@@ -459,6 +460,35 @@ describe('buildListLines', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('the one-key way out', () => {
|
||||
it('names a single key with no modifier at all', () => {
|
||||
// The whole point: three beta rounds died on a chord that had to be typed
|
||||
// in the right order with the modifier released at the right moment.
|
||||
expect(ONE_KEY_DETACH).toBe('F12');
|
||||
expect(ONE_KEY_DETACH).not.toContain('C-');
|
||||
expect(ONE_KEY_DETACH).not.toContain('+');
|
||||
});
|
||||
|
||||
it('puts ONE instruction on the bar, not a menu of ways out', () => {
|
||||
const banner = buildAttachBanner({ prefix: 'C-b', detachKey: 'd', heldAlias: 'C-d', oneKey: 'F12' });
|
||||
const bar = banner['status-format[0]'];
|
||||
expect(bar).toContain('press #[bold]F12#[nobold] to get back to the codeman dashboard');
|
||||
// Even though both fallbacks still work, the bar must not offer them: a bar
|
||||
// listing three ways to leave is what the tester called way too complicated.
|
||||
expect(bar).not.toContain('Ctrl+B');
|
||||
expect(bar).not.toContain('or Ctrl+D');
|
||||
});
|
||||
|
||||
it('falls back to the chord when the key could not be claimed', () => {
|
||||
// Never advertise a key we did not get: a bar naming an inert key is the
|
||||
// original bug, in a new costume.
|
||||
const bar = buildAttachBanner({ prefix: 'C-b', detachKey: 'd', heldAlias: 'C-d' })['status-format[0]'];
|
||||
expect(bar).toContain('Ctrl+B then d');
|
||||
expect(bar).toContain('(or Ctrl+D)');
|
||||
expect(bar).not.toContain('F12');
|
||||
});
|
||||
});
|
||||
|
||||
describe('the held-Ctrl detach alias', () => {
|
||||
it('names the key a user produces when they never let go of Ctrl', () => {
|
||||
// The failure this exists for: "Ctrl+B then d" typed as one held chord
|
||||
|
||||
@@ -621,6 +621,15 @@ describe('parsePrefixBinding', () => {
|
||||
it('is case-sensitive, like tmux itself', () => {
|
||||
expect(parsePrefixBinding('bind-key -T prefix D choose-client', 'd')).toBeNull();
|
||||
});
|
||||
|
||||
it('reads the prefix-less root table too, where the one-key exit lives', () => {
|
||||
const root = ['bind-key -T root MouseDown1Pane select-pane -t =', 'bind-key -T root F12 detach-client'].join('\n');
|
||||
expect(parsePrefixBinding(root, 'F12', 'root')).toBe('detach-client');
|
||||
// Stock tmux has no F12 there, which is what makes it safe to claim.
|
||||
expect(parsePrefixBinding('bind-key -T root MouseDown1Pane select-pane -t =', 'F12', 'root')).toBeNull();
|
||||
// A prefix binding must not be mistaken for a root one.
|
||||
expect(parsePrefixBinding('bind-key -T prefix F12 detach-client', 'F12', 'root')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('TuiClient.clearLeakedAttachBanners', () => {
|
||||
|
||||
Reference in New Issue
Block a user