summaryrefslogtreecommitdiffhomepage
path: root/internal/tui/components
diff options
context:
space:
mode:
authorEd Zynda <[email protected]>2025-05-17 21:35:49 +0300
committerGitHub <[email protected]>2025-05-17 13:35:49 -0500
commitc84918cb47d17c10286985bce7539161dfd13869 (patch)
tree141de02abb82fdf97989c55ff5220e1f378ca961 /internal/tui/components
parent05bb065d00e00e21bffd6312162cf9de92421dce (diff)
downloadopencode-c84918cb47d17c10286985bce7539161dfd13869.tar.gz
opencode-c84918cb47d17c10286985bce7539161dfd13869.zip
feat: Add message history navigation with arrow keys (#30)
Diffstat (limited to 'internal/tui/components')
-rw-r--r--internal/tui/components/chat/editor.go85
-rw-r--r--internal/tui/components/chat/messages.go2
2 files changed, 79 insertions, 8 deletions
diff --git a/internal/tui/components/chat/editor.go b/internal/tui/components/chat/editor.go
index 37ac60368..dbaa05181 100644
--- a/internal/tui/components/chat/editor.go
+++ b/internal/tui/components/chat/editor.go
@@ -25,18 +25,23 @@ import (
)
type editorCmp struct {
- width int
- height int
- app *app.App
- textarea textarea.Model
- attachments []message.Attachment
- deleteMode bool
+ width int
+ height int
+ app *app.App
+ textarea textarea.Model
+ attachments []message.Attachment
+ deleteMode bool
+ history []string
+ historyIndex int
+ currentMessage string
}
type EditorKeyMaps struct {
Send key.Binding
OpenEditor key.Binding
Paste key.Binding
+ HistoryUp key.Binding
+ HistoryDown key.Binding
}
type bluredEditorKeyMaps struct {
@@ -63,6 +68,14 @@ var editorMaps = EditorKeyMaps{
key.WithKeys("ctrl+v"),
key.WithHelp("ctrl+v", "paste content"),
),
+ HistoryUp: key.NewBinding(
+ key.WithKeys("up"),
+ key.WithHelp("up", "previous message"),
+ ),
+ HistoryDown: key.NewBinding(
+ key.WithKeys("down"),
+ key.WithHelp("down", "next message"),
+ ),
}
var DeleteKeyMaps = DeleteAttachmentKeyMaps{
@@ -139,6 +152,15 @@ func (m *editorCmp) send() tea.Cmd {
m.textarea.Reset()
attachments := m.attachments
+ // Save to history if not empty and not a duplicate of the last entry
+ if value != "" {
+ if len(m.history) == 0 || m.history[len(m.history)-1] != value {
+ m.history = append(m.history, value)
+ }
+ m.historyIndex = len(m.history)
+ m.currentMessage = ""
+ }
+
m.attachments = nil
if value == "" {
return nil
@@ -223,6 +245,50 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
return m, cmd
}
+
+ // Handle history navigation with up/down arrow keys
+ if m.textarea.Focused() && key.Matches(msg, editorMaps.HistoryUp) {
+ // Get the current line number
+ currentLine := m.textarea.Line()
+
+ // Only navigate history if we're at the first line
+ if currentLine == 0 && len(m.history) > 0 {
+ // Save current message if we're just starting to navigate
+ if m.historyIndex == len(m.history) {
+ m.currentMessage = m.textarea.Value()
+ }
+
+ // Go to previous message in history
+ if m.historyIndex > 0 {
+ m.historyIndex--
+ m.textarea.SetValue(m.history[m.historyIndex])
+ }
+ return m, nil
+ }
+ }
+
+ if m.textarea.Focused() && key.Matches(msg, editorMaps.HistoryDown) {
+ // Get the current line number and total lines
+ currentLine := m.textarea.Line()
+ value := m.textarea.Value()
+ lines := strings.Split(value, "\n")
+ totalLines := len(lines)
+
+ // Only navigate history if we're at the last line
+ if currentLine == totalLines-1 {
+ if m.historyIndex < len(m.history)-1 {
+ // Go to next message in history
+ m.historyIndex++
+ m.textarea.SetValue(m.history[m.historyIndex])
+ } else if m.historyIndex == len(m.history)-1 {
+ // Return to the current message being composed
+ m.historyIndex = len(m.history)
+ m.textarea.SetValue(m.currentMessage)
+ }
+ return m, nil
+ }
+ }
+
// Handle Enter key
if m.textarea.Focused() && key.Matches(msg, editorMaps.Send) {
value := m.textarea.Value()
@@ -336,7 +402,10 @@ func CreateTextArea(existing *textarea.Model) textarea.Model {
func NewEditorCmp(app *app.App) tea.Model {
ta := CreateTextArea(nil)
return &editorCmp{
- app: app,
- textarea: ta,
+ app: app,
+ textarea: ta,
+ history: []string{},
+ historyIndex: 0,
+ currentMessage: "",
}
}
diff --git a/internal/tui/components/chat/messages.go b/internal/tui/components/chat/messages.go
index baa7c7e6d..d6f252aad 100644
--- a/internal/tui/components/chat/messages.go
+++ b/internal/tui/components/chat/messages.go
@@ -386,6 +386,8 @@ func (m *messagesCmp) help() string {
baseStyle.Foreground(t.TextMuted()).Bold(true).Render("+"),
baseStyle.Foreground(t.Text()).Bold(true).Render("enter"),
baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for newline,"),
+ baseStyle.Foreground(t.Text()).Bold(true).Render(" ↑↓"),
+ baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" for history,"),
baseStyle.Foreground(t.Text()).Bold(true).Render(" ctrl+h"),
baseStyle.Foreground(t.TextMuted()).Bold(true).Render(" to toggle tool messages"),
)