package main import ( "fmt" "io" "os" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) const listHeight = 14 var ( titleStyle = lipgloss.NewStyle().MarginLeft(2) itemStyle = lipgloss.NewStyle().PaddingLeft(4) selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170")) paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4) ) type item string func (i item) FilterValue() string { return string(i) } type itemDelegate struct{} func (d itemDelegate) Height() int { return 1 } func (d itemDelegate) Spacing() int { return 0 } func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { i, ok := listItem.(item) if !ok { return } str := fmt.Sprintf("%d. %s", index+1, i) fn := itemStyle.Render if index == m.Index() { fn = func(s string) string { return selectedItemStyle.Render("> " + s) } } fmt.Fprintf(w, fn(str)) } type model struct { list list.Model items []item choice string quitting bool } func (m model) Init() tea.Cmd { return nil } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.list.SetWidth(msg.Width) return m, nil case tea.KeyMsg: switch keypress := msg.String(); keypress { case "ctrl+c": m.quitting = true return m, tea.Quit case "enter": i, ok := m.list.SelectedItem().(item) if ok { m.choice = string(i) } return m, tea.Quit default: if !m.list.SettingFilter() && (keypress == "q" || keypress == "esc") { m.quitting = true return m, tea.Quit } var cmd tea.Cmd m.list, cmd = m.list.Update(msg) return m, cmd } default: return m, nil } } func (m model) View() string { if m.choice != "" { return quitTextStyle.Render(fmt.Sprintf("%s? Sounds good to me.", m.choice)) } if m.quitting { return quitTextStyle.Render("Not hungry? That’s cool.") } return "\n" + m.list.View() } func main() { items := []list.Item{ item("Ramen"), item("Tomato Soup"), item("Hamburgers"), item("Cheeseburgers"), item("Currywurst"), item("Okonomiyaki"), item("Pasta"), item("Fillet Mignon"), item("Caviar"), item("Just Wine"), } const defaultWidth = 20 l := list.NewModel(items, itemDelegate{}, defaultWidth, listHeight) l.Title = "What do you want for dinner?" l.SetShowStatusBar(false) l.SetFilteringEnabled(false) l.Styles.Title = titleStyle l.Styles.PaginationStyle = paginationStyle l.Styles.HelpStyle = helpStyle m := model{list: l} if err := tea.NewProgram(m).Start(); err != nil { fmt.Println("Error running program:", err) os.Exit(1) } }