Detailed changes
@@ -22,6 +22,7 @@ import (
"github.com/charmbracelet/crush/internal/tui/components/completions"
"github.com/charmbracelet/crush/internal/tui/components/core/layout"
"github.com/charmbracelet/crush/internal/tui/components/dialogs"
+ "github.com/charmbracelet/crush/internal/tui/components/dialogs/commands"
"github.com/charmbracelet/crush/internal/tui/components/dialogs/filepicker"
"github.com/charmbracelet/crush/internal/tui/components/dialogs/quit"
"github.com/charmbracelet/crush/internal/tui/styles"
@@ -38,6 +39,7 @@ type Editor interface {
SetSession(session session.Session) tea.Cmd
IsCompletionsOpen() bool
+ HasAttachments() bool
Cursor() *tea.Cursor
}
@@ -206,6 +208,12 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.completionsStartIndex = 0
}
}
+
+ case commands.OpenExternalEditorMsg:
+ if m.app.CoderAgent.IsSessionBusy(m.session.ID) {
+ return m, util.ReportWarn("Agent is working, please wait...")
+ }
+ return m, m.openEditor(m.textarea.Value())
case OpenEditorMsg:
m.textarea.SetValue(msg.Text)
m.textarea.MoveToEnd()
@@ -482,6 +490,10 @@ func (c *editorCmp) IsCompletionsOpen() bool {
return c.isCompletionsOpen
}
+func (c *editorCmp) HasAttachments() bool {
+ return len(c.attachments) > 0
+}
+
func New(app *app.App) Editor {
t := styles.CurrentTheme()
ta := textarea.New()
@@ -22,8 +22,8 @@ func DefaultEditorKeyMap() EditorKeyMap {
key.WithHelp("enter", "send"),
),
OpenEditor: key.NewBinding(
- key.WithKeys("ctrl+v"),
- key.WithHelp("ctrl+v", "open editor"),
+ key.WithKeys("ctrl+o"),
+ key.WithHelp("ctrl+o", "open editor"),
),
Newline: key.NewBinding(
key.WithKeys("shift+enter", "ctrl+j"),
@@ -1,6 +1,8 @@
package commands
import (
+ "os"
+
"github.com/charmbracelet/bubbles/v2/help"
"github.com/charmbracelet/bubbles/v2/key"
tea "github.com/charmbracelet/bubbletea/v2"
@@ -66,6 +68,7 @@ type (
ToggleHelpMsg struct{}
ToggleCompactModeMsg struct{}
ToggleThinkingMsg struct{}
+ OpenExternalEditorMsg struct{}
CompactMsg struct {
SessionID string
}
@@ -343,6 +346,19 @@ func (c *commandDialogCmp) defaultCommands() []Command {
}
}
+ // Add external editor command if $EDITOR is available
+ if os.Getenv("EDITOR") != "" {
+ commands = append(commands, Command{
+ ID: "open_external_editor",
+ Title: "Open External Editor",
+ Shortcut: "ctrl+o",
+ Description: "Open external editor to compose message",
+ Handler: func(cmd Command) tea.Cmd {
+ return util.CmdHandler(OpenExternalEditorMsg{})
+ },
+ })
+ }
+
return append(commands, []Command{
{
ID: "toggle_help",
@@ -204,6 +204,10 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return p, tea.Batch(p.SetSize(p.width, p.height), cmd)
case commands.ToggleThinkingMsg:
return p, p.toggleThinking()
+ case commands.OpenExternalEditorMsg:
+ u, cmd := p.editor.Update(msg)
+ p.editor = u.(editor.Editor)
+ return p, cmd
case pubsub.Event[session.Session]:
u, cmd := p.header.Update(msg)
p.header = u.(header.Header)
@@ -896,9 +900,13 @@ func (p *chatPage) Help() help.KeyMap {
key.WithHelp("/", "add file"),
),
key.NewBinding(
- key.WithKeys("ctrl+v"),
- key.WithHelp("ctrl+v", "open editor"),
+ key.WithKeys("ctrl+o"),
+ key.WithHelp("ctrl+o", "open editor"),
),
+ })
+
+ if p.editor.HasAttachments() {
+ fullList = append(fullList, []key.Binding{
key.NewBinding(
key.WithKeys("ctrl+r"),
key.WithHelp("ctrl+r+{i}", "delete attachment at index i"),
@@ -912,6 +920,7 @@ func (p *chatPage) Help() help.KeyMap {
key.WithHelp("esc", "cancel delete mode"),
),
})
+ }
}
shortList = append(shortList,
// Quit
@@ -3,6 +3,7 @@ package tui
import (
"context"
"fmt"
+ "log/slog"
"strings"
"time"
@@ -258,6 +259,8 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, tea.Batch(cmds...)
// Key Press Messages
case tea.KeyPressMsg:
+
+ slog.Info("TUI Update", "msg", msg, "key", msg.String())
return a, a.handleKeyPressMsg(msg)
case tea.MouseWheelMsg: