package main import ( "fmt" "github.com/charmbracelet/lipgloss" 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) { var cmd tea.Cmd if m.addTask { m.textinput, cmd = m.textinput.Update(msg) } 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.addTask { m.cursor-- } // The "down" and "j" keys move the cursor down case "down", "j": if m.cursor < len(m.todos)-1 && !m.addTask { m.cursor++ } case "left", "h": if m.tab > 0 && !m.addTask { m.tab-- } case "right", "l": if m.tab < 4 && !m.addTask { m.tab++ } // new task case "n": if !m.addTask { m.addTask = true m.textinput.Focus() m.textinput.Reset() } case "esc": if m.addTask { m.addTask = false m.textinput.Reset() } case "enter": if m.addTask { AddNewTask(m) m.addTask = false m.textinput.Reset() } // The "enter" key and the spacebar (a literal space) toggle // the selected state for the item that the cursor is pointing at. case " ": _, 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, cmd } func AddNewTask(m model) { t := todo{ name: m.textinput.Value(), done: false, startdate: 0, deadline: 0, priority: 1, isInbox: true, } m.todos = append(m.todos, t) } func (m model) View() string { // The header s := "" currentList := []todo{} s += "GOTD\n" 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, value := 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, value) } // render tab bar for i, v := range []string{"Inbox", "Today", "Tomorrow", "Scheduled", "Anytime"} { if i == m.tab { s += lipgloss.NewStyle(). Bold(true). Underline(true). PaddingRight(3). Render(v) } else { s += lipgloss.NewStyle(). PaddingRight(3). Render(v) } } // The footer s += "\nn: new" if m.addTask { s += ": " s += m.textinput.View() } s += "\nq: quit.\n" // Send the UI for rendering return s }