Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions internal/tui/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package tui
import (
"strings"
"testing"

tea "github.com/charmbracelet/bubbletea"
)

func TestCommandPrefix(t *testing.T) {
Expand Down Expand Up @@ -128,6 +130,36 @@ func TestCommandCompletion(t *testing.T) {
}
}

// While the command popup is open, plain keys must keep flowing into the
// input (narrowing the filter) instead of being swallowed.
func TestCommandPopupKeepsTyping(t *testing.T) {
m := wired(t)
m.Update(key("/")) // opens the command popup
if !m.ac.open || m.ac.mode != acCmd {
t.Fatalf("command popup not open: %+v", m.ac)
}
m.Update(key("h")) // must reach the input, not be swallowed
if got := m.ta.Value(); got != "/h" {
t.Fatalf("input after typing = %q, want %q", got, "/h")
}
if !m.ac.open || m.ac.mode != acCmd {
t.Fatal("popup should stay open while the name is typed")
}
if len(m.ac.items) != 1 || m.ac.items[0].ID != "/help" {
t.Errorf("popup should re-filter to /help: %+v", m.ac.items)
}
// Backspace edits the input too.
m.Update(tea.KeyMsg{Type: tea.KeyBackspace})
if got := m.ta.Value(); got != "/" {
t.Errorf("input after backspace = %q, want %q", got, "/")
}
// ctrl+c still quits while the popup has capture.
m.Update(key("ctrl+c"))
if !m.quitting {
t.Error("ctrl+c should quit while the popup is open")
}
}

func TestCommandPopupEnterExecutes(t *testing.T) {
m := wired(t)
m.msgs = append(m.msgs, message{role: roleUser, content: "x"})
Expand Down
12 changes: 10 additions & 2 deletions internal/tui/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,16 @@ func (m *Model) handleACKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
case "esc":
m.closeAC()
return m, nil
}
return m, nil
case "ctrl+c":
m.quitting = true
return m, tea.Quit
}
// Any other key is plain input: forward it to the textarea, then
// re-evaluate the popup against the new value — typing narrows the
// filter, backspace widens it, a space ends command completion.
var cmd tea.Cmd
m.ta, cmd = m.ta.Update(msg)
return m, tea.Batch(cmd, m.syncAC())
}

// acMode selects what the completion popup is completing.
Expand Down