From 7a27e6bace6e9551292c7ce1122b43a0da8ee5a8 Mon Sep 17 00:00:00 2001 From: CnsMaple Date: Fri, 5 Jun 2026 16:30:49 +0800 Subject: [PATCH 1/2] feat(ui): rebind ctrl+c to clear input, move quit to ctrl+q, add ctrl+u restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Reassign Quit binding from ctrl+c to ctrl+q - Add Editor.ClearInput (ctrl+c) to reset the textarea when focused - Add Editor.RestoreInput (ctrl+u) to restore the most recently cleared value - Update quit dialog and commands panel shortcuts to reflect ctrl+q - Surface new bindings in ShortHelp/FullHelp 💘 Generated with Crush Assisted-by: Crush:MiniMax-M3 --- internal/ui/dialog/commands.go | 2 +- internal/ui/dialog/quit.go | 8 ++++---- internal/ui/model/keys.go | 16 ++++++++++++++-- internal/ui/model/ui.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/internal/ui/dialog/commands.go b/internal/ui/dialog/commands.go index 6e17db70d0..b1f7900858 100644 --- a/internal/ui/dialog/commands.go +++ b/internal/ui/dialog/commands.go @@ -531,7 +531,7 @@ func (c *Commands) defaultCommands() []*CommandItem { commands = append( commands, - NewCommandItem(c.com.Styles, "quit", "Quit", "ctrl+c", tea.QuitMsg{}).WithAliases("exit"), + NewCommandItem(c.com.Styles, "quit", "Quit", "ctrl+q", tea.QuitMsg{}).WithAliases("exit"), ) return commands diff --git a/internal/ui/dialog/quit.go b/internal/ui/dialog/quit.go index 531f25bea8..0fee6dbbfd 100644 --- a/internal/ui/dialog/quit.go +++ b/internal/ui/dialog/quit.go @@ -43,8 +43,8 @@ func NewQuit(com *common.Common) *Quit { key.WithHelp("enter/space", "confirm"), ) q.keyMap.Yes = key.NewBinding( - key.WithKeys("y", "Y", "ctrl+c"), - key.WithHelp("y/Y/ctrl+c", "yes"), + key.WithKeys("y", "Y", "ctrl+q"), + key.WithHelp("y/Y/ctrl+q", "yes"), ) q.keyMap.No = key.NewBinding( key.WithKeys("n", "N"), @@ -56,8 +56,8 @@ func NewQuit(com *common.Common) *Quit { ) q.keyMap.Close = CloseKey q.keyMap.Quit = key.NewBinding( - key.WithKeys("ctrl+c"), - key.WithHelp("ctrl+c", "quit"), + key.WithKeys("ctrl+q"), + key.WithHelp("ctrl+q", "quit"), ) return q } diff --git a/internal/ui/model/keys.go b/internal/ui/model/keys.go index ebf377035e..27bbd9ffd5 100644 --- a/internal/ui/model/keys.go +++ b/internal/ui/model/keys.go @@ -21,6 +21,10 @@ type KeyMap struct { // History navigation HistoryPrev key.Binding HistoryNext key.Binding + + // Clear current input + ClearInput key.Binding + RestoreInput key.Binding } Chat struct { @@ -70,8 +74,8 @@ type KeyMap struct { func DefaultKeyMap() KeyMap { km := KeyMap{ Quit: key.NewBinding( - key.WithKeys("ctrl+c"), - key.WithHelp("ctrl+c", "quit"), + key.WithKeys("ctrl+q"), + key.WithHelp("ctrl+q", "quit"), ), Help: key.NewBinding( key.WithKeys("ctrl+g"), @@ -156,6 +160,14 @@ func DefaultKeyMap() KeyMap { km.Editor.HistoryNext = key.NewBinding( key.WithKeys("down"), ) + km.Editor.ClearInput = key.NewBinding( + key.WithKeys("ctrl+c"), + key.WithHelp("ctrl+c", "clear input"), + ) + km.Editor.RestoreInput = key.NewBinding( + key.WithKeys("ctrl+u"), + key.WithHelp("ctrl+u", "restore cleared input"), + ) km.Chat.NewSession = key.NewBinding( key.WithKeys("ctrl+n"), diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 0c6102572c..820a85fd44 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -209,6 +209,10 @@ type UI struct { // Editor components textarea textarea.Model + // lastClearedInput stores the most recently cleared input value so it + // can be restored with Editor.RestoreInput (ctrl+shift+c). + lastClearedInput string + // Attachment list attachments *attachments.Attachments @@ -2036,6 +2040,26 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd { if cmd := m.openCommandsDialog(); cmd != nil { cmds = append(cmds, cmd) } + case key.Matches(msg, m.keyMap.Editor.ClearInput): + if m.textarea.Value() != "" { + m.lastClearedInput = m.textarea.Value() + prevHeight := m.textarea.Height() + m.textarea.Reset() + if cmd := m.handleTextareaHeightChange(prevHeight); cmd != nil { + cmds = append(cmds, cmd) + } + } + m.closeCompletions() + case key.Matches(msg, m.keyMap.Editor.RestoreInput): + if m.lastClearedInput != "" { + prevHeight := m.textarea.Height() + m.textarea.SetValue(m.lastClearedInput) + m.textarea.MoveToEnd() + if cmd := m.handleTextareaHeightChange(prevHeight); cmd != nil { + cmds = append(cmds, cmd) + } + m.lastClearedInput = "" + } default: if handleGlobalKeys(msg) { // Handle global keys first before passing to textarea. @@ -2403,6 +2427,8 @@ func (m *UI) ShortHelp() []key.Binding { binds = append( binds, k.Editor.Newline, + k.Editor.ClearInput, + k.Editor.RestoreInput, ) case uiFocusMain: binds = append( @@ -2495,6 +2521,8 @@ func (m *UI) FullHelp() [][]key.Binding { case uiFocusEditor: editorBinds := []key.Binding{ k.Editor.Newline, + k.Editor.ClearInput, + k.Editor.RestoreInput, k.Editor.MentionFile, k.Editor.OpenEditor, } @@ -2550,6 +2578,8 @@ func (m *UI) FullHelp() [][]key.Binding { ) editorBinds := []key.Binding{ k.Editor.Newline, + k.Editor.ClearInput, + k.Editor.RestoreInput, k.Editor.MentionFile, k.Editor.OpenEditor, } From f3ce8d2f924e131b37d62817cd16bf39bb38aef0 Mon Sep 17 00:00:00 2001 From: CnsMaple Date: Fri, 5 Jun 2026 17:04:28 +0800 Subject: [PATCH 2/2] feat(ui): hide ctrl+c/ctrl+u from the bottom ShortHelp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the clear/restore input hints out of the always-visible bottom bar; they remain in the expanded help shown via ctrl+g. 💘 Generated with Crush Assisted-by: Crush:MiniMax-M3 --- internal/ui/model/ui.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 820a85fd44..fa85479a34 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -2427,8 +2427,6 @@ func (m *UI) ShortHelp() []key.Binding { binds = append( binds, k.Editor.Newline, - k.Editor.ClearInput, - k.Editor.RestoreInput, ) case uiFocusMain: binds = append(