on main help sign in
chore: change open editor
28be096Kujtim Hoxha
internal/tui/components/chat/editor/editor.go+12
@@ -22,6 +22,7 @@ import (
22 "github.com/charmbracelet/crush/internal/tui/components/completions"
22 "github.com/charmbracelet/crush/internal/tui/components/completions"
23 "github.com/charmbracelet/crush/internal/tui/components/core/layout"
23 "github.com/charmbracelet/crush/internal/tui/components/core/layout"
24 "github.com/charmbracelet/crush/internal/tui/components/dialogs"
24 "github.com/charmbracelet/crush/internal/tui/components/dialogs"
25+ "github.com/charmbracelet/crush/internal/tui/components/dialogs/commands"
25 "github.com/charmbracelet/crush/internal/tui/components/dialogs/filepicker"
26 "github.com/charmbracelet/crush/internal/tui/components/dialogs/filepicker"
26 "github.com/charmbracelet/crush/internal/tui/components/dialogs/quit"
27 "github.com/charmbracelet/crush/internal/tui/components/dialogs/quit"
27 "github.com/charmbracelet/crush/internal/tui/styles"
28 "github.com/charmbracelet/crush/internal/tui/styles"
@@ -38,6 +39,7 @@ type Editor interface {
38
39
39 SetSession(session session.Session) tea.Cmd
40 SetSession(session session.Session) tea.Cmd
40 IsCompletionsOpen() bool
41 IsCompletionsOpen() bool
42+ HasAttachments() bool
41 Cursor() *tea.Cursor
43 Cursor() *tea.Cursor
42}
44}
43
45
@@ -206,6 +208,12 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
206 m.completionsStartIndex = 0
208 m.completionsStartIndex = 0
207 }
209 }
208 }
210 }
211+
212+ case commands.OpenExternalEditorMsg:
213+ if m.app.CoderAgent.IsSessionBusy(m.session.ID) {
214+ return m, util.ReportWarn("Agent is working, please wait...")
215+ }
216+ return m, m.openEditor(m.textarea.Value())
209 case OpenEditorMsg:
217 case OpenEditorMsg:
210 m.textarea.SetValue(msg.Text)
218 m.textarea.SetValue(msg.Text)
211 m.textarea.MoveToEnd()
219 m.textarea.MoveToEnd()
@@ -482,6 +490,10 @@ func (c *editorCmp) IsCompletionsOpen() bool {
482 return c.isCompletionsOpen
490 return c.isCompletionsOpen
483}
491}
484
492
493+func (c *editorCmp) HasAttachments() bool {
494+ return len(c.attachments) > 0
495+}
496+
485func New(app *app.App) Editor {
497func New(app *app.App) Editor {
486 t := styles.CurrentTheme()
498 t := styles.CurrentTheme()
487 ta := textarea.New()
499 ta := textarea.New()
internal/tui/components/chat/editor/keys.go+2−2
@@ -22,8 +22,8 @@ func DefaultEditorKeyMap() EditorKeyMap {
22 key.WithHelp("enter", "send"),
22 key.WithHelp("enter", "send"),
23 ),
23 ),
24 OpenEditor: key.NewBinding(
24 OpenEditor: key.NewBinding(
25− key.WithKeys("ctrl+v"),
25+ key.WithKeys("ctrl+o"),
26− key.WithHelp("ctrl+v", "open editor"),
26+ key.WithHelp("ctrl+o", "open editor"),
27 ),
27 ),
28 Newline: key.NewBinding(
28 Newline: key.NewBinding(
29 key.WithKeys("shift+enter", "ctrl+j"),
29 key.WithKeys("shift+enter", "ctrl+j"),
internal/tui/components/dialogs/commands/commands.go+16
@@ -1,6 +1,8 @@
1package commands
1package commands
2
2
3import (
3import (
4+ "os"
5+
4 "github.com/charmbracelet/bubbles/v2/help"
6 "github.com/charmbracelet/bubbles/v2/help"
5 "github.com/charmbracelet/bubbles/v2/key"
7 "github.com/charmbracelet/bubbles/v2/key"
6 tea "github.com/charmbracelet/bubbletea/v2"
8 tea "github.com/charmbracelet/bubbletea/v2"
@@ -66,6 +68,7 @@ type (
66 ToggleHelpMsg struct{}
68 ToggleHelpMsg struct{}
67 ToggleCompactModeMsg struct{}
69 ToggleCompactModeMsg struct{}
68 ToggleThinkingMsg struct{}
70 ToggleThinkingMsg struct{}
71+ OpenExternalEditorMsg struct{}
69 CompactMsg struct {
72 CompactMsg struct {
70 SessionID string
73 SessionID string
71 }
74 }
@@ -343,6 +346,19 @@ func (c *commandDialogCmp) defaultCommands() []Command {
343 }
346 }
344 }
347 }
345
348
349+ // Add external editor command if $EDITOR is available
350+ if os.Getenv("EDITOR") != "" {
351+ commands = append(commands, Command{
352+ ID: "open_external_editor",
353+ Title: "Open External Editor",
354+ Shortcut: "ctrl+o",
355+ Description: "Open external editor to compose message",
356+ Handler: func(cmd Command) tea.Cmd {
357+ return util.CmdHandler(OpenExternalEditorMsg{})
358+ },
359+ })
360+ }
361+
346 return append(commands, []Command{
362 return append(commands, []Command{
347 {
363 {
348 ID: "toggle_help",
364 ID: "toggle_help",
internal/tui/page/chat/chat.go+11−2
@@ -204,6 +204,10 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
204 return p, tea.Batch(p.SetSize(p.width, p.height), cmd)
204 return p, tea.Batch(p.SetSize(p.width, p.height), cmd)
205 case commands.ToggleThinkingMsg:
205 case commands.ToggleThinkingMsg:
206 return p, p.toggleThinking()
206 return p, p.toggleThinking()
207+ case commands.OpenExternalEditorMsg:
208+ u, cmd := p.editor.Update(msg)
209+ p.editor = u.(editor.Editor)
210+ return p, cmd
207 case pubsub.Event[session.Session]:
211 case pubsub.Event[session.Session]:
208 u, cmd := p.header.Update(msg)
212 u, cmd := p.header.Update(msg)
209 p.header = u.(header.Header)
213 p.header = u.(header.Header)
@@ -896,9 +900,13 @@ func (p *chatPage) Help() help.KeyMap {
896 key.WithHelp("/", "add file"),
900 key.WithHelp("/", "add file"),
897 ),
901 ),
898 key.NewBinding(
902 key.NewBinding(
899− key.WithKeys("ctrl+v"),
903+ key.WithKeys("ctrl+o"),
900− key.WithHelp("ctrl+v", "open editor"),
904+ key.WithHelp("ctrl+o", "open editor"),
901 ),
905 ),
906+ })
907+
908+ if p.editor.HasAttachments() {
909+ fullList = append(fullList, []key.Binding{
902 key.NewBinding(
910 key.NewBinding(
903 key.WithKeys("ctrl+r"),
911 key.WithKeys("ctrl+r"),
904 key.WithHelp("ctrl+r+{i}", "delete attachment at index i"),
912 key.WithHelp("ctrl+r+{i}", "delete attachment at index i"),
@@ -912,6 +920,7 @@ func (p *chatPage) Help() help.KeyMap {
912 key.WithHelp("esc", "cancel delete mode"),
920 key.WithHelp("esc", "cancel delete mode"),
913 ),
921 ),
914 })
922 })
923+ }
915 }
924 }
916 shortList = append(shortList,
925 shortList = append(shortList,
917 // Quit
926 // Quit
internal/tui/tui.go+3
@@ -3,6 +3,7 @@ package tui
3import (
3import (
4 "context"
4 "context"
5 "fmt"
5 "fmt"
6+ "log/slog"
6 "strings"
7 "strings"
7 "time"
8 "time"
8
9
@@ -258,6 +259,8 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
258 return a, tea.Batch(cmds...)
259 return a, tea.Batch(cmds...)
259 // Key Press Messages
260 // Key Press Messages
260 case tea.KeyPressMsg:
261 case tea.KeyPressMsg:
262+
263+ slog.Info("TUI Update", "msg", msg, "key", msg.String())
261 return a, a.handleKeyPressMsg(msg)
264 return a, a.handleKeyPressMsg(msg)
262
265
263 case tea.MouseWheelMsg:
266 case tea.MouseWheelMsg: