Skip to content

refactor: migrate interactive prompts from survey to huh - #955

Closed
nf-matt wants to merge 18 commits into
fwdcloudsec:mainfrom
nf-matt:huh-ui-migration
Closed

refactor: migrate interactive prompts from survey to huh#955
nf-matt wants to merge 18 commits into
fwdcloudsec:mainfrom
nf-matt:huh-ui-migration

Conversation

@nf-matt

@nf-matt nf-matt commented Jul 14, 2026

Copy link
Copy Markdown

Implements the migration proposed in #945.

AlecAivazis/survey is archived (last release June 2023, 74 open issues) and its API blocks features like ESC-to-cancel. This branch replaces it with huh (actively maintained, generically-typed Select, first-class theming, built-in ESC-cancel) behind the existing pkg/testable shim, and drops the survey dependency.

Why one branch instead of the per-package PRs from the RFC: I didn't hear back on #945, so I've consolidated the work here. The commits still follow the RFC's incremental plan — each is behavior-equivalent, self-contained, and independently revertible, so this can be reviewed commit-by-commit.

Commit progression (18 commits):

  1. Close the testable-shim leak (callers bypassing the shim).
  2. Add huh v2; introduce a Prompter interface with a huh-backed Confirm; migrate cfaws/env.go.
  3. Add Select / Input / Password methods and migrate their callers, package by package.
  4. Add validator-accepting Input/Select and migrate validator-using callers.
  5. Add SelectWithFilter (bubbles/list) and migrate the assume profile picker — removing the SelectQuestionTemplate monkey-patch and profileNameMap workaround called out in the RFC.
  6. Add ConfirmWithHelp/InputWithHelp and migrate Help-using callers.
  7. Drop the survey dependency.
  8. Theme the huh forms and the filter picker.

Verification: go build ./... clean; go test ./... passes (10 packages ok, no failures).

nf-matt added 18 commits May 22, 2026 14:52
Adds testable.Ask for multi-question forms and replaces ten direct
survey.AskOne / survey.Ask callers that bypassed the shim.
Adds the Prompter interface and a testable.Confirm function as the
entry point for migrated callers. The huh implementation writes to
os.Stderr (granted's stdout is shell-evaluated) and binds ESC alongside
Ctrl+C to the form's Quit action, since huh v2 binds Ctrl+C only.
Uses generic huh.Select[string] and inherits the ESC-cancel keybinding
from the form keymap.
Replaces twelve survey.Select sites that used only Message and Options.
Each migration drops the survey.WithStdio boilerplate since the
Prompter handles stderr internally. One adjacent Confirm in
browser/detect.go is migrated as well because it shared the
now-removed withStdio variable.
Replaces twelve survey.Input sites. The settings/set.go Int case keeps
the existing string-through-interface{} path (no behaviour change).
Migrates the secret-access-key Password prompt and six Confirm prompts
(alias install, default-browser-firefox, uninstall config, credentials
removal, settings/set Bool case, registry setup). Drops the
var prompt survey.Prompt declaration in settings/set.go since none of
the cases reference it anymore.
Adds InputWithValidator and SelectWithValidator to the Prompter
interface, plus a Required helper for the common non-empty case.
- credentials.go AddCredentialsCommand: survey.MinLength(1) becomes
  testable.Required (equivalent semantics).
- credentials.go ImportCredentialsCommand: custom validator now
  receives the selected string directly instead of a core.OptionAnswer.
- config_yaml.go required-keys prompt: the survey.Ask multi-question
  form only ever held a single Question (var questions was declared
  inside the loop). Collapses to InputWithValidator + SaveKey,
  dropping the ansmap intermediary. The now-unused SaveKeys function
  is removed and SaveKey's stale doc comment is updated.
huh.Select's built-in filter is literal substring only with no public
matcher hook; bubbles/list exposes a Filter field that takes a func,
so the implementation drops one layer down to build the picker
directly.

The non-modal key handler mirrors survey's UX: typing appends to the
filter, arrows navigate, Enter selects, Esc clears the filter or
quits. The default bubbles/list keymap is replaced with bindings that
match what's actually wired up.
QueryProfiles drops the survey.Select call and the associated
SelectQuestionTemplate global-mutation hack used to render the
Profile/Description column header. The header is now pre-printed via
fmt.Fprintln before launching the picker, which works because
bubbles/list runs inline.

filterMultiToken is restored with a simpler (term, opt) signature.
Help-text variants backed by huh's Description() on the underlying
field. Each shares a single private helper with its plain counterpart.
- browser/detect.go SSOBrowser: Confirm with Help -> ConfirmWithHelp
- settings/requesturl/set.go: Input with Help -> InputWithHelp
Removes testable.AskOne and testable.Ask along with the survey and
survey/core imports from pkg/testable. go mod tidy drops
AlecAivazis/survey/v2 from go.mod entirely. The library was archived
by its author in 2024.
Adds grantedTheme (based on huh.ThemeCharm) and styling helpers for
the bubbles/list-based filter picker. Replaces the fuchsia/indigo
accents with ANSI cyan and green, removes the outer left-border around
focused fields, and switches every colour to ANSI 16 indices so the
prompts pick up the user's terminal palette instead of Charm's hex
codes.

The filter picker's focused row indicator becomes a > cursor in cyan
with green option text, matching huh.Select's SelectSelector +
SelectedOption convention. Status bar stays visible to show the active
filter text.
@nf-matt
nf-matt force-pushed the huh-ui-migration branch from 60a23fc to 3d91fd6 Compare July 14, 2026 15:01
@nf-matt nf-matt closed this Jul 14, 2026
@nf-matt
nf-matt deleted the huh-ui-migration branch July 14, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant