diff --git a/_examples/interactive_multiselect/show-selected-options/README.md b/_examples/interactive_multiselect/show-selected-options/README.md new file mode 100644 index 000000000..f96a463f9 --- /dev/null +++ b/_examples/interactive_multiselect/show-selected-options/README.md @@ -0,0 +1,36 @@ +# interactive_multiselect/show_selected_options + +```go +package main + +import ( + "fmt" + + "github.com/pterm/pterm" +) + +func main() { + // Initialize an empty slice to hold the options. + var options []string + + // Populate the options slice with 100 options. + for i := 0; i < 100; i++ { + options = append(options, fmt.Sprintf("Option %d", i)) + } + + // Add 5 more options to the slice, indicating the availability of fuzzy searching. + for i := 0; i < 5; i++ { + options = append(options, fmt.Sprintf("You can use fuzzy searching (%d)", i)) + } + + // Use PTerm's interactive multiselect to present the options to the user and capture their selections. + // The Show() method displays the options and waits for user input. + selectedOptions, _ := pterm.DefaultInteractiveMultiselect. + WithOptions(options). + WithShowSelectedOptions(true). + Show() + + // Print the selected options, highlighted in green. + pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions)) +} +``` diff --git a/_examples/interactive_multiselect/show-selected-options/main.go b/_examples/interactive_multiselect/show-selected-options/main.go new file mode 100644 index 000000000..6ccf0722f --- /dev/null +++ b/_examples/interactive_multiselect/show-selected-options/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + + "github.com/pterm/pterm" +) + +func main() { + // Initialize an empty slice to hold the options. + var options []string + + // Populate the options slice with 100 options. + for i := 0; i < 100; i++ { + options = append(options, fmt.Sprintf("Option %d", i)) + } + + // Use PTerm's interactive multiselect to present the options to the user and capture their selections. + // The Show() method displays the options and waits for user input. + selectedOptions, _ := pterm.DefaultInteractiveMultiselect. + WithOptions(options). + WithShowSelectedOptions(true). + Show() + + // Print the selected options, highlighted in green. + pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions)) +} diff --git a/interactive_multiselect_printer.go b/interactive_multiselect_printer.go index 9dce03fb3..025bfa2e9 100644 --- a/interactive_multiselect_printer.go +++ b/interactive_multiselect_printer.go @@ -2,13 +2,15 @@ package pterm import ( "fmt" - "sort" "atomicgo.dev/cursor" "atomicgo.dev/keyboard" "atomicgo.dev/keyboard/keys" "github.com/lithammer/fuzzysearch/fuzzy" + "sort" + "strings" + "github.com/pterm/pterm/internal" ) @@ -32,17 +34,18 @@ var ( // InteractiveMultiselectPrinter is a printer for interactive multiselect menus. type InteractiveMultiselectPrinter struct { - DefaultText string - TextStyle *Style - Options []string - OptionStyle *Style - DefaultOptions []string - MaxHeight int - Selector string - SelectorStyle *Style - Filter bool - Checkmark *Checkmark - OnInterruptFunc func() + DefaultText string + TextStyle *Style + Options []string + OptionStyle *Style + DefaultOptions []string + MaxHeight int + Selector string + SelectorStyle *Style + Filter bool + Checkmark *Checkmark + OnInterruptFunc func() + ShowSelectedOptions bool selectedOption int selectedOptions []int @@ -110,12 +113,18 @@ func (p InteractiveMultiselectPrinter) WithCheckmark(checkmark *Checkmark) *Inte return &p } -// OnInterrupt sets the function to execute on exit of the input reader +// WithOnInterruptFunc sets the function to execute on exit of the input reader func (p InteractiveMultiselectPrinter) WithOnInterruptFunc(exitFunc func()) *InteractiveMultiselectPrinter { p.OnInterruptFunc = exitFunc return &p } +// WithShowSelectedOptions shows the selected options at the bottom if the menu +func (p InteractiveMultiselectPrinter) WithShowSelectedOptions(b ...bool) *InteractiveMultiselectPrinter { + p.ShowSelectedOptions = internal.WithBoolean(b) + return &p +} + // Show shows the interactive multiselect menu and returns the selected entry. func (p *InteractiveMultiselectPrinter) Show(text ...string) ([]string, error) { // should be the first defer statement to make sure it is executed last @@ -379,10 +388,20 @@ func (p *InteractiveMultiselectPrinter) renderSelectMenu() string { help := fmt.Sprintf("%s: %s | %s: %s | left: %s | right: %s", p.KeySelect, Bold.Sprint("select"), p.KeyConfirm, Bold.Sprint("confirm"), Bold.Sprint("none"), Bold.Sprint("all")) if p.Filter { - help += fmt.Sprintf("| type to %s", Bold.Sprint("filter")) + help += fmt.Sprintf(" | type to %s", Bold.Sprint("filter")) } content += ThemeDefault.SecondaryStyle.Sprintfln(help) + // Optionally, add selected options to the menu + if p.ShowSelectedOptions && len(p.selectedOptions) > 0 { + selected := make([]string, len(p.selectedOptions)) + for i, optIdx := range p.selectedOptions { + selected[i] = p.Options[optIdx] + } + + content += ThemeDefault.SecondaryStyle.Sprint("Selected: ") + Green(strings.Join(selected, Gray(", "))) + "\n" + } + return content }