mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
The module path moved to charm.land/huh/v2. Update the import in the ui prompts and refresh go.mod and go.sum. No API changes were needed.
72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
// Package ui provides small interactive prompts and their non-interactive
|
|
// equivalents for tests.
|
|
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"charm.land/huh/v2"
|
|
)
|
|
|
|
type msOpts struct {
|
|
nonInteractive []string
|
|
interactive bool
|
|
}
|
|
|
|
// Option configures MultiSelect behaviour.
|
|
type Option func(*msOpts)
|
|
|
|
// WithNonInteractive bypasses the TUI entirely and returns the given choices.
|
|
// Test code uses this to make MultiSelect deterministic.
|
|
func WithNonInteractive(choices []string) Option {
|
|
return func(o *msOpts) {
|
|
o.nonInteractive = choices
|
|
o.interactive = false
|
|
}
|
|
}
|
|
|
|
// MultiSelect prompts the user (or returns the pre-set non-interactive value).
|
|
// Choices passed via WithNonInteractive must all appear in `choices`.
|
|
func MultiSelect(title string, choices []string, opts ...Option) ([]string, error) {
|
|
o := &msOpts{interactive: true}
|
|
for _, fn := range opts {
|
|
fn(o)
|
|
}
|
|
if !o.interactive {
|
|
valid := map[string]bool{}
|
|
for _, c := range choices {
|
|
valid[c] = true
|
|
}
|
|
for _, c := range o.nonInteractive {
|
|
if !valid[c] {
|
|
return nil, fmt.Errorf("choice %q not in %v", c, choices)
|
|
}
|
|
}
|
|
return o.nonInteractive, nil
|
|
}
|
|
// Pre-select every choice. Users deselect what they don't want; hitting
|
|
// enter without toggling thus accepts all (the common case) instead of
|
|
// silently producing an empty result.
|
|
picked := make([]string, len(choices))
|
|
copy(picked, choices)
|
|
|
|
opts2 := make([]huh.Option[string], 0, len(choices))
|
|
for _, c := range choices {
|
|
opts2 = append(opts2, huh.NewOption(c, c).Selected(true))
|
|
}
|
|
form := huh.NewForm(huh.NewGroup(
|
|
huh.NewMultiSelect[string]().
|
|
Title(title).
|
|
Description("space to toggle · enter to confirm · all pre-selected").
|
|
Options(opts2...).
|
|
Value(&picked),
|
|
))
|
|
if err := form.Run(); err != nil {
|
|
return nil, err
|
|
}
|
|
if len(picked) == 0 {
|
|
return nil, fmt.Errorf("no items selected")
|
|
}
|
|
return picked, nil
|
|
}
|