aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/manifoldco/promptui/list
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2020-10-07 16:58:53 +0200
committerValentin Rothberg <rothberg@redhat.com>2020-11-13 15:40:06 +0100
commit8e4a42aa429c6dec0d5face7c69554d8a0677e96 (patch)
treebbfff77e7b32a8b46af6f57d42965a7751bec18e /vendor/github.com/manifoldco/promptui/list
parent0b1a60ec27928a40ac827148c1517098612616bd (diff)
downloadpodman-8e4a42aa429c6dec0d5face7c69554d8a0677e96.tar.gz
podman-8e4a42aa429c6dec0d5face7c69554d8a0677e96.tar.bz2
podman-8e4a42aa429c6dec0d5face7c69554d8a0677e96.zip
short-name aliasing
Add support for short-name aliasing. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'vendor/github.com/manifoldco/promptui/list')
-rw-r--r--vendor/github.com/manifoldco/promptui/list/list.go237
1 files changed, 237 insertions, 0 deletions
diff --git a/vendor/github.com/manifoldco/promptui/list/list.go b/vendor/github.com/manifoldco/promptui/list/list.go
new file mode 100644
index 000000000..c98a39cfa
--- /dev/null
+++ b/vendor/github.com/manifoldco/promptui/list/list.go
@@ -0,0 +1,237 @@
+package list
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// Searcher is a base function signature that is used inside select when activating the search mode.
+// If defined, it is called on each items of the select and should return a boolean for whether or not
+// the item fits the searched term.
+type Searcher func(input string, index int) bool
+
+// NotFound is an index returned when no item was selected. This could
+// happen due to a search without results.
+const NotFound = -1
+
+// List holds a collection of items that can be displayed with an N number of
+// visible items. The list can be moved up, down by one item of time or an
+// entire page (ie: visible size). It keeps track of the current selected item.
+type List struct {
+ items []*interface{}
+ scope []*interface{}
+ cursor int // cursor holds the index of the current selected item
+ size int // size is the number of visible options
+ start int
+ Searcher Searcher
+}
+
+// New creates and initializes a list of searchable items. The items attribute must be a slice type with a
+// size greater than 0. Error will be returned if those two conditions are not met.
+func New(items interface{}, size int) (*List, error) {
+ if size < 1 {
+ return nil, fmt.Errorf("list size %d must be greater than 0", size)
+ }
+
+ if items == nil || reflect.TypeOf(items).Kind() != reflect.Slice {
+ return nil, fmt.Errorf("items %v is not a slice", items)
+ }
+
+ slice := reflect.ValueOf(items)
+ values := make([]*interface{}, slice.Len())
+
+ for i := range values {
+ item := slice.Index(i).Interface()
+ values[i] = &item
+ }
+
+ return &List{size: size, items: values, scope: values}, nil
+}
+
+// Prev moves the visible list back one item. If the selected item is out of
+// view, the new select item becomes the last visible item. If the list is
+// already at the top, nothing happens.
+func (l *List) Prev() {
+ if l.cursor > 0 {
+ l.cursor--
+ }
+
+ if l.start > l.cursor {
+ l.start = l.cursor
+ }
+}
+
+// Search allows the list to be filtered by a given term. The list must
+// implement the searcher function signature for this functionality to work.
+func (l *List) Search(term string) {
+ term = strings.Trim(term, " ")
+ l.cursor = 0
+ l.start = 0
+ l.search(term)
+}
+
+// CancelSearch stops the current search and returns the list to its
+// original order.
+func (l *List) CancelSearch() {
+ l.cursor = 0
+ l.start = 0
+ l.scope = l.items
+}
+
+func (l *List) search(term string) {
+ var scope []*interface{}
+
+ for i, item := range l.items {
+ if l.Searcher(term, i) {
+ scope = append(scope, item)
+ }
+ }
+
+ l.scope = scope
+}
+
+// Start returns the current render start position of the list.
+func (l *List) Start() int {
+ return l.start
+}
+
+// SetStart sets the current scroll position. Values out of bounds will be
+// clamped.
+func (l *List) SetStart(i int) {
+ if i < 0 {
+ i = 0
+ }
+ if i > l.cursor {
+ l.start = l.cursor
+ } else {
+ l.start = i
+ }
+}
+
+// SetCursor sets the position of the cursor in the list. Values out of bounds
+// will be clamped.
+func (l *List) SetCursor(i int) {
+ max := len(l.scope) - 1
+ if i >= max {
+ i = max
+ }
+ if i < 0 {
+ i = 0
+ }
+ l.cursor = i
+
+ if l.start > l.cursor {
+ l.start = l.cursor
+ } else if l.start+l.size <= l.cursor {
+ l.start = l.cursor - l.size + 1
+ }
+}
+
+// Next moves the visible list forward one item. If the selected item is out of
+// view, the new select item becomes the first visible item. If the list is
+// already at the bottom, nothing happens.
+func (l *List) Next() {
+ max := len(l.scope) - 1
+
+ if l.cursor < max {
+ l.cursor++
+ }
+
+ if l.start+l.size <= l.cursor {
+ l.start = l.cursor - l.size + 1
+ }
+}
+
+// PageUp moves the visible list backward by x items. Where x is the size of the
+// visible items on the list. The selected item becomes the first visible item.
+// If the list is already at the bottom, the selected item becomes the last
+// visible item.
+func (l *List) PageUp() {
+ start := l.start - l.size
+ if start < 0 {
+ l.start = 0
+ } else {
+ l.start = start
+ }
+
+ cursor := l.start
+
+ if cursor < l.cursor {
+ l.cursor = cursor
+ }
+}
+
+// PageDown moves the visible list forward by x items. Where x is the size of
+// the visible items on the list. The selected item becomes the first visible
+// item.
+func (l *List) PageDown() {
+ start := l.start + l.size
+ max := len(l.scope) - l.size
+
+ switch {
+ case len(l.scope) < l.size:
+ l.start = 0
+ case start > max:
+ l.start = max
+ default:
+ l.start = start
+ }
+
+ cursor := l.start
+
+ if cursor == l.cursor {
+ l.cursor = len(l.scope) - 1
+ } else if cursor > l.cursor {
+ l.cursor = cursor
+ }
+}
+
+// CanPageDown returns whether a list can still PageDown().
+func (l *List) CanPageDown() bool {
+ max := len(l.scope)
+ return l.start+l.size < max
+}
+
+// CanPageUp returns whether a list can still PageUp().
+func (l *List) CanPageUp() bool {
+ return l.start > 0
+}
+
+// Index returns the index of the item currently selected inside the searched list. If no item is selected,
+// the NotFound (-1) index is returned.
+func (l *List) Index() int {
+ selected := l.scope[l.cursor]
+
+ for i, item := range l.items {
+ if item == selected {
+ return i
+ }
+ }
+
+ return NotFound
+}
+
+// Items returns a slice equal to the size of the list with the current visible
+// items and the index of the active item in this list.
+func (l *List) Items() ([]interface{}, int) {
+ var result []interface{}
+ max := len(l.scope)
+ end := l.start + l.size
+
+ if end > max {
+ end = max
+ }
+
+ active := NotFound
+
+ for i, j := l.start, 0; i < end; i, j = i+1, j+1 {
+ if l.cursor == i {
+ active = j
+ }
+
+ result = append(result, *l.scope[i])
+ }
+
+ return result, active
+}