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