From 12d4e495d4730c52ee54b8df6aba6f21d1e9916b Mon Sep 17 00:00:00 2001 From: Matt Low Date: Tue, 12 Mar 2024 17:50:10 +0000 Subject: [PATCH] tui: add focus switching between input/messages view --- pkg/tui/tui.go | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/pkg/tui/tui.go b/pkg/tui/tui.go index 815bd92..abca398 100644 --- a/pkg/tui/tui.go +++ b/pkg/tui/tui.go @@ -2,7 +2,6 @@ package tui // The terminal UI for lmcli, launched from the `lmcli chat` command // TODO: -// - mode/focus changing between input and message selection // - binding to open selected message/input in $EDITOR import ( @@ -19,6 +18,13 @@ import ( "github.com/charmbracelet/lipgloss" ) +type focusState int + +const ( + focusInput focusState = iota + focusMessages +) + type model struct { ctx *lmcli.Context convShortname string @@ -30,6 +36,7 @@ type model struct { err error // ui state + focus focusState isWaiting bool status string // a general status message @@ -81,7 +88,25 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: - cmd = m.handleKeyMsg(msg) + switch msg.String() { + case "ctrl+c": + return m, tea.Quit + case "q": + if m.focus != focusInput { + return m, tea.Quit + } + default: + var inputHandled tea.Cmd + switch m.focus { + case focusInput: + inputHandled = m.handleInputKey(msg) + case focusMessages: + inputHandled = m.handleMessagesKey(msg) + } + if inputHandled != nil { + return m, inputHandled + } + } case tea.WindowSizeMsg: m.content.Width = msg.Width m.content.Height = msg.Height - m.input.Height() - lipgloss.Height(m.footerView()) @@ -161,14 +186,23 @@ func initialModel(ctx *lmcli.Context, convShortname string) model { m.isWaiting = false m.status = "Press ctrl+s to send" - return m } -func (m *model) handleKeyMsg(msg tea.KeyMsg) tea.Cmd { +func (m *model) handleMessagesKey(msg tea.KeyMsg) tea.Cmd { switch msg.String() { - case "ctrl+c", "q": - return tea.Quit + case "tab": + m.focus = focusInput + m.input.Focus() + } + return nil +} + +func (m *model) handleInputKey(msg tea.KeyMsg) tea.Cmd { + switch msg.String() { + case "esc": + m.focus = focusMessages + m.input.Blur() case "ctrl+s": userInput := strings.TrimSpace(m.input.Value()) if strings.TrimSpace(userInput) == "" { @@ -186,11 +220,7 @@ func (m *model) handleKeyMsg(msg tea.KeyMsg) tea.Cmd { m.isWaiting = true m.status = "Waiting for response... (Press 's' to stop)" return m.promptLLM() - case "s": - // TOOD: stop response - break } - return nil }