148 lines
3.1 KiB
Go
148 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/textinput"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/charmbracelet/bubbles/list"
|
|
)
|
|
|
|
|
|
type item struct {
|
|
value string
|
|
}
|
|
func (i item) FilterValue() string { return i.value }
|
|
type itemDelegate struct{}
|
|
|
|
func (d itemDelegate) Height() int { return 1 }
|
|
func (d itemDelegate) Spacing() int { return 0 }
|
|
func (d itemDelegate) Update(_ tea.Msg, _ *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("%s", i.value)
|
|
|
|
fn := lipgloss.NewStyle().PaddingLeft(2).Render
|
|
if index == m.Index() {
|
|
fn = func(s ...string) string {
|
|
return lipgloss.NewStyle().PaddingLeft(0).PaddingRight(1).Background(lipgloss.Color("#0F7FCF")).Render("> " + strings.Join(s, " "))
|
|
}
|
|
}
|
|
|
|
fmt.Fprint(w, fn(str))
|
|
}
|
|
|
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
var cmd tea.Cmd
|
|
ignoreInput := false
|
|
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
switch msg.Type {
|
|
case tea.KeyCtrlC, tea.KeyEsc:
|
|
m.quitting = true;
|
|
return m, tea.Quit
|
|
case tea.KeyEnter:
|
|
i, ok := m.list.SelectedItem().(item)
|
|
if ok {
|
|
m.choice = i.value
|
|
}
|
|
return m, tea.Quit
|
|
case tea.KeyUp, tea.KeyCtrlK:
|
|
m.list.CursorUp()
|
|
ignoreInput = true
|
|
case tea.KeyDown, tea.KeyCtrlJ:
|
|
m.list.CursorDown()
|
|
ignoreInput = true
|
|
}
|
|
|
|
// We handle errors just like any other message
|
|
case errMsg:
|
|
m.err = msg
|
|
return m, nil
|
|
|
|
case tea.WindowSizeMsg:
|
|
m.textInput.Width = msg.Width
|
|
m.list.SetWidth(msg.Width)
|
|
return m, nil
|
|
}
|
|
|
|
if ignoreInput {
|
|
return m, cmd
|
|
}
|
|
cmds := []tea.Cmd{}
|
|
|
|
m.textInput, cmd = m.textInput.Update(msg)
|
|
cmds = append(cmds, cmd)
|
|
|
|
|
|
if !m.list.SettingFilter() {
|
|
m.list, cmd = m.list.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("/")})
|
|
cmds = append(cmds, cmd)
|
|
}
|
|
m.list, cmd = m.list.Update(msg)
|
|
cmds = append(cmds, cmd)
|
|
|
|
return m, tea.Batch(cmds...)
|
|
}
|
|
|
|
func (m model) View() string {
|
|
if m.choice != "" {
|
|
return m.choice
|
|
}
|
|
if m.quitting {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("%s\n",
|
|
m.list.View(),
|
|
)
|
|
}
|
|
|
|
|
|
type (
|
|
errMsg error
|
|
)
|
|
|
|
type model struct {
|
|
textInput textinput.Model
|
|
list list.Model
|
|
choice string
|
|
quitting bool
|
|
err error
|
|
}
|
|
|
|
func initialModel(items []list.Item) model {
|
|
const defaultWidth = 20
|
|
|
|
l := list.New(items, itemDelegate{}, defaultWidth, 14)
|
|
l.SetShowFilter(true)
|
|
l.SetShowStatusBar(false)
|
|
l.SetFilteringEnabled(true)
|
|
l.SetShowHelp(false)
|
|
l.SetShowTitle(false)
|
|
l.SetShowPagination(false)
|
|
l.Styles.TitleBar = lipgloss.NewStyle()
|
|
ti := textinput.New()
|
|
ti.Focus()
|
|
ti.CharLimit = 4096
|
|
ti.Width = 20
|
|
l.FilterInput = ti
|
|
l.Filter = Filter
|
|
|
|
return model{
|
|
list: l,
|
|
err: nil,
|
|
}
|
|
}
|
|
|
|
func (m model) Init() tea.Cmd {
|
|
return textinput.Blink
|
|
}
|