cli

package
v0.0.0-...-308d991 Latest Latest
Warning

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

Go to latest
Published: Jan 25, 2026 License: GPL-3.0 Imports: 16 Imported by: 0

README

CLI Package

The cli package provides a declarative framework for building CLI applications within the Vanilla OS SDK. It handles command hierarchy, flag parsing, argument validation, and help text generation.

Usage

CLI applications are defined by mapping structs to commands, using struct fields and their associated tags.

Command Definition

A struct representing a command must include cli.Base (an alias for go-cli-builder's Base struct).

  • cmd: Defines the name of a subcommand
  • help: Defines the help description for the command or flag
type RootCmd struct {
    cli.Base
    Config ConfigCmd `cmd:"config" help:"pr:vso.cmd.config"`
}
Flags

Flags are defined as struct fields with the flag tag.

  • short: Defines a single-letter alias
  • long: Defines the full name of the flag
  • name: Defines the display name in help text (can be a translation key)
type RootCmd struct {
    cli.Base
    Version bool `flag:"short:v, long:version" help:"pr:vso.msg.version"`
}
Arguments

Positional arguments are defined as struct fields with the arg tag.

  • optional: Marks an argument as not required
  • name: Defines the argument placeholder in help text
type ConfigSetCmd struct {
    cli.Base
    Key   string `arg:"" name:"key" help:"pr:vso.arg.key"`
    Value string `arg:"" name:"value" help:"pr:vso.arg.value"`
}

i18n Integration

The package integrates with the SDK's i18n component through the pr: (that stands for "provider")prefix in tags.

Strings starting with pr: are treated as translation keys, when an application is initialized via app.App, the SDK automatically registers a translator that resolves these keys using the application's locale files. Command titles, flag descriptions, and argument names are all translatable.

Dynamic Commands

While the primary structure is static, commands can be added or modified at runtime using the AddCommand method on a Command instance.

cmd, _ := cli.NewCommandFromStruct(&RootCmd{})
cmd.AddCommand("dynamic-command", myDynamicNode)

UI Components

The package provides several pre-styled UI components built with Bubble Tea for common CLI interactions:

Component Purpose
PromptText Collects string input from the user.
SelectOption Displays a list for selection. Supports %d formatting for option counts.
ConfirmAction Handles Yes/No confirmations.
ProgressBar Visualizes the progress of a task.
Spinner Indicates background activity for indeterminate tasks.
Table Renders structured data in tabular format.

Execution

To initialize and run a CLI application:

func main() {
    myApp := app.New("my-app", "1.0.0")
    // ... setup app ...
    
    cmd, err := cli.NewCommandFromStruct(&RootCmd{})
    if err != nil {
        panic(err)
    }
    
    if err := cmd.Execute(); err != nil {
        fmt.Println(err)
    }
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateManPage

func GenerateManPage(root any, tr help.Translator) (string, error)

GenerateManPage generates a man page for the declarative struct

Example:

type RootCmd struct {
	cli.Base
	Poll PollCmd `cmd:"poll" help:"Ask the user preferred hero"`
	Man  ManCmd  `cmd:"man" help:"Generate man page"`
}

man, err := cli.GenerateManPage(&RootCmd{}, nil)
if err != nil {
	return "", err
}

GenerateManPage automatically uses a zero-value instance of the root struct to exclude any dynamic commands.

Types

type Base

type Base = builder.Base

Base is an alias for builder.Base to be used by consumers

type Command

type Command struct {
	Use   string
	Short string
	Long  string
	// contains filtered or unexported fields
}

Command represents a CLI command.

func NewCommandFromStruct

func NewCommandFromStruct(s any) (*Command, error)

NewCommandFromStruct returns a new Command created from a struct.

Example:

type RootCmd struct {
	cli.Base
	Poll PollCmd `cmd:"poll" help:"Ask the user preferred hero"`
	Man  ManCmd  `cmd:"man" help:"Generate man page"`
}

cmd, err := cli.NewCommandFromStruct(&RootCmd{})
if err != nil {
	return nil, err
}

err := cmd.Execute()

func (*Command) AddCommand

func (c *Command) AddCommand(name string, cmd *parser.CommandNode)

AddCommand adds a dynamic command to the application.

func (*Command) ConfirmAction

func (c *Command) ConfirmAction(prompt, yesText, noText string, defaultChoice bool) (bool, error)

ConfirmAction prompts the user to confirm an action, it supports customizing the prompt and the text for the "yes" and "no" options. If the user does not provide an answer, the default choice is used.

Example:

confirm, err := myApp.CLI.ConfirmAction(
	"Do you like Batman?",
	"Yes", "No",
	true,
)
if err != nil {
	fmt.Println(err)
	return err
}
if confirm {
	fmt.Println("Everybody likes Batman!")
} else {
	fmt.Println("You don't like Batman...")
}

func (*Command) Execute

func (c *Command) Execute() error

Execute runs the command

func (*Command) GetRoot

func (c *Command) GetRoot() any

GetRoot returns the underlying root struct of the command.

func (*Command) Name

func (c *Command) Name() string

Name returns the name of the command

func (*Command) PromptText

func (c *Command) PromptText(prompt, placeholder string) (string, error)

PromptText prompts the user to input a text, it supports customizing the prompt and the placeholder.

Example:

response, err := myApp.CLI.PromptText(
	"What is your name?",
	"Bruce Wayne",
)
if err != nil {
	fmt.Println(err)
	return err
}
fmt.Printf("Hello %s!\n", response)

func (*Command) Reload

func (c *Command) Reload() error

Reload re-parses the root struct to pick up dynamic changes.

func (*Command) SelectOption

func (c *Command) SelectOption(prompt string, options []string) (string, error)

SelectOption prompts the user to select an option from a list of options.

Example:

selected, err := myApp.CLI.SelectOption(
	"What is your preferred hero?",
	[]string{"Batman", "Ironman", "Spiderman", "Robin", "None"},
)
if err != nil {
	fmt.Println(err)
	return err
}
fmt.Printf("You selected %s!\n", selected)

func (*Command) SetName

func (c *Command) SetName(name string)

SetName sets the name of the root command.

func (*Command) SetTranslator

func (c *Command) SetTranslator(tr help.Translator)

SetTranslator sets the translator for the application.

func (Command) StartProgressBar

func (c Command) StartProgressBar(message string, total int) *ProgressBarModel

StartProgressBar starts a progress bar with a message and a total. The progress bar is stopped automatically when it reaches the total or manually by calling the Stop method on the returned model.

Example:

progressBar := myApp.CLI.StartProgressBar("Loading the batmobile...", 100)
for i := 0; i < 100; i++ {
	progressBar.Increment(1)
	time.Sleep(50 * time.Millisecond)
}

func (Command) StartSpinner

func (c Command) StartSpinner(message string) *SpinnerModel

StartSpinner starts a spinner with a message. The spinner can be stopped by calling the Stop method on the returned model.

Example:

spinner := myApp.CLI.StartSpinner("Loading the batmobile...")
time.Sleep(3 * time.Second)
spinner.Stop()

func (*Command) Table

func (c *Command) Table(headers []string, data [][]string) error

Table renders a styled table with the given headers and data using lipgloss.

Example:

err := myApp.CLI.Table(
	[]string{"Name", "Age"},
	[][]string{
		{"Batman", "35"},
		{"Robin", "25"},
	},
)

type ManCmd

type ManCmd struct {
	Base
	// contains filtered or unexported fields
}

ManCmd is the command to generate the man page

func (*ManCmd) Run

func (c *ManCmd) Run() error

Run runs the man command

Example:

manCmd := &cli.ManCmd{root: s}
err := parser.Run(manCmd)

type ProgressBarModel

type ProgressBarModel struct {
	// contains filtered or unexported fields
}

func (*ProgressBarModel) Increment

func (m *ProgressBarModel) Increment(inc int)

func (*ProgressBarModel) Stop

func (m *ProgressBarModel) Stop()

func (*ProgressBarModel) UpdateMessage

func (m *ProgressBarModel) UpdateMessage(msg string)

UpdateMessage updates the title logic.

type SpinnerModel

type SpinnerModel struct {
	// contains filtered or unexported fields
}

func (*SpinnerModel) Stop

func (m *SpinnerModel) Stop()

func (*SpinnerModel) UpdateMessage

func (m *SpinnerModel) UpdateMessage(message string)

UpdateMessage updates the spinner message dynamically.

Example:

spinner.UpdateMessage("Loading the batcave...")

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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