github.com/elves/elvish@v0.15.0/pkg/cli/addons/listing/listing.go (about)

     1  // Package listing provides the custom listing addon.
     2  package listing
     3  
     4  import (
     5  	"github.com/elves/elvish/pkg/cli"
     6  	"github.com/elves/elvish/pkg/ui"
     7  )
     8  
     9  // Config is the configuration to start the custom listing addon.
    10  type Config struct {
    11  	// Keybinding.
    12  	Binding cli.Handler
    13  	// Caption of the listing. If empty, defaults to " LISTING ".
    14  	Caption string
    15  	// A function that takes the query string and returns a list of Item's and
    16  	// the index of the Item to select. Required.
    17  	GetItems func(query string) (items []Item, selected int)
    18  	// A function to call when the user has accepted the selected item. If the
    19  	// return value is true, the listing will not be closed after accpeting.
    20  	// If unspecified, the Accept function default to a function that does
    21  	// nothing other than returning false.
    22  	Accept func(string) bool
    23  	// Whether to automatically accept when there is only one item.
    24  	AutoAccept bool
    25  }
    26  
    27  // Item is an item to show in the listing.
    28  type Item struct {
    29  	// Passed to the Accept callback in Config.
    30  	ToAccept string
    31  	// How the item is shown.
    32  	ToShow ui.Text
    33  }
    34  
    35  // Start starts the custom listing addon.
    36  func Start(app cli.App, cfg Config) {
    37  	if cfg.GetItems == nil {
    38  		app.Notify("internal error: GetItems must be specified")
    39  		return
    40  	}
    41  	if cfg.Accept == nil {
    42  		cfg.Accept = func(string) bool { return false }
    43  	}
    44  	if cfg.Caption == "" {
    45  		cfg.Caption = " LISTING "
    46  	}
    47  	accept := func(s string) {
    48  		retain := cfg.Accept(s)
    49  		if !retain {
    50  			cli.SetAddon(app, nil)
    51  		}
    52  	}
    53  	w := cli.NewComboBox(cli.ComboBoxSpec{
    54  		CodeArea: cli.CodeAreaSpec{
    55  			Prompt: cli.ModePrompt(cfg.Caption, true),
    56  		},
    57  		ListBox: cli.ListBoxSpec{
    58  			OverlayHandler: cfg.Binding,
    59  			OnAccept: func(it cli.Items, i int) {
    60  				accept(it.(items)[i].ToAccept)
    61  			},
    62  			ExtendStyle: true,
    63  		},
    64  		OnFilter: func(w cli.ComboBox, q string) {
    65  			it, selected := cfg.GetItems(q)
    66  			w.ListBox().Reset(items(it), selected)
    67  			if cfg.AutoAccept && len(it) == 1 {
    68  				accept(it[0].ToAccept)
    69  			}
    70  		},
    71  	})
    72  	cli.SetAddon(app, w)
    73  	app.Redraw()
    74  }
    75  
    76  type items []Item
    77  
    78  func (it items) Len() int           { return len(it) }
    79  func (it items) Show(i int) ui.Text { return it[i].ToShow }