Skip to content

Commit 6390f83

Browse files
blouflabblouf
authored andcommitted
feat(editor): implement keyboard navigation enhancements
1 parent 67cf754 commit 6390f83

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

internal/tui/components/chat/editor/editor.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ type editorCmp struct {
6767
currentQuery string
6868
completionsStartIndex int
6969
isCompletionsOpen bool
70+
71+
// History
72+
history []string
73+
historyIndex int
7074
}
7175

7276
var DeleteKeyMaps = DeleteAttachmentKeyMaps{
@@ -148,6 +152,12 @@ func (m *editorCmp) send() tea.Cmd {
148152
return util.CmdHandler(dialogs.OpenDialogMsg{Model: quit.NewQuitDialog()})
149153
}
150154

155+
// Add to history
156+
if value != "" {
157+
m.history = append(m.history, value)
158+
m.historyIndex = len(m.history)
159+
}
160+
151161
m.textarea.Reset()
152162
attachments := m.attachments
153163

@@ -274,8 +284,44 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
274284
cmds = append(cmds, m.startCompletions)
275285
case m.isCompletionsOpen && curIdx <= m.completionsStartIndex:
276286
cmds = append(cmds, util.CmdHandler(completions.CloseCompletionsMsg{}))
277-
}
278-
if key.Matches(msg, DeleteKeyMaps.AttachmentDeleteMode) {
287+
case key.Matches(msg, m.keyMap.ClearLine):
288+
m.textarea.SetValue("")
289+
m.textarea.SetCursorColumn(0)
290+
return m, nil
291+
case key.Matches(msg, m.keyMap.WordBackward):
292+
// Handle word backward navigation
293+
// Send the same key event to the textarea to trigger word backward navigation
294+
// The textarea already has the customized keymap that maps Ctrl+Left to WordBackward
295+
return m, nil
296+
case key.Matches(msg, m.keyMap.WordForward):
297+
// Handle word forward navigation
298+
// Send the same key event to the textarea to trigger word forward navigation
299+
// The textarea already has the customized keymap that maps Ctrl+Right to WordForward
300+
return m, nil
301+
case key.Matches(msg, m.keyMap.PreviousPrompt):
302+
if len(m.history) > 0 && m.historyIndex > 0 {
303+
if m.historyIndex == len(m.history) { // If currently typing, save it before navigating
304+
currentValue := m.textarea.Value()
305+
if currentValue != "" {
306+
m.history = append(m.history, currentValue)
307+
}
308+
}
309+
m.historyIndex--
310+
m.textarea.SetValue(m.history[m.historyIndex])
311+
m.textarea.MoveToEnd()
312+
}
313+
return m, nil
314+
case key.Matches(msg, m.keyMap.NextPrompt):
315+
if len(m.history) > 0 && m.historyIndex < len(m.history)-1 {
316+
m.historyIndex++
317+
m.textarea.SetValue(m.history[m.historyIndex])
318+
m.textarea.MoveToEnd()
319+
} else if m.historyIndex == len(m.history)-1 { // If at the last history item, clear the input
320+
m.historyIndex++
321+
m.textarea.SetValue("")
322+
m.textarea.SetCursorColumn(0)
323+
}
324+
return m, nil
279325
m.deleteMode = true
280326
return m, nil
281327
}
@@ -570,6 +616,17 @@ func yoloPromptFunc(info textarea.PromptInfo) string {
570616
func New(app *app.App) Editor {
571617
t := styles.CurrentTheme()
572618
ta := textarea.New()
619+
620+
// Customize the textarea keymap to use Ctrl+Left/Right for word navigation
621+
ta.KeyMap.WordBackward = key.NewBinding(
622+
key.WithKeys("ctrl+left", "alt+left", "alt+b"),
623+
key.WithHelp("ctrl+←", "word backward"),
624+
)
625+
ta.KeyMap.WordForward = key.NewBinding(
626+
key.WithKeys("ctrl+right", "alt+right", "alt+f"),
627+
key.WithHelp("ctrl+→", "word forward"),
628+
)
629+
573630
ta.SetStyles(t.S().TextArea)
574631
ta.ShowLineNumbers = false
575632
ta.CharLimit = -1
@@ -580,6 +637,8 @@ func New(app *app.App) Editor {
580637
app: app,
581638
textarea: ta,
582639
keyMap: DefaultEditorKeyMap(),
640+
history: []string{},
641+
historyIndex: 0,
583642
}
584643
e.setEditorPrompt()
585644

internal/tui/components/chat/editor/keys.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ import (
55
)
66

77
type EditorKeyMap struct {
8-
AddFile key.Binding
9-
SendMessage key.Binding
10-
OpenEditor key.Binding
11-
Newline key.Binding
8+
AddFile key.Binding
9+
SendMessage key.Binding
10+
OpenEditor key.Binding
11+
Newline key.Binding
12+
ClearLine key.Binding
13+
PreviousPrompt key.Binding
14+
NextPrompt key.Binding
15+
WordBackward key.Binding
16+
WordForward key.Binding
1217
}
1318

1419
func DefaultEditorKeyMap() EditorKeyMap {
@@ -32,6 +37,26 @@ func DefaultEditorKeyMap() EditorKeyMap {
3237
// to reflect that.
3338
key.WithHelp("ctrl+j", "newline"),
3439
),
40+
ClearLine: key.NewBinding(
41+
key.WithKeys("ctrl+u"),
42+
key.WithHelp("ctrl+u", "clear line"),
43+
),
44+
PreviousPrompt: key.NewBinding(
45+
key.WithKeys("up"),
46+
key.WithHelp("↑", "previous prompt"),
47+
),
48+
NextPrompt: key.NewBinding(
49+
key.WithKeys("down"),
50+
key.WithHelp("↓", "next prompt"),
51+
),
52+
WordBackward: key.NewBinding(
53+
key.WithKeys("ctrl+left"),
54+
key.WithHelp("ctrl+←", "previous word"),
55+
),
56+
WordForward: key.NewBinding(
57+
key.WithKeys("ctrl+right"),
58+
key.WithHelp("ctrl+→", "next word"),
59+
),
3560
}
3661
}
3762

@@ -42,6 +67,11 @@ func (k EditorKeyMap) KeyBindings() []key.Binding {
4267
k.SendMessage,
4368
k.OpenEditor,
4469
k.Newline,
70+
k.ClearLine,
71+
k.PreviousPrompt,
72+
k.NextPrompt,
73+
k.WordBackward,
74+
k.WordForward,
4575
AttachmentsKeyMaps.AttachmentDeleteMode,
4676
AttachmentsKeyMaps.DeleteAllAttachments,
4777
AttachmentsKeyMaps.Escape,

0 commit comments

Comments
 (0)