mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
- internal/ui/prompts.go: MultiSelect with huh TUI + WithNonInteractive for tests - internal/cli/init.go: NewInit cobra command with --from/--no-prompt flags - internal/cli/init_test.go: TestInitImportWritesCanonical - internal/cli/root.go: add resolveRoot helper (shared by profile/rollback/show/init) - go.mod: add github.com/charmbracelet/huh v1.0.0 as direct dep
63 lines
1.5 KiB
Go
63 lines
1.5 KiB
Go
// Package ui provides small interactive prompts and their non-interactive
|
|
// equivalents for tests.
|
|
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/charmbracelet/huh"
|
|
)
|
|
|
|
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
|
|
}
|
|
var picked []string
|
|
opts2 := make([]huh.Option[string], 0, len(choices))
|
|
for _, c := range choices {
|
|
opts2 = append(opts2, huh.NewOption(c, c))
|
|
}
|
|
form := huh.NewForm(huh.NewGroup(
|
|
huh.NewMultiSelect[string]().
|
|
Title(title).
|
|
Options(opts2...).
|
|
Value(&picked),
|
|
))
|
|
if err := form.Run(); err != nil {
|
|
return nil, err
|
|
}
|
|
return picked, nil
|
|
}
|