wizard

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2026 License: MIT Imports: 8 Imported by: 0

README

cli-wizard-core

CI Release Go Version License

Reusable core primitives for interactive CLI wizards in Go.

Behavioral Contract

This library defines shared wizard behavior contracts used by consumer repos.

What it provides

  • Session: draft lifecycle orchestration (load/start/stop/finalize)
  • RunSteps: deterministic step runner with start/done callbacks
  • Manage: generic create/edit/delete/default action flow for list-based resources
  • FormatMenuLabel: aligned two-column menu labels ([tag] + text)
  • FormatActionLabel / ActionVerb: aligned action-menu labels (Create/Edit/...) + robust action dispatch
  • Colorize: ANSI color wrapper for labels/messages
  • BackLabel / BackMenuLabel / IsBackChoice: consistent Back UX primitives
  • ExitLabel / ExitMenuLabel / IsExitChoice: consistent Exit UX primitives
  • SelectHint: standard selector hint ([Use arrows to move, type to filter, Esc=Back, Ctrl+C=Exit])
  • NewUserError / WithHint: attach actionable hints to user-facing errors
  • FormatCLIError: consistent colored error+hint output for CLIs
  • ReconcileWithTemplate: generic template sync for config objects (added/removed/missing-required report)

The package is intentionally transport-agnostic: no direct dependency on survey/readline/TTY, no provider-specific logic (VMware, Talos, etc.).

Install

go get github.com/Bibi40k/cli-wizard-core

Usage

import wizard "github.com/Bibi40k/cli-wizard-core"

session := wizard.NewSession(
    targetPath,
    draftPath,
    &state,
    isEmpty,
    loadDraftFn,
    startDraftFn,
    finalizeFn,
)

_ = wizard.RunSteps([]wizard.Step{
    {Name: "Step 1", Run: step1},
    {Name: "Step 2", Run: step2},
}, onStart, onDone)

template := map[string]any{
    "vm": map[string]any{
        "name":       "",
        "profile":    "talos",
        "ip_address": "",
    },
}
current := map[string]any{
    "vm": map[string]any{
        "name":     "cp-01",
        "username": "",
    },
}

out, report, err := wizard.ReconcileWithTemplate(current, template, wizard.ReconcileOptions{
    DropUnknown:   true,
    RequiredPaths: []string{"vm.name", "vm.ip_address"},
})
_ = out
_ = report
_ = err

Documentation

Index

Constants

View Source
const (
	ANSIReset  = "\033[0m"
	ANSIRed    = "\033[31m"
	ANSIYellow = "\033[33m"
	ANSICyan   = "\033[36m"
)

Variables

View Source
var ErrInterrupted = errors.New("wizard interrupted")

ErrInterrupted is the shared sentinel used by wizard consumers to propagate Ctrl+C / prompt interruption consistently.

Functions

func ActionVerb added in v0.2.0

func ActionVerb(text string) string

ActionVerb returns the first word from an action label (after ANSI normalization).

func BackLabel added in v0.2.0

func BackLabel() string

BackLabel returns a consistently colored "Back" label.

func BackMenuLabel added in v0.2.0

func BackMenuLabel(width int) string

BackMenuLabel renders a colored Back label aligned like menu entries.

func Colorize added in v0.1.3

func Colorize(text, color string) string

Colorize wraps a string with an ANSI color code and resets formatting. Pass empty color to keep the text unchanged.

func ErrorHint added in v0.1.4

func ErrorHint(err error) string

ErrorHint extracts a hint from an error if available.

func ExitLabel added in v0.2.0

func ExitLabel() string

ExitLabel returns a normalized "Exit" label.

func ExitMenuLabel added in v0.2.0

func ExitMenuLabel(width int) string

ExitMenuLabel renders an Exit label aligned like menu entries.

func FormatActionLabel added in v0.2.0

func FormatActionLabel(text string, verbWidth int) string

FormatActionLabel aligns action menus as two columns: verb + description. "Back"/"Exit" remain plain.

func FormatCLIError added in v0.1.4

func FormatCLIError(err error) string

FormatCLIError renders a colored CLI error and optional hint.

func FormatMenuLabel added in v0.1.3

func FormatMenuLabel(tag, text string, width int) string

FormatMenuLabel renders a two-column menu label: [tag] + aligned text. width controls the fixed width for the [tag] column; values <= 0 default to 12.

func IsBackChoice added in v0.2.0

func IsBackChoice(value string) bool

IsBackChoice checks whether a selected value maps to Back.

func IsCancelChoice added in v0.2.0

func IsCancelChoice(value string) bool

IsCancelChoice checks whether a selected value maps to Cancel.

func IsExitChoice added in v0.2.0

func IsExitChoice(value string) bool

IsExitChoice checks whether a selected value maps to Exit.

func IsInterrupted added in v0.2.0

func IsInterrupted(err error) bool

IsInterrupted reports whether err is or wraps ErrInterrupted.

