chore: handle scrolling keys in history mode

tauraamui created

Change summary

internal/tui/components/chat/editor/editor.go  | 32 ++++++++++++--
internal/tui/components/chat/editor/history.go | 43 ++++++++++++++++++-
2 files changed, 66 insertions(+), 9 deletions(-)

Detailed changes

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

@@ -195,12 +195,15 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 		if err != nil {
 			// TODO(tauraamui): handle error for loading history better in the UI later
 		}
-		m.history = InitialiseHistory(msgs)
-		m.textarea.SetValue("opened history state")
+		if len(msgs) == 0 {
+			break
+		}
+		m.history = InitialiseHistory(m.textarea.Value(), msgs)
+		m.textarea.SetValue(m.history.Value())
 		return m, nil
 	case CloseHistoryMsg:
+		m.textarea.SetValue(m.history.ExistingValue())
 		m.history = nil
-		m.textarea.SetValue("closed history") // for easier temporary visual debugging
 		return m, nil
 	case tea.WindowSizeMsg:
 		return m, m.repositionCompletions
@@ -289,6 +292,16 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 	case tea.KeyPressMsg:
 		cur := m.textarea.Cursor()
 		curIdx := m.textarea.Width()*cur.Y + cur.X
+		/*
+			if m.inHistoryMode() {
+				switch true {
+				case key.Matches(msg, m.keyMap.Escape):
+					return m, util.CmdHandler(CloseHistoryMsg{})
+				case key.Matches(msg, m.keyMap.Previous):
+					m.history.ScrollUp()
+				}
+			}
+		*/
 		switch {
 		// Open command palette when "/" is pressed on empty prompt
 		case msg.String() == "/" && len(strings.TrimSpace(m.textarea.Value())) == 0:
@@ -315,7 +328,7 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 			m.attachments = nil
 			return m, nil
 		}
-		if key.Matches(msg, DeleteKeyMaps.Escape) && m.inHistoryMode() {
+		if key.Matches(msg, m.keyMap.Escape) && m.inHistoryMode() {
 			cmds = append(cmds, util.CmdHandler(CloseHistoryMsg{}))
 		}
 		rune := msg.Code
@@ -362,6 +375,16 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
 				cmds = append(cmds, util.CmdHandler(LoadHistoryMsg{}))
 				break
 			}
+
+			if key.Matches(msg, m.keyMap.Previous) {
+				m.history.ScrollUp()
+			} else if key.Matches(msg, m.keyMap.Next) {
+				m.history.ScrollDown()
+			} else {
+				break
+			}
+
+			m.textarea.SetValue(m.history.Value())
 		}
 	}
 
@@ -496,7 +519,6 @@ func (m *editorCmp) getUserMessagesAsText() ([]string, error) {
 		}
 	}
 
-	userMessages = append(userMessages, m.textarea.Value())
 	return userMessages, nil
 }
 

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

@@ -3,18 +3,53 @@ package editor
 type historyState struct {
 	previouslyScrollingPromptHistory bool
 	promptHistoryIndex               int
+	existingValue                    string
 	historyCache                     []string
 }
 
 type History interface {
+	ExistingValue() string
+	Value() string
 	ScrollUp()
 	ScrollDown()
 }
 
-func InitialiseHistory(messages []string) History {
-	return &historyState{}
+func InitialiseHistory(existingValue string, messages []string) History {
+	return &historyState{
+		existingValue:      existingValue,
+		historyCache:       messages,
+		promptHistoryIndex: len(messages) - 1,
+	}
 }
 
-func (h *historyState) ScrollUp() {}
+func (h *historyState) Value() string {
+	if len(h.historyCache) == 0 {
+		return h.existingValue
+	}
+	return h.historyCache[h.promptHistoryIndex]
+}
+
+func (h *historyState) ExistingValue() string {
+	return h.existingValue
+}
+
+func (h *historyState) ScrollUp() {
+	h.promptHistoryIndex--
+	h.clampIndex()
+}
 
-func (h *historyState) ScrollDown() {}
+func (h *historyState) ScrollDown() {
+	h.promptHistoryIndex++
+	h.clampIndex()
+}
+
+func (h *historyState) clampIndex() {
+	if h.promptHistoryIndex > len(h.historyCache)-1 {
+		h.promptHistoryIndex = len(h.historyCache) - 1
+		return
+	}
+
+	if h.promptHistoryIndex < 0 {
+		h.promptHistoryIndex = 0
+	}
+}