diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go index 13f6bfbabb6b56e68c5b9519730e51257a4039f8..038249277ffa572755de160f0d404525def803b7 100644 --- a/internal/tui/components/chat/editor/editor.go +++ b/internal/tui/components/chat/editor/editor.go @@ -157,6 +157,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 filepicker.FilePickedMsg: if len(m.attachments) >= maxAttachments { return m, util.ReportError(fmt.Errorf("cannot add more than %d images", maxAttachments)) @@ -252,7 +255,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 4362ff1ea962ec76939ada4bd3fd330b521739b9..5cf5618b6705a87a41661bfe1d8d9b5d481da951 100644 --- a/internal/tui/page/chat/chat.go +++ b/internal/tui/page/chat/chat.go @@ -152,6 +152,10 @@ func (p *chatPage) Init() 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.editor.Update(msg) + p.editor = m.(editor.Editor) + return p, cmd case tea.WindowSizeMsg: return p, p.SetSize(msg.Width, msg.Height) case CancelTimerExpiredMsg: diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 28469caf2ed979eef89d90bdecb90b140154c77d..f8b30c4a5f761c40bffb07667b92fc89bf631e04 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -99,7 +99,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)