TUI refactor
- Clean up, improved startup logic, initial conversation load - Moved converation/message business logic (mostly) into `model/tui`
This commit is contained in:
@@ -5,18 +5,12 @@ import (
|
||||
"strings"
|
||||
|
||||
"git.mlow.ca/mlow/lmcli/pkg/api"
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/model"
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/shared"
|
||||
tuiutil "git.mlow.ca/mlow/lmcli/pkg/tui/util"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type MessageCycleDirection int
|
||||
|
||||
const (
|
||||
CycleNext MessageCycleDirection = 1
|
||||
CyclePrev MessageCycleDirection = -1
|
||||
)
|
||||
|
||||
func (m *Model) HandleInput(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
switch m.focus {
|
||||
case focusInput:
|
||||
@@ -71,17 +65,17 @@ func (m *Model) handleMessagesKey(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
m.input.Focus()
|
||||
return true, nil
|
||||
case "e":
|
||||
if m.selectedMessage < len(m.messages) {
|
||||
if m.selectedMessage < len(m.App.Messages) {
|
||||
m.editorTarget = selectedMessage
|
||||
return true, tuiutil.OpenTempfileEditor(
|
||||
"message.*.md",
|
||||
m.messages[m.selectedMessage].Content,
|
||||
m.App.Messages[m.selectedMessage].Content,
|
||||
"# Edit the message below\n",
|
||||
)
|
||||
}
|
||||
return false, nil
|
||||
case "ctrl+k":
|
||||
if m.selectedMessage > 0 && len(m.messages) == len(m.messageOffsets) {
|
||||
if m.selectedMessage > 0 && len(m.App.Messages) == len(m.messageOffsets) {
|
||||
m.selectedMessage--
|
||||
m.updateContent()
|
||||
offset := m.messageOffsets[m.selectedMessage]
|
||||
@@ -89,7 +83,7 @@ func (m *Model) handleMessagesKey(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
}
|
||||
return true, nil
|
||||
case "ctrl+j":
|
||||
if m.selectedMessage < len(m.messages)-1 && len(m.messages) == len(m.messageOffsets) {
|
||||
if m.selectedMessage < len(m.App.Messages)-1 && len(m.App.Messages) == len(m.messageOffsets) {
|
||||
m.selectedMessage++
|
||||
m.updateContent()
|
||||
offset := m.messageOffsets[m.selectedMessage]
|
||||
@@ -97,23 +91,23 @@ func (m *Model) handleMessagesKey(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
}
|
||||
return true, nil
|
||||
case "ctrl+h", "ctrl+l":
|
||||
dir := CyclePrev
|
||||
dir := model.CyclePrev
|
||||
if msg.String() == "ctrl+l" {
|
||||
dir = CycleNext
|
||||
dir = model.CycleNext
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
if m.selectedMessage == 0 {
|
||||
cmd = m.cycleSelectedRoot(m.conversation, dir)
|
||||
cmd = m.cycleSelectedRoot(m.App.Conversation, dir)
|
||||
} else if m.selectedMessage > 0 {
|
||||
cmd = m.cycleSelectedReply(&m.messages[m.selectedMessage-1], dir)
|
||||
cmd = m.cycleSelectedReply(&m.App.Messages[m.selectedMessage-1], dir)
|
||||
}
|
||||
|
||||
return cmd != nil, cmd
|
||||
case "ctrl+r":
|
||||
// resubmit the conversation with all messages up until and including the selected message
|
||||
if m.state == idle && m.selectedMessage < len(m.messages) {
|
||||
m.messages = m.messages[:m.selectedMessage+1]
|
||||
if m.state == idle && m.selectedMessage < len(m.App.Messages) {
|
||||
m.App.Messages = m.App.Messages[:m.selectedMessage+1]
|
||||
m.messageCache = m.messageCache[:m.selectedMessage+1]
|
||||
cmd := m.promptLLM()
|
||||
m.updateContent()
|
||||
@@ -129,9 +123,9 @@ func (m *Model) handleInputKey(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
switch msg.String() {
|
||||
case "esc":
|
||||
m.focus = focusMessages
|
||||
if len(m.messages) > 0 {
|
||||
if m.selectedMessage < 0 || m.selectedMessage >= len(m.messages) {
|
||||
m.selectedMessage = len(m.messages) - 1
|
||||
if len(m.App.Messages) > 0 {
|
||||
if m.selectedMessage < 0 || m.selectedMessage >= len(m.App.Messages) {
|
||||
m.selectedMessage = len(m.App.Messages) - 1
|
||||
}
|
||||
offset := m.messageOffsets[m.selectedMessage]
|
||||
tuiutil.ScrollIntoView(&m.content, offset, m.content.Height/2)
|
||||
@@ -150,7 +144,7 @@ func (m *Model) handleInputKey(msg tea.KeyMsg) (bool, tea.Cmd) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if len(m.messages) > 0 && m.messages[len(m.messages)-1].Role == api.MessageRoleUser {
|
||||
if len(m.App.Messages) > 0 && m.App.Messages[len(m.App.Messages)-1].Role == api.MessageRoleUser {
|
||||
return true, shared.WrapError(fmt.Errorf("Can't reply to a user message"))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user