From 967930f9bc4056334f0681f547b85e1229da982b Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Wed, 28 Oct 2026 01:30:33 +0100 Subject: [PATCH] Make Alt and a digit set the send target as /window does (closes #221) In neoirc-cli, Alt and a digit switched the window but kept the send target, so typed text went to the window the user had left. The key now runs /window with that digit through the input handler. /window 0 now clears the send target. The status window has no target, but the command used to keep the previous one. Model: opus-5-5 --- internal/cli/app.go | 4 +++ internal/cli/app_internal_test.go | 57 +++++++++++++++++++++++++++++++ internal/cli/ui.go | 7 ++-- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/internal/cli/app.go b/internal/cli/app.go index eae6d63..acadfc3 100644 --- a/internal/cli/app.go +++ b/internal/cli/app.go @@ -627,6 +627,10 @@ func (a *App) cmdWindow(args string) { nick, buf.Name, "connected", ) } else { + a.mu.Lock() + a.target = "" + a.mu.Unlock() + a.ui.SetStatus(nick, "", "connected") } } diff --git a/internal/cli/app_internal_test.go b/internal/cli/app_internal_test.go index 15dba69..54586f2 100644 --- a/internal/cli/app_internal_test.go +++ b/internal/cli/app_internal_test.go @@ -219,6 +219,63 @@ func TestJoinResponse(t *testing.T) { } } +// TestAltDigit checks that Alt and a digit shows that window and +// makes its channel or user the target, as /window does. Window +// 0, the status window, leaves no target. +func TestAltDigit(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + digit rune + // The buffer shown and the target after the key. + wantBuffer string + wantTarget string + }{ + { + name: "channel window", + digit: '1', + wantBuffer: testChannel, + wantTarget: testChannel, + }, + { + name: "status window", + digit: '0', + wantBuffer: "(status)", + wantTarget: "", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + app := &App{ui: NewUI(), nick: testNick, target: testOtherNick} + app.ui.OnInput(app.handleInput) + runUI(t, app.ui) + + // Window 1 is the channel. Window 2, the one shown, is + // the other user's. + app.ui.SwitchToBuffer(testChannel) + app.ui.SwitchToBuffer(testOtherNick) + + key := tcell.NewEventKey(tcell.KeyRune, test.digit, tcell.ModAlt) + app.ui.app.GetInputCapture()(key) + + var shown string + + app.ui.app.QueueUpdate(func() { + shown = app.ui.buffers[app.ui.currentBuffer].Name + }) + + if shown != test.wantBuffer || app.target != test.wantTarget { + t.Fatalf("got buffer %s and target %q, want %s and %q", + shown, app.target, test.wantBuffer, test.wantTarget) + } + }) + } +} + // TestOwnEventFromOtherClient checks that a message, notice, // join or part that the user's session makes from another // client shows as one line in the buffer it belongs to. diff --git a/internal/cli/ui.go b/internal/cli/ui.go index b36d714..581ba0b 100644 --- a/internal/cli/ui.go +++ b/internal/cli/ui.go @@ -240,10 +240,13 @@ func (ui *UI) initKeyCapture() { return event } + // Alt and a digit runs /window with that digit. + // SwitchBuffer alone would leave the target as it was. r := event.Rune() if r >= '0' && r <= '9' { - idx := int(r - '0') - ui.SwitchBuffer(idx) + if ui.onInput != nil { + ui.onInput("/window " + string(r)) + } return nil }