package gui import ( "fmt" "gitea.tyrel.dev/tyrel/itor/models" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "io" ) 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 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.(models.Card) if !ok { return } checked := " " // not selected if i.Selected { checked = "✓" // selected! } str := fmt.Sprintf("[%s] %d. %s", checked, index+1, i.ToString()) fn := itemStyle.Render if index == m.Index() { fn = func(s string) string { return selectedItemStyle.Render("> " + s) } } _, _ = fmt.Fprint(w, fn(str)) // ignore error } func (m *model) updateSelect(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.selectList.SetWidth(msg.Width) return m, nil // Is it a key press? case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit // The "up" and "k" keys move the selectCardIndex up case "up", "k": if m.selectCardIndex > 0 { m.selectCardIndex-- } // The "down" and "j" keys move the selectCardIndex down case "down", "j": if m.selectCardIndex < len(m.deck)-1 { m.selectCardIndex++ } // MODES case "d": // Only draw if at least one card if len(m.selected) > 0 { m.drawRandomCard() m.switchMode(Draw) } case "c": m.switchMode(Create) // The "enter" key and the spacebar (a literal space) toggle // the selected state for the item that the selectCardIndex is pointing at. case "enter", " ": card, ok := m.selectList.SelectedItem().(models.Card) if ok { idx := SliceIndex(len(m.deck), func(i int) bool { return m.deck[i].Id == card.Id }) if _, ok := m.selected[idx]; ok { delete(m.selected, idx) m.deck[idx].Selected = false } else { m.selected[idx] = struct{}{} m.deck[idx].Selected = true } m.selectList.SetItem(idx, m.deck[idx]) } } } var cmd tea.Cmd m.selectList, cmd = m.selectList.Update(msg) return m, cmd } func (m *model) viewSelect() string { return template(`Select cards to draw: {selectList} Press [↑/k] move up. Press [↓/j] move down. Press [enter/space] to toggle selection. Press [c] to Create. Press [d] to Draw. Press [q] to quit. `, "{selectList}", m.selectList.View(), ) } func SliceIndex(limit int, predicate func(i int) bool) int { for i := 0; i < limit; i++ { if predicate(i) { return i } } return -1 }