tui: renamed uiCache to views, cleanup
This commit is contained in:
parent
0b991800d6
commit
9cd28d28d7
130
pkg/tui/tui.go
130
pkg/tui/tui.go
@ -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
|
||||||
|
|
||||||
@ -204,7 +212,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.width = msg.Width
|
m.width = msg.Width
|
||||||
m.height = msg.Height
|
m.height = msg.Height
|
||||||
m.content.Width = msg.Width
|
m.content.Width = msg.Width
|
||||||
m.input.SetWidth(msg.Width-m.input.FocusedStyle.Base.GetHorizontalBorderSize())
|
m.input.SetWidth(msg.Width - m.input.FocusedStyle.Base.GetHorizontalBorderSize())
|
||||||
m.rebuildMessageCache()
|
m.rebuildMessageCache()
|
||||||
m.updateContent()
|
m.updateContent()
|
||||||
case msgConversationLoaded:
|
case msgConversationLoaded:
|
||||||
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user