okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

dawnadd charm tui skillf7fcae1

main
1.5 KiB75 linesraw
1package main
2
3import (
4	"fmt"
5	"io"
6	"strings"
7)
8
9type item struct{ ID, Label, Detail string }
10
11type selection struct {
12	items   []item
13	visible []int // Indexes into items; never the identity returned to a caller.
14	cursor  int
15}
16
17func newSelection(items []item) selection {
18	s := selection{items: append([]item(nil), items...)}
19	s.filter("")
20	return s
21}
22
23func (s *selection) current() (item, bool) {
24	if s.cursor < 0 || s.cursor >= len(s.visible) {
25		return item{}, false
26	}
27	return s.items[s.visible[s.cursor]], true
28}
29
30func (s *selection) filter(query string) {
31	old, hadOld := s.current()
32	s.visible = nil
33	query = strings.ToLower(query)
34	for i, row := range s.items {
35		if strings.Contains(strings.ToLower(row.Label), query) {
36			s.visible = append(s.visible, i)
37		}
38	}
39	s.cursor = 0
40	if hadOld {
41		for i, index := range s.visible {
42			if s.items[index].ID == old.ID {
43				s.cursor = i
44				break
45			}
46		}
47	}
48}
49
50func (s *selection) move(delta int) {
51	s.cursor = min(max(0, s.cursor+delta), max(0, len(s.visible)-1))
52}
53
54type outcome struct {
55	Accepted, Interrupted bool
56	ID                    string
57}
58
59// finish is called only after Bubble Tea has released the terminal.
60// Demo policy: 0 accepted, 1 cancelled, 130 keyboard interrupt, 2 failure.
61func finish(w io.Writer, result outcome) (int, error) {
62	if result.Interrupted {
63		return 130, nil
64	}
65	if !result.Accepted {
66		return 1, nil
67	}
68	if result.ID == "" {
69		return 2, fmt.Errorf("accepted result has no ID")
70	}
71	if _, err := fmt.Fprintln(w, result.ID); err != nil {
72		return 2, err
73	}
74	return 0, nil
75}