From 08ed3e251974347397ca74ba52de48491815a08a Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Fri, 13 Jan 2023 00:06:11 +0530 Subject: [PATCH] feat(choose): keep order of selected items (#182) * feat(choose): keep order of selected items * fix: KeepOrder -> Ordered Co-authored-by: Maas Lalani --- choose/choose.go | 8 ++++++++ choose/command.go | 16 ++++++++++++++-- choose/options.go | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/choose/choose.go b/choose/choose.go index 9aa6f93..0e898fa 100644 --- a/choose/choose.go +++ b/choose/choose.go @@ -30,6 +30,7 @@ type model struct { index int limit int numSelected int + currentOrder int paginator paginator.Model aborted bool @@ -42,6 +43,7 @@ type model struct { type item struct { text string selected bool + order int } func (m model) Init() tea.Cmd { return nil } @@ -96,7 +98,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { continue } m.items[i].selected = true + m.items[i].order = m.currentOrder m.numSelected++ + m.currentOrder++ } case "A": if m.limit <= 1 { @@ -104,8 +108,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } for i := range m.items { m.items[i].selected = false + m.items[i].order = 0 } m.numSelected = 0 + m.currentOrder = 0 case "ctrl+c", "esc": m.aborted = true m.quitting = true @@ -120,7 +126,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.numSelected-- } else if m.numSelected < m.limit { m.items[m.index].selected = true + m.items[m.index].order = m.currentOrder m.numSelected++ + m.currentOrder++ } case "enter": m.quitting = true diff --git a/choose/command.go b/choose/command.go index 6dd6b99..6c39788 100644 --- a/choose/command.go +++ b/choose/command.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "sort" "strings" "github.com/alecthomas/kong" @@ -56,10 +57,12 @@ func (o Options) Run() error { hasSelectedItems := len(o.Selected) > 0 startingIndex := 0 + currentOrder := 0 - var items = make([]item, len(o.Options)) + items := make([]item, len(o.Options)) for i, option := range o.Options { + var order int // Check if the option should be selected. isSelected := hasSelectedItems && currentSelected < o.Limit && arrayContains(o.Selected, option) // If the option is selected then increment the current selected count. @@ -71,10 +74,12 @@ func (o Options) Run() error { isSelected = false } else { currentSelected++ + order = currentOrder + currentOrder++ } } - items[i] = item{text: option, selected: isSelected} + items[i] = item{text: option, selected: isSelected, order: order} } // Use the pagination model to display the current and total number of @@ -94,6 +99,7 @@ func (o Options) Run() error { tm, err := tea.NewProgram(model{ index: startingIndex, + currentOrder: currentOrder, height: o.Height, cursor: o.Cursor, selectedPrefix: o.SelectedPrefix, @@ -117,6 +123,12 @@ func (o Options) Run() error { return exit.ErrAborted } + if o.Ordered && o.Limit > 1 { + sort.Slice(m.items, func(i, j int) bool { + return m.items[i].order < m.items[j].order + }) + } + var s strings.Builder for _, item := range m.items { diff --git a/choose/options.go b/choose/options.go index 68eb412..f6ee123 100644 --- a/choose/options.go +++ b/choose/options.go @@ -8,6 +8,7 @@ type Options struct { Limit int `help:"Maximum number of options to pick" default:"1" group:"Selection"` NoLimit bool `help:"Pick unlimited number of options (ignores limit)" group:"Selection"` + Ordered bool `help:"Maintain the order of the selected options" env:"GUM_CHOOSE_ORDERED"` Height int `help:"Height of the list" default:"10" env:"GUM_CHOOSE_HEIGHT"` Cursor string `help:"Prefix to show on item that corresponds to the cursor position" default:"> " env:"GUM_CHOOSE_CURSOR"` CursorPrefix string `help:"Prefix to show on the cursor item (hidden if limit is 1)" default:"○ " env:"GUM_CHOOSE_CURSOR_PREFIX"`