diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go index 1464512a403d8208aea669dced2811e3efa4bae8..3042b84c97a528246d4edc11c2a9ead89eb0aa38 100644 --- a/internal/tui/components/chat/editor/editor.go +++ b/internal/tui/components/chat/editor/editor.go @@ -145,6 +145,9 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd var cmds []tea.Cmd switch msg := msg.(type) { + case tea.KeyboardEnhancementsMsg: + m.keyMap.keyboard = msg + return m, nil case chat.SessionSelectedMsg: if msg.ID != m.session.ID { m.session = msg @@ -245,7 +248,11 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.deleteMode = false return m, nil } - // Hanlde Enter key + if key.Matches(msg, m.keyMap.Newline) { + m.textarea.InsertRune('\n') + return m, nil + } + // Handle Enter key if m.textarea.Focused() && key.Matches(msg, m.keyMap.SendMessage) { value := m.textarea.Value() if len(value) > 0 && value[len(value)-1] == '\\' { diff --git a/internal/tui/components/chat/editor/keys.go b/internal/tui/components/chat/editor/keys.go index c64a92d526a1a81e558909fe5500b2bf1d4e3990..aa2ba1ee44ce7fe9928e7e812acea3898a7496e5 100644 --- a/internal/tui/components/chat/editor/keys.go +++ b/internal/tui/components/chat/editor/keys.go @@ -2,12 +2,16 @@ package editor import ( "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" ) type EditorKeyMap struct { AddFile key.Binding SendMessage key.Binding OpenEditor key.Binding + Newline key.Binding + + keyboard tea.KeyboardEnhancementsMsg } func DefaultEditorKeyMap() EditorKeyMap { @@ -24,15 +28,27 @@ func DefaultEditorKeyMap() EditorKeyMap { key.WithKeys("ctrl+e"), key.WithHelp("ctrl+e", "open editor"), ), + Newline: key.NewBinding( + key.WithKeys("shift+enter", "ctrl+j"), + // "ctrl+j" is a common keybinding for newline in many editors. If + // the terminal supports "shift+enter", we substitute the help text + // to reflect that. + key.WithHelp("ctrl+j", "newline"), + ), } } // KeyBindings implements layout.KeyMapProvider func (k EditorKeyMap) KeyBindings() []key.Binding { + newline := k.Newline + if k.keyboard.SupportsKeyDisambiguation() { + newline.SetHelp("shift+enter", newline.Help().Desc) + } return []key.Binding{ k.AddFile, k.SendMessage, k.OpenEditor, + newline, } } diff --git a/internal/tui/page/chat/chat.go b/internal/tui/page/chat/chat.go index 59b8ac86da3901bfb5a3affe8aeedf27f293a507..5c3a769d23ae085b342d330e4089831179ad43bf 100644 --- a/internal/tui/page/chat/chat.go +++ b/internal/tui/page/chat/chat.go @@ -81,6 +81,10 @@ func (p *chatPage) cancelTimerCmd() tea.Cmd { func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd switch msg := msg.(type) { + case tea.KeyboardEnhancementsMsg: + m, cmd := p.layout.Update(msg) + p.layout = m.(layout.SplitPaneLayout) + return p, cmd case CancelTimerExpiredMsg: p.cancelPending = false return p, nil diff --git a/internal/tui/tui.go b/internal/tui/tui.go index dd0d4f9085d92b20aa92c8d2f25227b5e2206816..9efecb2ac9aab48bd24881176b1f1b530c1db658 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -115,7 +115,14 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyboardEnhancementsMsg: - return a, nil + for id, page := range a.pages { + m, pageCmd := page.Update(msg) + a.pages[id] = m.(util.Model) + if pageCmd != nil { + cmds = append(cmds, pageCmd) + } + } + return a, tea.Batch(cmds...) case tea.WindowSizeMsg: return a, a.handleWindowResize(msg.Width, msg.Height)