func NewUserError added in v0.1.4

func NewUserError(message, hint string) error

NewUserError creates a user-facing error message with an optional hint.

func NormalizeChoice added in v0.2.0

func NormalizeChoice(value string) string

NormalizeChoice strips ANSI colors and trims whitespace for robust comparisons.

func RunSteps

func RunSteps(steps []Step, onStepStart func(index, total int, name string), onStepDone func(index, total int)) error

RunSteps executes steps in order and reports transitions through callbacks.

func SelectHint added in v0.2.0

func SelectHint() string

SelectHint returns the standard selector help hint used across wizard UIs.

func WithHint added in v0.1.4

func WithHint(err error, hint string) error

WithHint wraps an existing error with a user-facing hint.

Types

type ManageAction added in v0.1.3

type ManageAction string
const (
	ManageCreate     ManageAction = "create"
	ManageEdit       ManageAction = "edit"
	ManageDelete     ManageAction = "delete"
	ManageSetDefault ManageAction = "set_default"
	ManageCancel     ManageAction = "cancel"
)

type ManageOptions added in v0.1.3

type ManageOptions[T any] struct {
	Items         []T
	ItemLabel     func(item T) string
	Select        func(options []string, defaultOption, message string) string
	MainMessage   string
	ItemMessage   string
	DefaultLabel  string
	CreateLabel   string
	EditLabel     string
	DeleteLabel   string
	SetDefaultLbl string
	CancelLabel   string
}

type ManageSelection added in v0.1.3

type ManageSelection[T any] struct {
	Action ManageAction
	Item   *T
}

func Manage added in v0.1.3

func Manage[T any](opts ManageOptions[T]) (ManageSelection[T], error)

type ReconcileOptions added in v0.1.5

type ReconcileOptions struct {
	// DropUnknown removes keys not present in template.
	DropUnknown bool
	// RequiredPaths are dot-notation keys that must exist after reconcile.
	RequiredPaths []string
}

ReconcileOptions controls template sync behavior.

type ReconcileReport added in v0.1.5

type ReconcileReport struct {
	Added           []string
	Removed         []string
	MissingRequired []string
}

ReconcileReport summarizes changes and validation findings.

func ReconcileWithTemplate added in v0.1.5

func ReconcileWithTemplate(current, template map[string]any, opts ReconcileOptions) (map[string]any, ReconcileReport, error)

ReconcileWithTemplate syncs a config object against a template object. It keeps existing values for keys defined in template, fills missing keys from template defaults, and optionally removes unknown keys.

type Selector added in v0.2.0

type Selector struct {
	// MaxVisible limits items visible at once. 0 means show all.
	MaxVisible int
	// contains filtered or unexported fields
}

Selector provides an interactive arrow-key selection widget for terminal UIs.

func NewSelector added in v0.2.0

func NewSelector() *Selector

NewSelector creates a Selector with sensible defaults (MaxVisible = 10).

func (*Selector) Select added in v0.2.0

func (s *Selector) Select(items []string, defaultItem, message string) string

Select displays an interactive menu with arrow-key navigation, type-to-filter, and optional scrolling. Returns the selected item. On ESC or Ctrl+C, returns the preferred cancel option (Back > Exit > Cancel) if present, or empty string. Call WasInterrupted() to check for Ctrl+C.

Signature is compatible with ManageOptions.Select.

func (*Selector) WasInterrupted added in v0.2.0

func (s *Selector) WasInterrupted() bool

WasInterrupted returns true if the last Select ended with Ctrl+C.

type Session

type Session struct {
	TargetPath string
	DraftPath  string
	State      any
	IsEmpty    func() bool
	// contains filtered or unexported fields
}

Session manages a wizard draft lifecycle with pluggable IO handlers.

func NewSession

func NewSession(
	targetPath, draftPath string,
	state any,
	isEmpty func() bool,
	loadDraftFn func(draftPath string, state any) (bool, error),
	startFn func(targetPath, draftPath string, state any, isEmpty func() bool) func(),
	finalizeFn func(targetPath string) error,
) *Session

NewSession creates a reusable wizard session orchestrator.

func (*Session) Finalize

func (s *Session) Finalize() error

Finalize removes stale drafts for target.

func (*Session) LoadDraft

func (s *Session) LoadDraft() (bool, error)

LoadDraft loads draft state when available.

func (*Session) Start

func (s *Session) Start()

Start installs draft handling for this session.

func (*Session) Stop

func (s *Session) Stop()

Stop restores process state after Start.

type Step

type Step struct {
	Name string
	Run  func() error
}

Step defines one wizard action.

type UserError added in v0.1.4

type UserError struct {
	Message string
	HintMsg string
}

UserError is a user-facing error with an optional actionable hint.

func (*UserError) Error added in v0.1.4

func (e *UserError) Error() string

func (*UserError) Hint added in v0.1.4

func (e *UserError) Hint() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL