tui: renamed uiCache to views, cleanup

This commit is contained in:
Matt Low 2024-03-29 20:43:19 +00:00
parent 0b991800d6
commit 9cd28d28d7

View File

@ -42,14 +42,6 @@ const (
selectedMessage selectedMessage
) )
type uiCache struct {
header string
content string
error string
input string
footer string
}
type model struct { type model struct {
width int width int
height int height int
@ -81,15 +73,50 @@ type model struct {
content viewport.Model content viewport.Model
input textarea.Model input textarea.Model
spinner spinner.Model spinner spinner.Model
views *views
cache *uiCache
} }
type message struct { // we populate these fields in the main Update() function, and let View()
role string // be responsible for returning the final composition of elements
type views struct {
header string
content string content string
error string
input string
footer string
} }
// styles
var (
headerStyle = lipgloss.NewStyle().
PaddingLeft(1).
PaddingRight(1).
Background(lipgloss.Color("0"))
messageHeadingStyle = lipgloss.NewStyle().
MarginTop(1).
MarginBottom(1).
PaddingLeft(1).
Bold(true)
userStyle = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("10"))
assistantStyle = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("12"))
messageStyle = lipgloss.NewStyle().
PaddingLeft(2).
PaddingRight(2)
inputFocusedStyle = lipgloss.NewStyle().
Border(lipgloss.RoundedBorder(), true, true, true, false)
inputBlurredStyle = lipgloss.NewStyle().
Faint(true).
Border(lipgloss.RoundedBorder(), true, true, true, false)
footerStyle = lipgloss.NewStyle()
)
// custom tea.Msg types // custom tea.Msg types
type ( type (
// sent on each chunk received from LLM // sent on each chunk received from LLM
@ -110,24 +137,11 @@ type (
msgError error msgError error
) )
// styles func wrapError(err error) tea.Cmd {
var ( return func() tea.Msg {
headingStyle = lipgloss.NewStyle(). return msgError(err)
MarginTop(1). }
MarginBottom(1). }
PaddingLeft(1).
Bold(true)
userStyle = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("10"))
assistantStyle = lipgloss.NewStyle().Faint(true).Foreground(lipgloss.Color("12"))
messageStyle = lipgloss.NewStyle().
PaddingLeft(2).
PaddingRight(2)
headerStyle = lipgloss.NewStyle().
PaddingLeft(1).
PaddingRight(1).
Background(lipgloss.Color("0"))
footerStyle = lipgloss.NewStyle()
)
func (m model) Init() tea.Cmd { func (m model) Init() tea.Cmd {
return tea.Batch( return tea.Batch(
@ -139,12 +153,6 @@ func (m model) Init() tea.Cmd {
) )
} }
func wrapError(err error) tea.Cmd {
return func() tea.Msg {
return msgError(err)
}
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd var cmds []tea.Cmd
@ -293,7 +301,6 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmds = append(cmds, cmd) cmds = append(cmds, cmd)
} }
prevInputLineCnt := m.input.LineCount() prevInputLineCnt := m.input.LineCount()
inputCaptured := false inputCaptured := false
m.input, cmd = m.input.Update(msg) m.input, cmd = m.input.Update(msg)
@ -310,19 +317,19 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
if m.width > 0 { if m.width > 0 {
m.cache.header = m.headerView() m.views.header = m.headerView()
m.cache.footer = m.footerView() m.views.footer = m.footerView()
m.cache.error = m.errorView() m.views.error = m.errorView()
fixedHeight := height(m.cache.header) + height(m.cache.error) + height(m.cache.footer) fixedHeight := height(m.views.header) + height(m.views.error) + height(m.views.footer)
// calculate clamped input height to accomodate input text // calculate clamped input height to accomodate input text
newHeight := max(4, min((m.height-fixedHeight-1)/2, m.input.LineCount())) newHeight := max(4, min((m.height-fixedHeight-1)/2, m.input.LineCount()))
m.input.SetHeight(newHeight) m.input.SetHeight(newHeight)
m.cache.input = m.inputView() m.views.input = m.input.View()
m.content.Height = m.height - height(m.cache.input) - fixedHeight m.content.Height = m.height - height(m.views.input) - fixedHeight
m.cache.content = m.contentView() m.views.content = m.content.View()
} }
// this is a pretty nasty hack to ensure the input area viewport doesn't // this is a pretty nasty hack to ensure the input area viewport doesn't
@ -384,13 +391,13 @@ func (m model) View() string {
} }
sections := make([]string, 0, 6) sections := make([]string, 0, 6)
sections = append(sections, m.cache.header) sections = append(sections, m.views.header)
sections = append(sections, m.cache.content) sections = append(sections, m.views.content)
if m.cache.error != "" { if m.views.error != "" {
sections = append(sections, m.cache.error) sections = append(sections, m.views.error)
} }
sections = append(sections, m.cache.input) sections = append(sections, m.views.input)
sections = append(sections, m.cache.footer) sections = append(sections, m.views.footer)
return lipgloss.JoinVertical( return lipgloss.JoinVertical(
lipgloss.Left, lipgloss.Left,
@ -411,10 +418,6 @@ func (m *model) headerView() string {
return headerStyle.Width(m.width).Render(part) return headerStyle.Width(m.width).Render(part)
} }
func (m *model) contentView() string {
return m.content.View()
}
func (m *model) errorView() string { func (m *model) errorView() string {
if m.err == nil { if m.err == nil {
return "" return ""
@ -427,10 +430,6 @@ func (m *model) errorView() string {
Render(fmt.Sprintf("%s", m.err)) Render(fmt.Sprintf("%s", m.err))
} }
func (m *model) inputView() string {
return m.input.View()
}
func (m *model) footerView() string { func (m *model) footerView() string {
segmentStyle := lipgloss.NewStyle().PaddingLeft(1).PaddingRight(1).Faint(true) segmentStyle := lipgloss.NewStyle().PaddingLeft(1).PaddingRight(1).Faint(true)
segmentSeparator := "|" segmentSeparator := "|"
@ -488,7 +487,7 @@ func initialModel(ctx *lmcli.Context, convShortname string) model {
wrap: true, wrap: true,
selectedMessage: -1, selectedMessage: -1,
cache: &uiCache{}, views: &views{},
} }
m.content = viewport.New(0, 0) m.content = viewport.New(0, 0)
@ -497,14 +496,11 @@ func initialModel(ctx *lmcli.Context, convShortname string) model {
m.input.CharLimit = 0 m.input.CharLimit = 0
m.input.Placeholder = "Enter a message" m.input.Placeholder = "Enter a message"
m.input.ShowLineNumbers = false
m.input.Focus() m.input.Focus()
m.input.FocusedStyle.CursorLine = lipgloss.NewStyle() m.input.FocusedStyle.CursorLine = lipgloss.NewStyle()
m.input.FocusedStyle.Base = lipgloss.NewStyle(). m.input.FocusedStyle.Base = inputFocusedStyle
Border(lipgloss.RoundedBorder(), true, true, true, false) m.input.BlurredStyle.Base = inputBlurredStyle
m.input.BlurredStyle.Base = lipgloss.NewStyle(). m.input.ShowLineNumbers = false
Faint(true).
Border(lipgloss.RoundedBorder(), true, true, true, false)
m.spinner = spinner.New(spinner.WithSpinner( m.spinner = spinner.New(spinner.WithSpinner(
spinner.Spinner{ spinner.Spinner{
@ -826,7 +822,7 @@ func (m *model) renderMessageHeading(i int, message *models.Message) string {
suffix += faint.Render(" (not saved)") suffix += faint.Render(" (not saved)")
} }
return headingStyle.Render(prefix + user + suffix) return messageHeadingStyle.Render(prefix + user + suffix)
} }
func (m *model) renderMessage(msg *models.Message) string { func (m *model) renderMessage(msg *models.Message) string {