github.com/elves/elvish@v0.15.0/pkg/cli/combobox.go (about) 1 package cli 2 3 import ( 4 "github.com/elves/elvish/pkg/cli/term" 5 ) 6 7 // ComboBox is a Widget that combines a ListBox and a CodeArea. 8 type ComboBox interface { 9 Widget 10 // Returns the embedded codearea widget. 11 CodeArea() CodeArea 12 // Returns the embedded listbox widget. 13 ListBox() ListBox 14 // Forces the filtering to rerun. 15 Refilter() 16 } 17 18 // ComboBoxSpec specifies the configuration and initial state for ComboBox. 19 type ComboBoxSpec struct { 20 CodeArea CodeAreaSpec 21 ListBox ListBoxSpec 22 OnFilter func(ComboBox, string) 23 } 24 25 type comboBox struct { 26 codeArea CodeArea 27 listBox ListBox 28 OnFilter func(ComboBox, string) 29 30 // Last filter value. 31 lastFilter string 32 } 33 34 // NewComboBox creates a new ComboBox from the given spec. 35 func NewComboBox(spec ComboBoxSpec) ComboBox { 36 if spec.OnFilter == nil { 37 spec.OnFilter = func(ComboBox, string) {} 38 } 39 w := &comboBox{ 40 codeArea: NewCodeArea(spec.CodeArea), 41 listBox: NewListBox(spec.ListBox), 42 OnFilter: spec.OnFilter, 43 } 44 w.OnFilter(w, "") 45 return w 46 } 47 48 // Render renders the codearea and the listbox below it. 49 func (w *comboBox) Render(width, height int) *term.Buffer { 50 buf := w.codeArea.Render(width, height) 51 bufListBox := w.listBox.Render(width, height-len(buf.Lines)) 52 buf.Extend(bufListBox, false) 53 return buf 54 } 55 56 // Handle first lets the listbox handle the event, and if it is unhandled, lets 57 // the codearea handle it. If the codearea has handled the event and the code 58 // content has changed, it calls OnFilter with the new content. 59 func (w *comboBox) Handle(event term.Event) bool { 60 if w.listBox.Handle(event) { 61 return true 62 } 63 if w.codeArea.Handle(event) { 64 filter := w.codeArea.CopyState().Buffer.Content 65 if filter != w.lastFilter { 66 w.OnFilter(w, filter) 67 w.lastFilter = filter 68 } 69 return true 70 } 71 return false 72 } 73 74 func (w *comboBox) Refilter() { 75 w.OnFilter(w, w.codeArea.CopyState().Buffer.Content) 76 } 77 78 func (w *comboBox) CodeArea() CodeArea { return w.codeArea } 79 func (w *comboBox) ListBox() ListBox { return w.listBox }