123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- // localizing all of the functions required to construct the user interface
- package itashi
- import (
- "fmt"
- tea "github.com/charmbracelet/bubbletea"
- )
- type model struct {
- choices []string
- cursor int
- selected map[int]struct{}
- }
- func initialModel() model {
- return model{
- // Our to-do list is a grocery list
- choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
- // A map which indicates which choices are selected. We're using
- // the map like a mathematical set. The keys refer to the indexes
- // of the `choices` slice, above.
- selected: make(map[int]struct{}),
- }
- }
- func (m model) Init() tea.Cmd {
- // Just return `nil`, which means "no I/O right now, please."
- return nil
- }
- func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
- switch msg := msg.(type) {
- // Is it a key press?
- case tea.KeyMsg:
- // Cool, what was the actual key pressed?
- switch msg.String() {
- // These keys should exit the program.
- case "ctrl+c", "q":
- return m, tea.Quit
- // The "up" and "k" keys move the cursor up
- case "up", "k":
- if m.cursor > 0 {
- m.cursor--
- }
- // The "down" and "j" keys move the cursor down
- case "down", "j":
- if m.cursor < len(m.choices)-1 {
- m.cursor++
- }
- // The "enter" key and the spacebar (a literal space) toggle
- // the selected state for the item that the cursor is pointing at.
- case "enter", " ":
- _, ok := m.selected[m.cursor]
- if ok {
- delete(m.selected, m.cursor)
- } else {
- m.selected[m.cursor] = struct{}{}
- }
- }
- }
- // Return the updated model to the Bubble Tea runtime for processing.
- // Note that we're not returning a command.
- return m, nil
- }
- func (m model) View() string {
- // The header
- s := "What should we buy at the market?\n\n"
- // Iterate over our choices
- for i, choice := range m.choices {
- // Is the cursor pointing at this choice?
- cursor := " " // no cursor
- if m.cursor == i {
- cursor = ">" // cursor!
- }
- // Is this choice selected?
- checked := " " // not selected
- if _, ok := m.selected[i]; ok {
- checked = "x" // selected!
- }
- // Render the row
- s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
- }
- // The footer
- s += "\nPress q to quit.\n"
- // Send the UI for rendering
- return s
- }
|