feat: implement rich multi-selector (#19201)

Fixes: https://github.com/coder/coder/issues/19182
This commit is contained in:
Marcin Tojek
2025-08-06 23:03:51 +02:00
committed by GitHub
parent 9505ecc73d
commit a7fac302bb
4 changed files with 193 additions and 61 deletions
+68
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/signal"
"slices"
"strings"
"syscall"
@@ -299,6 +300,73 @@ func (m selectModel) filteredOptions() []string {
return options
}
type RichMultiSelectOptions struct {
Message string
Options []codersdk.TemplateVersionParameterOption
Defaults []string
EnableCustomInput bool
}
func RichMultiSelect(inv *serpent.Invocation, richOptions RichMultiSelectOptions) ([]string, error) {
var opts []string
var defaultOpts []string
asLine := func(option codersdk.TemplateVersionParameterOption) string {
line := option.Name
if len(option.Description) > 0 {
line += ": " + option.Description
}
return line
}
var predefinedOpts []string
for i, option := range richOptions.Options {
opts = append(opts, asLine(option)) // Some options may have description defined.
// Check if option is selected by default
if slices.Contains(richOptions.Defaults, option.Value) {
defaultOpts = append(defaultOpts, opts[i])
predefinedOpts = append(predefinedOpts, option.Value)
}
}
// Check if "defaults" contains extra/custom options, user could select them.
for _, def := range richOptions.Defaults {
if !slices.Contains(predefinedOpts, def) {
opts = append(opts, def)
defaultOpts = append(defaultOpts, def)
}
}
selected, err := MultiSelect(inv, MultiSelectOptions{
Message: richOptions.Message,
Options: opts,
Defaults: defaultOpts,
EnableCustomInput: richOptions.EnableCustomInput,
})
if err != nil {
return nil, err
}
// Check selected option, convert descriptions (line) to values
var results []string
for _, sel := range selected {
custom := true
for i, option := range richOptions.Options {
if asLine(option) == sel {
results = append(results, richOptions.Options[i].Value)
custom = false
break
}
}
if custom {
results = append(results, sel)
}
}
return results, nil
}
type MultiSelectOptions struct {
Message string
Options []string