package main import( "fmt" tea "github.com/charmbracelet/bubbletea" ) 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.todos)-1 { m.cursor++ } case "left", "h": if m.tab > 0 { m.tab-- } case "right", "l": if m.tab < 4 { m.tab++ } // 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 := "" currentList := []todo{} switch m.tab { case 0: s += "Inbox" inboxFilter := func(t todo) bool { return t.isInbox} currentList = filter(m.todos, inboxFilter) case 1: s += "Today" case 2: s += "Tomorrow" case 3: s += "Scheduled" case 4: s += "Anytime" } s += "\n\n" // Iterate over our choices for i, choice := range currentList { // 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 += "n: new\n" s += "q: quit.\n" // Send the UI for rendering return s }