Просмотр исходного кода

feat: Add message history navigation with arrow keys (#30)

Ed Zynda 9 месяцев назад
Родитель
Сommit
c84918cb47
2 измененных файлов с 79 добавлено и 8 удалено
  1. 77 8
      internal/tui/components/chat/editor.go
  2. 2 0
      internal/tui/components/chat/messages.go

+ 77 - 8
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: "",
 	}
 }

+ 2 - 0
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"),
 		)