package fields import ( "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" ) type SelectModel struct { label string options []string focus int open bool chosen string } func NewSelectModel(label, value string, options []string) *SelectModel { found := false for i := range options { if options[i] == value { found = true } } if !found { value = "" } return &SelectModel{ options: options, label: label, focus: len(options), chosen: value, } } func (m *SelectModel) Init() tea.Cmd { return textinput.Blink } func (m *SelectModel) Update(msg tea.Msg) (FieldModel, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: if m.open { switch msg.String() { case "esc": m.open = false case "up": m.focus-- if m.focus < 0 { m.focus = len(m.options) - 1 } case "down": m.focus++ if m.focus == len(m.options) { m.focus = 0 } case "enter": if len(m.options) == 0 || m.focus == len(m.options) { return m, nil } m.chosen = m.options[m.focus] m.open = false m.focus = len(m.options) return m, nil } } else { switch msg.String() { case "enter": m.open = true for optionIdx := range m.options { if m.options[optionIdx] == m.chosen { m.focus = optionIdx } } if m.chosen == "" && len(m.options) > 0 { m.focus = 0 } } } } return m, cmd } func (m *SelectModel) View() string { res := fmt.Sprintf("%s: %s", m.label, m.chosen) if m.open && len(m.options) > 0 { for i := range m.options { if m.focus == i { res += "\n\t-> " + m.options[i] } else { res += "\n\t " + m.options[i] } } } return res } func (m *SelectModel) Close() { m.open = false } func (m *SelectModel) Focus() { } func (m *SelectModel) Blur() { m.open = false } func (m *SelectModel) CaptureKeys() bool { return m.open } func (m *SelectModel) GetLabel() string { return m.label } func (m *SelectModel) GetValue() interface{} { return m.chosen }