on main help sign in
chore: show configured indicator
commit99d4b010978f42801e3858d86740d468f5dea8ad authorKujtim Hoxha <kujtimii.h@gmail.com> dateMon 7 Jul 2025, 12:49 (1 year ago) parentfca9fbb
6 files changed+65−9
internal/tui/components/chat/splash/splash.go+1−1 internal/tui/components/core/helpers.go+16 internal/tui/components/core/list/list.go+5 internal/tui/components/dialogs/commands/item.go+16−4 internal/tui/components/dialogs/models/list.go+21−3 internal/tui/components/dialogs/models/models.go+6−1
internal/tui/components/chat/splash/splash.go+1−1
@@ -59,7 +59,7 @@ func New() Splash {
5959
6060 t := styles.CurrentTheme()
6161 inputStyle := t.S().Base.Padding(0, 1, 0, 1)
62− modelList := models.NewModelListComponent(listKeyMap, inputStyle)
62+ modelList := models.NewModelListComponent(listKeyMap, inputStyle, "Find your fave")
6363 return &splashCmp{
6464 width: 0,
6565 height: 0,
internal/tui/components/core/helpers.go+16
@@ -23,6 +23,22 @@ func Section(text string, width int) string {
2323 return text
2424}
2525
26+func SectionWithInfo(text string, width int, info string) string {
27+ t := styles.CurrentTheme()
28+ char := "─"
29+ length := lipgloss.Width(text) + 1
30+ remainingWidth := width - length
31+
32+ if info != "" {
33+ remainingWidth -= lipgloss.Width(info) + 1 // 1 for the space before info
34+ }
35+ lineStyle := t.S().Base.Foreground(t.Border)
36+ if remainingWidth > 0 {
37+ text = text + " " + lineStyle.Render(strings.Repeat(char, remainingWidth)) + " " + info
38+ }
39+ return text
40+}
41+
2642func Title(title string, width int) string {
2743 t := styles.CurrentTheme()
2844 char := "╱"
internal/tui/components/core/list/list.go+5
@@ -41,6 +41,7 @@ type ListModel interface {
4141 SelectedIndex() int // Get the index of the currently selected item
4242 SetSelected(int) tea.Cmd // Set the selected item by index and scroll to it
4343 Filter(string) tea.Cmd // Filter items based on a search term
44+ SetFilterPlaceholder(string) // Set the placeholder text for the filter input
4445}
4546
4647// HasAnim interface identifies items that support animation.
@@ -1355,3 +1356,7 @@ func (m *model) Focus() tea.Cmd {
13551356func (m *model) IsFocused() bool {
13561357 return m.isFocused
13571358}
1359+
1360+func (m *model) SetFilterPlaceholder(placeholder string) {
1361+ m.input.Placeholder = placeholder
1362+}
internal/tui/components/dialogs/commands/item.go+16−4
@@ -14,11 +14,12 @@ type ItemSection interface {
1414 util.Model
1515 layout.Sizeable
1616 list.SectionHeader
17+ SetInfo(info string)
1718}
1819type itemSectionModel struct {
19− width int
20− title string
21− noPadding bool // No padding for the section header
20+ width int
21+ title string
22+ info string
2223}
2324
2425func NewItemSection(title string) ItemSection {
@@ -40,7 +41,14 @@ func (m *itemSectionModel) View() tea.View {
4041 title := ansi.Truncate(m.title, m.width-2, "…")
4142 style := t.S().Base.Padding(1, 1, 0, 1)
4243 title = t.S().Muted.Render(title)
43− return tea.NewView(style.Render(core.Section(title, m.width-2)))
44+ section := ""
45+ if m.info != "" {
46+ section = core.SectionWithInfo(title, m.width-2, m.info)
47+ } else {
48+ section = core.Section(title, m.width-2)
49+ }
50+
51+ return tea.NewView(style.Render(section))
4452}
4553
4654func (m *itemSectionModel) GetSize() (int, int) {
@@ -55,3 +63,7 @@ func (m *itemSectionModel) SetSize(width int, height int) tea.Cmd {
5563func (m *itemSectionModel) IsSectionHeader() bool {
5664 return true
5765}
66+
67+func (m *itemSectionModel) SetInfo(info string) {
68+ m.info = info
69+}
internal/tui/components/dialogs/models/list.go+21−3
@@ -1,6 +1,7 @@
11package models
22
33import (
4+ "fmt"
45 "slices"
56
67 tea "github.com/charmbracelet/bubbletea/v2"
@@ -9,6 +10,7 @@ import (
910 "github.com/charmbracelet/crush/internal/tui/components/completions"
1011 "github.com/charmbracelet/crush/internal/tui/components/core/list"
1112 "github.com/charmbracelet/crush/internal/tui/components/dialogs/commands"
13+ "github.com/charmbracelet/crush/internal/tui/styles"
1214 "github.com/charmbracelet/crush/internal/tui/util"
1315 "github.com/charmbracelet/lipgloss/v2"
1416)
@@ -18,11 +20,12 @@ type ModelListComponent struct {
1820 modelType int
1921}
2022
21−func NewModelListComponent(keyMap list.KeyMap, inputStyle lipgloss.Style) *ModelListComponent {
23+func NewModelListComponent(keyMap list.KeyMap, inputStyle lipgloss.Style, inputPlaceholder string) *ModelListComponent {
2224 modelList := list.New(
2325 list.WithFilterable(true),
2426 list.WithKeyMap(keyMap),
2527 list.WithInputStyle(inputStyle),
28+ list.WithFilterPlaceholder(inputPlaceholder),
2629 list.WithWrapNavigation(true),
2730 )
2831
@@ -59,6 +62,7 @@ func (m *ModelListComponent) SelectedIndex() int {
5962}
6063
6164func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
65+ t := styles.CurrentTheme()
6266 m.modelType = modelType
6367
6468 providers, err := config.Providers()
@@ -77,6 +81,9 @@ func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
7781 currentModel = cfg.Models[config.SelectedModelTypeSmall]
7882 }
7983
84+ configuredIcon := t.S().Base.Foreground(t.Success).Render(styles.CheckIcon)
85+ configured := fmt.Sprintf("%s %s", configuredIcon, t.S().Subtle.Render("Configured"))
86+
8087 // Create a map to track which providers we've already added
8188 addedProviders := make(map[string]bool)
8289
@@ -120,7 +127,9 @@ func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
120127 if name == "" {
121128 name = string(configProvider.ID)
122129 }
123− modelItems = append(modelItems, commands.NewItemSection(name))
130+ section := commands.NewItemSection(name)
131+ section.SetInfo(configured)
132+ modelItems = append(modelItems, section)
124133 for _, model := range configProvider.Models {
125134 modelItems = append(modelItems, completions.NewCompletionItem(model.Name, ModelOption{
126135 Provider: configProvider,
@@ -150,7 +159,12 @@ func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
150159 if name == "" {
151160 name = string(provider.ID)
152161 }
153− modelItems = append(modelItems, commands.NewItemSection(name))
162+
163+ section := commands.NewItemSection(name)
164+ if _, ok := cfg.Providers[string(provider.ID)]; ok {
165+ section.SetInfo(configured)
166+ }
167+ modelItems = append(modelItems, section)
154168 for _, model := range provider.Models {
155169 modelItems = append(modelItems, completions.NewCompletionItem(model.Name, ModelOption{
156170 Provider: provider,
@@ -169,3 +183,7 @@ func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
169183func (m *ModelListComponent) GetModelType() int {
170184 return m.modelType
171185}
186+
187+func (m *ModelListComponent) SetInputPlaceholder(placeholder string) {
188+ m.list.SetFilterPlaceholder(placeholder)
189+}
internal/tui/components/dialogs/models/models.go+6−1
@@ -24,6 +24,9 @@ const (
2424const (
2525 LargeModelType int = iota
2626 SmallModelType
27+
28+ largeModelInputPlaceholder = "Choose a model for large, complex tasks"
29+ smallModelInputPlaceholder = "Choose a model for small, simple tasks"
2730)
2831
2932// ModelSelectedMsg is sent when a model is selected
@@ -71,7 +74,7 @@ func NewModelDialogCmp() ModelDialog {
7174
7275 t := styles.CurrentTheme()
7376 inputStyle := t.S().Base.Padding(0, 1, 0, 1)
74− modelList := NewModelListComponent(listKeyMap, inputStyle)
77+ modelList := NewModelListComponent(listKeyMap, inputStyle, "Choose a model for large, complex tasks")
7578 help := help.New()
7679 help.Styles = t.S().Help
7780
@@ -122,8 +125,10 @@ func (m *modelDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
122125 )
123126 case key.Matches(msg, m.keyMap.Tab):
124127 if m.modelList.GetModelType() == LargeModelType {
128+ m.modelList.SetInputPlaceholder(smallModelInputPlaceholder)
125129 return m, m.modelList.SetModelType(SmallModelType)
126130 } else {
131+ m.modelList.SetInputPlaceholder(largeModelInputPlaceholder)
127132 return m, m.modelList.SetModelType(LargeModelType)
128133 }
129134 case key.Matches(msg, m.keyMap.Close):