on main help sign in
remove edit/normal mode
2c5003eKujtim Hoxha
README.md+1−1
@@ -1,4 +1,4 @@
1−# OpenCode
1+# ⌬ OpenCode
2
2
3> **⚠️ Early Development Notice:** This project is in early development and is not yet ready for production use. Features may change, break, or be incomplete. Use at your own risk.
3> **⚠️ Early Development Notice:** This project is in early development and is not yet ready for production use. Features may change, break, or be incomplete. Use at your own risk.
4
4
internal/tui/components/chat/editor.go+23−41
@@ -26,7 +26,6 @@ type FocusEditorMsg bool
26type focusedEditorKeyMaps struct {
26type focusedEditorKeyMaps struct {
27 Send key.Binding
27 Send key.Binding
28 OpenEditor key.Binding
28 OpenEditor key.Binding
29− Blur key.Binding
30}
29}
31
30
32type bluredEditorKeyMaps struct {
31type bluredEditorKeyMaps struct {
@@ -35,30 +34,11 @@ type bluredEditorKeyMaps struct {
35 OpenEditor key.Binding
34 OpenEditor key.Binding
36}
35}
37
36
38−var focusedKeyMaps = focusedEditorKeyMaps{
37+var KeyMaps = focusedEditorKeyMaps{
39 Send: key.NewBinding(
38 Send: key.NewBinding(
40 key.WithKeys("ctrl+s"),
39 key.WithKeys("ctrl+s"),
41 key.WithHelp("ctrl+s", "send message"),
40 key.WithHelp("ctrl+s", "send message"),
42 ),
41 ),
43− Blur: key.NewBinding(
44− key.WithKeys("esc"),
45− key.WithHelp("esc", "focus messages"),
46− ),
47− OpenEditor: key.NewBinding(
48− key.WithKeys("ctrl+e"),
49− key.WithHelp("ctrl+e", "open editor"),
50− ),
51−}
52−
53−var bluredKeyMaps = bluredEditorKeyMaps{
54− Send: key.NewBinding(
55− key.WithKeys("ctrl+s", "enter"),
56− key.WithHelp("ctrl+s/enter", "send message"),
57− ),
58− Focus: key.NewBinding(
59− key.WithKeys("i"),
60− key.WithHelp("i", "focus editor"),
61− ),
62 OpenEditor: key.NewBinding(
42 OpenEditor: key.NewBinding(
63 key.WithKeys("ctrl+e"),
43 key.WithKeys("ctrl+e"),
64 key.WithHelp("ctrl+e", "open editor"),
44 key.WithHelp("ctrl+e", "open editor"),
@@ -88,6 +68,9 @@ func openEditor() tea.Cmd {
88 if err != nil {
68 if err != nil {
89 return util.ReportError(err)
69 return util.ReportError(err)
90 }
70 }
71+ if len(content) == 0 {
72+ return util.ReportWarn("Message is empty")
73+ }
91 os.Remove(tmpfile.Name())
74 os.Remove(tmpfile.Name())
92 return SendMsg{
75 return SendMsg{
93 Text: string(content),
76 Text: string(content),
@@ -106,7 +89,6 @@ func (m *editorCmp) send() tea.Cmd {
106
89
107 value := m.textarea.Value()
90 value := m.textarea.Value()
108 m.textarea.Reset()
91 m.textarea.Reset()
109− m.textarea.Blur()
110 if value == "" {
92 if value == "" {
111 return nil
93 return nil
112 }
94 }
@@ -131,26 +113,32 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
131 return m, tea.Batch(textarea.Blink, util.CmdHandler(EditorFocusMsg(true)))
113 return m, tea.Batch(textarea.Blink, util.CmdHandler(EditorFocusMsg(true)))
132 }
114 }
133 case tea.KeyMsg:
115 case tea.KeyMsg:
134− if key.Matches(msg, focusedKeyMaps.OpenEditor) {
116+ if key.Matches(msg, messageKeys.PageUp) || key.Matches(msg, messageKeys.PageDown) ||
117+ key.Matches(msg, messageKeys.HalfPageUp) || key.Matches(msg, messageKeys.HalfPageDown) {
118+ return m, nil
119+ }
120+ if key.Matches(msg, KeyMaps.OpenEditor) {
135 if m.app.CoderAgent.IsSessionBusy(m.session.ID) {
121 if m.app.CoderAgent.IsSessionBusy(m.session.ID) {
136 return m, util.ReportWarn("Agent is working, please wait...")
122 return m, util.ReportWarn("Agent is working, please wait...")
137 }
123 }
138 return m, openEditor()
124 return m, openEditor()
139 }
125 }
140 // if the key does not match any binding, return
126 // if the key does not match any binding, return
141− if m.textarea.Focused() && key.Matches(msg, focusedKeyMaps.Send) {
127+ if m.textarea.Focused() && key.Matches(msg, KeyMaps.Send) {
142 return m, m.send()
128 return m, m.send()
143 }
129 }
130+
131+ // Handle Enter key
144− if !m.textarea.Focused() && key.Matches(msg, bluredKeyMaps.Send) {
132+ if m.textarea.Focused() && msg.String() == "enter" {
145− return m, m.send()
133+ value := m.textarea.Value()
146− }
134+ if len(value) > 0 && value[len(value)-1] == '\\' {
147− if m.textarea.Focused() && key.Matches(msg, focusedKeyMaps.Blur) {
135+ // If the last character is a backslash, remove it and add a newline
148− m.textarea.Blur()
136+ m.textarea.SetValue(value[:len(value)-1] + "\n")
149− return m, util.CmdHandler(EditorFocusMsg(false))
137+ return m, nil
150− }
138+ } else {
151− if !m.textarea.Focused() && key.Matches(msg, bluredKeyMaps.Focus) {
139+ // Otherwise, send the message
152− m.textarea.Focus()
140+ return m, m.send()
153− return m, tea.Batch(textarea.Blink, util.CmdHandler(EditorFocusMsg(true)))
141+ }
154 }
142 }
155 }
143 }
156 m.textarea, cmd = m.textarea.Update(msg)
144 m.textarea, cmd = m.textarea.Update(msg)
@@ -175,13 +163,7 @@ func (m *editorCmp) GetSize() (int, int) {
175
163
176func (m *editorCmp) BindingKeys() []key.Binding {
164func (m *editorCmp) BindingKeys() []key.Binding {
177 bindings := []key.Binding{}
165 bindings := []key.Binding{}
178− if m.textarea.Focused() {
179− bindings = append(bindings, layout.KeyMapToSlice(focusedKeyMaps)...)
166+ bindings = append(bindings, layout.KeyMapToSlice(KeyMaps)...)
180− } else {
181− bindings = append(bindings, layout.KeyMapToSlice(bluredKeyMaps)...)
182− }
183−
184− bindings = append(bindings, layout.KeyMapToSlice(m.textarea.KeyMap)...)
185 return bindings
167 return bindings
186}
168}
187
169
internal/tui/components/chat/list.go+41−22
@@ -14,7 +14,6 @@ import (
14 "github.com/kujtimiihoxha/opencode/internal/message"
14 "github.com/kujtimiihoxha/opencode/internal/message"
15 "github.com/kujtimiihoxha/opencode/internal/pubsub"
15 "github.com/kujtimiihoxha/opencode/internal/pubsub"
16 "github.com/kujtimiihoxha/opencode/internal/session"
16 "github.com/kujtimiihoxha/opencode/internal/session"
17− "github.com/kujtimiihoxha/opencode/internal/tui/layout"
18 "github.com/kujtimiihoxha/opencode/internal/tui/styles"
17 "github.com/kujtimiihoxha/opencode/internal/tui/styles"
19 "github.com/kujtimiihoxha/opencode/internal/tui/util"
18 "github.com/kujtimiihoxha/opencode/internal/tui/util"
20)
19)
@@ -26,7 +25,6 @@ type cacheItem struct {
26type messagesCmp struct {
25type messagesCmp struct {
27 app *app.App
26 app *app.App
28 width, height int
27 width, height int
29− writingMode bool
30 viewport viewport.Model
28 viewport viewport.Model
31 session session.Session
29 session session.Session
32 messages []message.Message
30 messages []message.Message
@@ -38,6 +36,32 @@ type messagesCmp struct {
38}
36}
39type renderFinishedMsg struct{}
37type renderFinishedMsg struct{}
40
38
39+type MessageKeys struct {
40+ PageDown key.Binding
41+ PageUp key.Binding
42+ HalfPageUp key.Binding
43+ HalfPageDown key.Binding
44+}
45+
46+var messageKeys = MessageKeys{
47+ PageDown: key.NewBinding(
48+ key.WithKeys("pgdown"),
49+ key.WithHelp("f/pgdn", "page down"),
50+ ),
51+ PageUp: key.NewBinding(
52+ key.WithKeys("pgup"),
53+ key.WithHelp("b/pgup", "page up"),
54+ ),
55+ HalfPageUp: key.NewBinding(
56+ key.WithKeys("ctrl+u"),
57+ key.WithHelp("ctrl+u", "½ page up"),
58+ ),
59+ HalfPageDown: key.NewBinding(
60+ key.WithKeys("ctrl+d", "ctrl+d"),
61+ key.WithHelp("ctrl+d", "½ page down"),
62+ ),
63+}
64+
41func (m *messagesCmp) Init() tea.Cmd {
65func (m *messagesCmp) Init() tea.Cmd {
42 return tea.Batch(m.viewport.Init(), m.spinner.Tick)
66 return tea.Batch(m.viewport.Init(), m.spinner.Tick)
43}
67}
@@ -45,8 +69,7 @@ func (m *messagesCmp) Init() tea.Cmd {
45func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
69func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
46 var cmds []tea.Cmd
70 var cmds []tea.Cmd
47 switch msg := msg.(type) {
71 switch msg := msg.(type) {
48− case EditorFocusMsg:
72+
49− m.writingMode = bool(msg)
50 case SessionSelectedMsg:
73 case SessionSelectedMsg:
51 if msg.ID != m.session.ID {
74 if msg.ID != m.session.ID {
52 cmd := m.SetSession(msg)
75 cmd := m.SetSession(msg)
@@ -63,10 +86,6 @@ func (m *messagesCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
63 case renderFinishedMsg:
86 case renderFinishedMsg:
64 m.rendering = false
87 m.rendering = false
65 m.viewport.GotoBottom()
88 m.viewport.GotoBottom()
66− case tea.KeyMsg:
67− if m.writingMode {
68− return m, nil
69− }
70 case pubsub.Event[message.Message]:
89 case pubsub.Event[message.Message]:
71 needsRerender := false
90 needsRerender := false
72 if msg.Type == pubsub.CreatedEvent {
91 if msg.Type == pubsub.CreatedEvent {
@@ -326,22 +345,14 @@ func (m *messagesCmp) working() string {
326func (m *messagesCmp) help() string {
345func (m *messagesCmp) help() string {
327 text := ""
346 text := ""
328
347
329− if m.writingMode {
348+ if m.app.CoderAgent.IsBusy() {
330 text += lipgloss.JoinHorizontal(
349 text += lipgloss.JoinHorizontal(
331 lipgloss.Left,
350 lipgloss.Left,
332 styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render("press "),
351 styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render("press "),
333 styles.BaseStyle.Foreground(styles.Forground).Bold(true).Render("esc"),
352 styles.BaseStyle.Foreground(styles.Forground).Bold(true).Render("esc"),
334− styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render(" to exit writing mode"),
353+ styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render(" to exit cancel"),
335− )
336− } else {
337− text += lipgloss.JoinHorizontal(
338− lipgloss.Left,
339− styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render("press "),
340− styles.BaseStyle.Foreground(styles.Forground).Bold(true).Render("i"),
341− styles.BaseStyle.Foreground(styles.ForgroundDim).Bold(true).Render(" to start writing"),
342 )
354 )
343 }
355 }
344−
345 return styles.BaseStyle.
356 return styles.BaseStyle.
346 Width(m.width).
357 Width(m.width).
347 Render(text)
358 Render(text)
@@ -398,18 +409,26 @@ func (m *messagesCmp) SetSession(session session.Session) tea.Cmd {
398}
409}
399
410
400func (m *messagesCmp) BindingKeys() []key.Binding {
411func (m *messagesCmp) BindingKeys() []key.Binding {
401− bindings := layout.KeyMapToSlice(m.viewport.KeyMap)
402− return bindings
412+ return []key.Binding{
413+ m.viewport.KeyMap.PageDown,
414+ m.viewport.KeyMap.PageUp,
415+ m.viewport.KeyMap.HalfPageUp,
416+ m.viewport.KeyMap.HalfPageDown,
417+ }
403}
418}
404
419
405func NewMessagesCmp(app *app.App) tea.Model {
420func NewMessagesCmp(app *app.App) tea.Model {
406 s := spinner.New()
421 s := spinner.New()
407 s.Spinner = spinner.Pulse
422 s.Spinner = spinner.Pulse
423+ vp := viewport.New(0, 0)
424+ vp.KeyMap.PageUp = messageKeys.PageUp
425+ vp.KeyMap.PageDown = messageKeys.PageDown
426+ vp.KeyMap.HalfPageUp = messageKeys.HalfPageUp
427+ vp.KeyMap.HalfPageDown = messageKeys.HalfPageDown
408 return &messagesCmp{
428 return &messagesCmp{
409 app: app,
429 app: app,
410− writingMode: true,
411 cachedContent: make(map[string]cacheItem),
430 cachedContent: make(map[string]cacheItem),
412− viewport: viewport.New(0, 0),
431+ viewport: vp,
413 spinner: s,
432 spinner: s,
414 }
433 }
415}
434}
internal/tui/components/dialog/commands.go−2
@@ -190,7 +190,6 @@ func (c *commandDialogCmp) View() string {
190 styles.BaseStyle.Width(maxWidth).Render(""),
190 styles.BaseStyle.Width(maxWidth).Render(""),
191 styles.BaseStyle.Width(maxWidth).Render(lipgloss.JoinVertical(lipgloss.Left, commandItems...)),
191 styles.BaseStyle.Width(maxWidth).Render(lipgloss.JoinVertical(lipgloss.Left, commandItems...)),
192 styles.BaseStyle.Width(maxWidth).Render(""),
192 styles.BaseStyle.Width(maxWidth).Render(""),
193− styles.BaseStyle.Width(maxWidth).Padding(0, 1).Foreground(styles.ForgroundDim).Render("↑/k: up ↓/j: down enter: select esc: cancel"),
194 )
193 )
195
194
196 return styles.BaseStyle.Padding(1, 2).
195 return styles.BaseStyle.Padding(1, 2).
@@ -244,4 +243,3 @@ func NewCommandDialogCmp() CommandDialog {
244 selectedCommandID: "",
243 selectedCommandID: "",
245 }
244 }
246}
245}
247−
internal/tui/components/dialog/help.go+1−1
@@ -62,7 +62,7 @@ func (h *helpCmp) render() string {
62 var (
62 var (
63 pairs []string
63 pairs []string
64 width int
64 width int
65− rows = 14 - 2
65+ rows = 10 - 2
66 )
66 )
67 for i := 0; i < len(bindings); i += rows {
67 for i := 0; i < len(bindings); i += rows {
68 var (
68 var (
internal/tui/components/dialog/init.go+3−9
@@ -46,8 +46,8 @@ func (k initDialogKeyMap) ShortHelp() []key.Binding {
46 key.WithHelp("enter", "confirm"),
46 key.WithHelp("enter", "confirm"),
47 ),
47 ),
48 key.NewBinding(
48 key.NewBinding(
49− key.WithKeys("esc"),
49+ key.WithKeys("esc", "q"),
50− key.WithHelp("esc", "cancel"),
50+ key.WithHelp("esc/q", "cancel"),
51 ),
51 ),
52 key.NewBinding(
52 key.NewBinding(
53 key.WithKeys("y", "n"),
53 key.WithKeys("y", "n"),
@@ -114,6 +114,7 @@ func (m InitDialogCmp) View() string {
114 Padding(1, 1).
114 Padding(1, 1).
115 Render("Would you like to initialize this project?")
115 Render("Would you like to initialize this project?")
116
116
117+ maxWidth = min(maxWidth, m.width-10)
117 yesStyle := styles.BaseStyle
118 yesStyle := styles.BaseStyle
118 noStyle := styles.BaseStyle
119 noStyle := styles.BaseStyle
119
120
@@ -144,12 +145,6 @@ func (m InitDialogCmp) View() string {
144 Padding(1, 0).
145 Padding(1, 0).
145 Render(buttons)
146 Render(buttons)
146
147
147− help := styles.BaseStyle.
148− Width(maxWidth).
149− Padding(0, 1).
150− Foreground(styles.ForgroundDim).
151− Render("tab/←/→: toggle y/n: yes/no enter: confirm esc: cancel")
152−
153 content := lipgloss.JoinVertical(
148 content := lipgloss.JoinVertical(
154 lipgloss.Left,
149 lipgloss.Left,
155 title,
150 title,
@@ -158,7 +153,6 @@ func (m InitDialogCmp) View() string {
158 question,
153 question,
159 buttons,
154 buttons,
160 styles.BaseStyle.Width(maxWidth).Render(""),
155 styles.BaseStyle.Width(maxWidth).Render(""),
161− help,
162 )
156 )
163
157
164 return styles.BaseStyle.Padding(1, 2).
158 return styles.BaseStyle.Padding(1, 2).
internal/tui/components/dialog/permission.go+5−9
@@ -64,15 +64,15 @@ var permissionsKeys = permissionsMapping{
64 ),
64 ),
65 Allow: key.NewBinding(
65 Allow: key.NewBinding(
66 key.WithKeys("a"),
66 key.WithKeys("a"),
67− key.WithHelp("a", "allow"),
67+ key.WithHelp("a", "[a]llow"),
68 ),
68 ),
69 AllowSession: key.NewBinding(
69 AllowSession: key.NewBinding(
70− key.WithKeys("A"),
70+ key.WithKeys("s"),
71− key.WithHelp("A", "allow for session"),
71+ key.WithHelp("s", "allow for [s]ession"),
72 ),
72 ),
73 Deny: key.NewBinding(
73 Deny: key.NewBinding(
74 key.WithKeys("d"),
74 key.WithKeys("d"),
75− key.WithHelp("d", "deny"),
75+ key.WithHelp("d", "[d]eny"),
76 ),
76 ),
77 Tab: key.NewBinding(
77 Tab: key.NewBinding(
78 key.WithKeys("tab"),
78 key.WithKeys("tab"),
@@ -375,9 +375,6 @@ func (p *permissionDialogCmp) render() string {
375 contentFinal = p.renderDefaultContent()
375 contentFinal = p.renderDefaultContent()
376 }
376 }
377
377
378− // Add help text
379− helpText := styles.BaseStyle.Width(p.width - 4).Padding(0, 1).Foreground(styles.ForgroundDim).Render("←/→/tab: switch options a: allow A: allow for session d: deny enter/space: confirm")
380−
381 content := lipgloss.JoinVertical(
378 content := lipgloss.JoinVertical(
382 lipgloss.Top,
379 lipgloss.Top,
383 title,
380 title,
@@ -385,8 +382,7 @@ func (p *permissionDialogCmp) render() string {
385 headerContent,
382 headerContent,
386 contentFinal,
383 contentFinal,
387 buttons,
384 buttons,
388− styles.BaseStyle.Render(strings.Repeat(" ", p.width - 4)),
385+ styles.BaseStyle.Render(strings.Repeat(" ", p.width-4)),
389− helpText,
390 )
386 )
391
387
392 return styles.BaseStyle.
388 return styles.BaseStyle.
internal/tui/components/dialog/session.go+2−2
@@ -122,6 +122,8 @@ func (s *sessionDialogCmp) View() string {
122 }
122 }
123 }
123 }
124
124
125+ maxWidth = max(30, min(maxWidth, s.width-15)) // Limit width to avoid overflow
126+
125 // Limit height to avoid taking up too much screen space
127 // Limit height to avoid taking up too much screen space
126 maxVisibleSessions := min(10, len(s.sessions))
128 maxVisibleSessions := min(10, len(s.sessions))
127
129
@@ -169,7 +171,6 @@ func (s *sessionDialogCmp) View() string {
169 styles.BaseStyle.Width(maxWidth).Render(""),
171 styles.BaseStyle.Width(maxWidth).Render(""),
170 styles.BaseStyle.Width(maxWidth).Render(lipgloss.JoinVertical(lipgloss.Left, sessionItems...)),
172 styles.BaseStyle.Width(maxWidth).Render(lipgloss.JoinVertical(lipgloss.Left, sessionItems...)),
171 styles.BaseStyle.Width(maxWidth).Render(""),
173 styles.BaseStyle.Width(maxWidth).Render(""),
172− styles.BaseStyle.Width(maxWidth).Padding(0, 1).Foreground(styles.ForgroundDim).Render("↑/k: up ↓/j: down enter: select esc: cancel"),
173 )
174 )
174
175
175 return styles.BaseStyle.Padding(1, 2).
176 return styles.BaseStyle.Padding(1, 2).
@@ -223,4 +224,3 @@ func NewSessionDialogCmp() SessionDialog {
223 selectedSessionID: "",
224 selectedSessionID: "",
224 }
225 }
225}
226}
226−
internal/tui/page/chat.go+11−19
@@ -15,12 +15,11 @@ import (
15var ChatPage PageID = "chat"
15var ChatPage PageID = "chat"
16
16
17type chatPage struct {
17type chatPage struct {
18− app *app.App
18+ app *app.App
19− editor layout.Container
19+ editor layout.Container
20− messages layout.Container
20+ messages layout.Container
21− layout layout.SplitPaneLayout
21+ layout layout.SplitPaneLayout
22− session session.Session
22+ session session.Session
23− editingMode bool
24}
23}
25
24
26type ChatKeyMap struct {
25type ChatKeyMap struct {
@@ -34,8 +33,8 @@ var keyMap = ChatKeyMap{
34 key.WithHelp("ctrl+n", "new session"),
33 key.WithHelp("ctrl+n", "new session"),
35 ),
34 ),
36 Cancel: key.NewBinding(
35 Cancel: key.NewBinding(
37− key.WithKeys("ctrl+x"),
36+ key.WithKeys("esc"),
38− key.WithHelp("ctrl+x", "cancel"),
37+ key.WithHelp("esc", "cancel"),
39 ),
38 ),
40}
39}
41
40
@@ -65,8 +64,6 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
65 }
64 }
66 }
65 }
67 p.session = msg
66 p.session = msg
68− case chat.EditorFocusMsg:
69− p.editingMode = bool(msg)
70 case tea.KeyMsg:
67 case tea.KeyMsg:
71 switch {
68 switch {
72 case key.Matches(msg, keyMap.NewSession):
69 case key.Matches(msg, keyMap.NewSession):
@@ -136,11 +133,7 @@ func (p *chatPage) View() string {
136
133
137func (p *chatPage) BindingKeys() []key.Binding {
134func (p *chatPage) BindingKeys() []key.Binding {
138 bindings := layout.KeyMapToSlice(keyMap)
135 bindings := layout.KeyMapToSlice(keyMap)
139− if p.editingMode {
140− bindings = append(bindings, p.editor.BindingKeys()...)
141− } else {
142− bindings = append(bindings, p.messages.BindingKeys()...)
136+ bindings = append(bindings, p.messages.BindingKeys()...)
143− }
144 return bindings
137 return bindings
145}
138}
146
139
@@ -155,10 +148,9 @@ func NewChatPage(app *app.App) tea.Model {
155 layout.WithBorder(true, false, false, false),
148 layout.WithBorder(true, false, false, false),
156 )
149 )
157 return &chatPage{
150 return &chatPage{
158− app: app,
151+ app: app,
159− editor: editorContainer,
152+ editor: editorContainer,
160− messages: messagesContainer,
153+ messages: messagesContainer,
161− editingMode: true,
162 layout: layout.NewSplitPane(
154 layout: layout.NewSplitPane(
163 layout.WithLeftPanel(messagesContainer),
155 layout.WithLeftPanel(messagesContainer),
164 layout.WithBottomPanel(editorContainer),
156 layout.WithBottomPanel(editorContainer),
internal/tui/tui.go+5−10
@@ -30,7 +30,7 @@ type keyMap struct {
30var keys = keyMap{
30var keys = keyMap{
31 Logs: key.NewBinding(
31 Logs: key.NewBinding(
32 key.WithKeys("ctrl+l"),
32 key.WithKeys("ctrl+l"),
33− key.WithHelp("ctrl+L", "logs"),
33+ key.WithHelp("ctrl+l", "logs"),
34 ),
34 ),
35
35
36 Quit: key.NewBinding(
36 Quit: key.NewBinding(
@@ -49,7 +49,7 @@ var keys = keyMap{
49
49
50 Commands: key.NewBinding(
50 Commands: key.NewBinding(
51 key.WithKeys("ctrl+k"),
51 key.WithKeys("ctrl+k"),
52− key.WithHelp("ctrl+K", "commands"),
52+ key.WithHelp("ctrl+k", "commands"),
53 ),
53 ),
54}
54}
55
55
@@ -95,8 +95,6 @@ type appModel struct {
95
95
96 showInitDialog bool
96 showInitDialog bool
97 initDialog dialog.InitDialogCmp
97 initDialog dialog.InitDialogCmp
98−
99− editingMode bool
100}
98}
101
99
102func (a appModel) Init() tea.Cmd {
100func (a appModel) Init() tea.Cmd {
@@ -164,8 +162,6 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
164 a.initDialog.SetSize(msg.Width, msg.Height)
162 a.initDialog.SetSize(msg.Width, msg.Height)
165
163
166 return a, tea.Batch(cmds...)
164 return a, tea.Batch(cmds...)
167− case chat.EditorFocusMsg:
168− a.editingMode = bool(msg)
169 // Status
165 // Status
170 case util.InfoMsg:
166 case util.InfoMsg:
171 s, cmd := a.status.Update(msg)
167 s, cmd := a.status.Update(msg)
@@ -360,7 +356,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
360 a.showHelp = !a.showHelp
356 a.showHelp = !a.showHelp
361 return a, nil
357 return a, nil
362 case key.Matches(msg, helpEsc):
358 case key.Matches(msg, helpEsc):
363− if !a.editingMode {
359+ if a.app.CoderAgent.IsBusy() {
364 if a.showQuit {
360 if a.showQuit {
365 return a, nil
361 return a, nil
366 }
362 }
@@ -477,7 +473,7 @@ func (a appModel) View() string {
477 )
473 )
478 }
474 }
479
475
480− if a.editingMode {
476+ if !a.app.CoderAgent.IsBusy() {
481 a.status.SetHelpMsg("ctrl+? help")
477 a.status.SetHelpMsg("ctrl+? help")
482 } else {
478 } else {
483 a.status.SetHelpMsg("? help")
479 a.status.SetHelpMsg("? help")
@@ -494,7 +490,7 @@ func (a appModel) View() string {
494 if a.currentPage == page.LogsPage {
490 if a.currentPage == page.LogsPage {
495 bindings = append(bindings, logsKeyReturnKey)
491 bindings = append(bindings, logsKeyReturnKey)
496 }
492 }
497− if !a.editingMode {
493+ if !a.app.CoderAgent.IsBusy() {
498 bindings = append(bindings, helpEsc)
494 bindings = append(bindings, helpEsc)
499 }
495 }
500 a.help.SetBindings(bindings)
496 a.help.SetBindings(bindings)
@@ -585,7 +581,6 @@ func New(app *app.App) tea.Model {
585 permissions: dialog.NewPermissionDialogCmp(),
581 permissions: dialog.NewPermissionDialogCmp(),
586 initDialog: dialog.NewInitDialogCmp(),
582 initDialog: dialog.NewInitDialogCmp(),
587 app: app,
583 app: app,
588− editingMode: true,
589 commands: []dialog.Command{},
584 commands: []dialog.Command{},
590 pages: map[page.PageID]tea.Model{
585 pages: map[page.PageID]tea.Model{
591 page.ChatPage: page.NewChatPage(app),
586 page.ChatPage: page.NewChatPage(app),