-
-
Save meowgorithm/90b3b645f8a82196442a72b5e0cf61ba to your computer and use it in GitHub Desktop.
Bubble Tea simple list example with filtering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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": | |
if m.list.FilterState() != list.Filtering { | |
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 | |
} | |
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(true) | |
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) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment