forked from Mirrors/bubbletea
138 lines
3.0 KiB
Go
138 lines
3.0 KiB
Go
|
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)
|
|||
|
}
|
|||
|
}
|