diff --git a/cmd/skill.go b/cmd/skill.go index 811c07d..d1641fd 100644 --- a/cmd/skill.go +++ b/cmd/skill.go @@ -49,7 +49,8 @@ func runSkillWizard(cmd *cobra.Command) error { choices := make([]ui.Choice, 0, len(targets)+1) for _, t := range targets { choices = append(choices, ui.Choice{ - Label: fmt.Sprintf("%s (%s)", t.Name, filepath.Join(t.Dir, skill.FileName)), + Label: t.Name, + Hint: filepath.Join(t.Dir, skill.FileName), }) } choices = append(choices, ui.Choice{Label: "Other (custom path)"}) diff --git a/internal/ui/select.go b/internal/ui/select.go index fab519c..e268c3c 100644 --- a/internal/ui/select.go +++ b/internal/ui/select.go @@ -3,6 +3,7 @@ package ui import ( "errors" "io" + "strings" "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" @@ -20,11 +21,23 @@ func Select(in io.Reader, out io.Writer, prompt string, choices []Choice) (idx i return 0, false, errors.New("ui.Select: no choices") } dim := lipgloss.NewStyle().Foreground(dimColor) + + // Pad labels to a common width so the dimmed hints line up in a column. + maxLabel := 0 + for _, c := range choices { + if c.Hint != "" { + if w := lipgloss.Width(c.Label); w > maxLabel { + maxLabel = w + } + } + } + opts := make([]huh.Option[int], len(choices)) for i, c := range choices { label := c.Label if c.Hint != "" { - label = label + " " + dim.Render(c.Hint) + pad := maxLabel - lipgloss.Width(c.Label) + label = label + strings.Repeat(" ", pad+2) + dim.Render(c.Hint) } opts[i] = huh.NewOption(label, i) } @@ -33,11 +46,16 @@ func Select(in io.Reader, out io.Writer, prompt string, choices []Choice) (idx i field := huh.NewSelect[int](). Title(prompt). Options(opts...). + Filtering(false). Value(&selected) + // Disable the "/" filter binding so the option list is never searchable. + km := EscKeyMap() + km.Select.Filter.SetEnabled(false) + form := huh.NewForm(huh.NewGroup(field)). WithTheme(EmailableTheme()). - WithKeyMap(EscKeyMap()). + WithKeyMap(km). WithInput(in). WithOutput(out)