Documentation
¶
Overview ¶
Package clix provides a declarative framework for building command line interfaces with nested commands, global flags, configuration hydration and interactive prompting. The package exposes high level types such as App and Command which can be composed to describe the command tree and execution behaviour of a CLI.
Getting Started ¶
Define an App, create commands with handlers, and call Run:
app := clix.NewApp("myapp")
app.Root = clix.NewGroup("myapp", "My application",
clix.NewCommand("greet", "Greet someone", func(ctx *clix.Context) error {
name, _ := ctx.Arg(0)
fmt.Printf("Hello, %s!\n", name)
return nil
}),
)
app.Run(context.Background(), nil)
Core Types ¶
The primary stable types for v1 are:
- App – owns the root command, flags, and extensions
- Command – represents a node in the CLI tree (group or command)
- Context – wraps context.Context with CLI metadata (App, Command, Args)
- Extension – plugs cross-cutting behavior into App
Context Usage ¶
clix uses a layered context design:
App.Run(ctx context.Context, args []string) accepts a standard context.Context that controls process-level cancellation and deadlines.
For each command execution, clix builds a *clix.Context which embeds the original context.Context and adds CLI-specific data (App, Command, Args, hydrated flags/config).
Within command handlers, pass *clix.Context to any functions that need CLI metadata. Because *clix.Context embeds context.Context, you can pass it anywhere a context.Context is required (e.g., to Prompter.Prompt).
Internal clix functions that need CLI awareness (App, Command, Args) should accept *clix.Context. Functions that only need cancellation/deadlines should accept context.Context.
Example:
cmd.Run = func(ctx *clix.Context) error {
// ctx is both a context.Context (for cancellation) and has CLI data
value, err := ctx.App.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Enter value",
})
// Use ctx.Done(), ctx.Err() for cancellation
// Use ctx.App, ctx.Command, ctx.Args for CLI data
return nil
}
Compatibility ¶
clix v1 follows semantic versioning. The github.com/SCKelemen/clix module path will not have breaking changes within major version 1. Extensions under github.com/SCKelemen/clix/ext/... may evolve more quickly but will also respect semver for their exported APIs.
clix requires Go 1.24 or later.
Example (DeclarativeStyle) ¶
Example_declarativeStyle demonstrates a purely declarative CLI app using only struct-based APIs throughout.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
var (
project string
verbose bool
port int
)
// Create app using struct fields
app := clix.NewApp("myapp")
app.Description = "A declarative-style CLI application"
app.Version = "1.0.0"
// Global flags using struct-based API
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "project",
Short: "p",
Usage: "Project to operate on",
EnvVar: "MYAPP_PROJECT",
},
Default: "default-project",
Value: &project,
})
app.Flags().BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "verbose",
Short: "v",
Usage: "Enable verbose output",
},
Value: &verbose,
})
// Commands using struct fields
createCmd := clix.NewCommand("create")
createCmd.Short = "Create a new resource"
createCmd.Run = func(ctx *clix.Context) error {
name, _ := ctx.String("project")
fmt.Fprintf(ctx.App.Out, "Creating resource in project: %s\n", name)
return nil
}
// Command flags using struct-based API
createCmd.Flags.IntVar(clix.IntVarOptions{
FlagOptions: clix.FlagOptions{
Name: "port",
Usage: "Server port",
},
Default: "8080",
Value: &port,
})
// Arguments using struct-based API
createCmd.Arguments = []*clix.Argument{
{
Name: "name",
Prompt: "Enter resource name",
Required: true,
},
{
Name: "email",
Prompt: "Enter email address",
Default: "[email protected]",
},
}
// Config schema using struct-based API
app.Config.RegisterSchema(clix.ConfigSchema{
Key: "project.retries",
Type: clix.ConfigInteger,
})
// Build command tree
listCmd := clix.NewCommand("list")
listCmd.Short = "List resources"
listCmd.Run = func(ctx *clix.Context) error {
fmt.Fprintln(ctx.App.Out, "Listing resources...")
return nil
}
root := clix.NewGroup("myapp", "My application", createCmd, listCmd)
app.Root = root
// Run the app
_ = app
}
Example (FluentStyle) ¶
Example_fluentStyle demonstrates a fully fluent-style CLI app using only builder-style (method chaining) APIs throughout.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
var (
project string
verbose bool
port int
)
// Create app using builder-style
app := clix.NewApp("myapp").
SetDescription("A fluent-style CLI application").
SetVersion("1.0.0")
// Global flags using builder-style
projectFlagOpts := &clix.StringVarOptions{}
projectFlagOpts.SetName("project").
SetShort("p").
SetUsage("Project to operate on").
SetEnvVar("MYAPP_PROJECT").
SetDefault("default-project").
SetValue(&project)
app.Flags().StringVar(*projectFlagOpts)
verboseFlagOpts := &clix.BoolVarOptions{}
verboseFlagOpts.SetName("verbose").
SetShort("v").
SetUsage("Enable verbose output").
SetValue(&verbose)
app.Flags().BoolVar(*verboseFlagOpts)
// Commands using builder-style
createCmd := clix.NewCommand("create").
SetShort("Create a new resource").
SetRun(func(ctx *clix.Context) error {
name, _ := ctx.String("project")
fmt.Fprintf(ctx.App.Out, "Creating resource in project: %s\n", name)
return nil
})
// Command flags using builder-style
portFlagOpts := &clix.IntVarOptions{}
portFlagOpts.SetName("port").
SetUsage("Server port").
SetDefault("8080").
SetValue(&port)
createCmd.Flags.IntVar(*portFlagOpts)
// Arguments using builder-style
createCmd.Arguments = []*clix.Argument{
clix.NewArgument().
SetName("name").
SetPrompt("Enter resource name").
SetRequired(),
clix.NewArgument().
SetName("email").
SetPrompt("Enter email address").
SetDefault("[email protected]"),
}
// Config schema using builder-style
schema := &clix.ConfigSchema{}
schema.SetKey("project.retries").
SetType(clix.ConfigInteger)
app.Config.RegisterSchema(*schema)
// Build command tree using builder-style
listCmd := clix.NewCommand("list").
SetShort("List resources").
SetRun(func(ctx *clix.Context) error {
fmt.Fprintln(ctx.App.Out, "Listing resources...")
return nil
})
root := clix.NewGroup("myapp", "My application", createCmd, listCmd)
app.SetRoot(root)
// Run the app
_ = app
}
Example (FunctionalStyle) ¶
Example_functionalStyle demonstrates a purely functional-style CLI app using only functional options APIs throughout.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
var (
project string
verbose bool
port int
)
// Create app with functional options
app := clix.NewApp("myapp")
app.Description = "A fully functional-style CLI application"
// Global flags using functional options
app.Flags().StringVar(
clix.WithFlagName("project"),
clix.WithFlagShort("p"),
clix.WithFlagUsage("Project to operate on"),
clix.WithFlagEnvVar("MYAPP_PROJECT"),
clix.WithStringValue(&project),
clix.WithStringDefault("default-project"),
)
app.Flags().BoolVar(
clix.WithFlagName("verbose"),
clix.WithFlagShort("v"),
clix.WithFlagUsage("Enable verbose output"),
clix.WithBoolValue(&verbose),
)
// Commands using functional options
createCmd := clix.NewCommand("create",
clix.WithCommandShort("Create a new resource"),
clix.WithCommandRun(func(ctx *clix.Context) error {
name, _ := ctx.String("project")
fmt.Fprintf(ctx.App.Out, "Creating resource in project: %s\n", name)
return nil
}),
)
// Command flags using functional options
createCmd.Flags.IntVar(
clix.WithFlagName("port"),
clix.WithFlagUsage("Server port"),
clix.WithIntegerValue(&port),
clix.WithIntegerDefault("8080"),
)
// Arguments using functional options
createCmd.Arguments = []*clix.Argument{
clix.NewArgument(
clix.WithArgName("name"),
clix.WithArgPrompt("Enter resource name"),
clix.WithArgRequired(),
),
clix.NewArgument(
clix.WithArgName("email"),
clix.WithArgPrompt("Enter email address"),
clix.WithArgDefault("[email protected]"),
),
}
// Config schema using functional options
app.Config.RegisterSchema(
clix.WithConfigKey("project.retries"),
clix.WithConfigType(clix.ConfigInteger),
)
// Build command tree
root := clix.NewGroup("myapp", "My application",
createCmd,
clix.NewCommand("list",
clix.WithCommandShort("List resources"),
clix.WithCommandRun(func(ctx *clix.Context) error {
fmt.Fprintln(ctx.App.Out, "Listing resources...")
return nil
}),
),
)
app.Root = root
// Run the app
_ = app
}
Index ¶
- Variables
- func FormatData(w io.Writer, data interface{}, format string) error
- type App
- func (a *App) AddDefaultCommands()
- func (a *App) AddExtension(ext Extension)
- func (a *App) ApplyExtensions() error
- func (a *App) ConfigDir() (string, error)
- func (a *App) ConfigFile() (string, error)
- func (a *App) Flags() *FlagSet
- func (a *App) FormatOutput(data interface{}) error
- func (a *App) OutputFormat() string
- func (a *App) Run(ctx context.Context, args []string) error
- func (a *App) SaveConfig() error
- func (a *App) SetDefaultTheme(theme PromptTheme) *App
- func (a *App) SetDescription(description string) *App
- func (a *App) SetEnvPrefix(prefix string) *App
- func (a *App) SetErr(err io.Writer) *App
- func (a *App) SetIn(in io.Reader) *App
- func (a *App) SetOut(out io.Writer) *App
- func (a *App) SetPrompter(prompter Prompter) *App
- func (a *App) SetRoot(root *Command) *App
- func (a *App) SetStyles(styles Styles) *App
- func (a *App) SetVersion(version string) *App
- type AppOption
- func WithAppDefaultTheme(theme PromptTheme) AppOption
- func WithAppDescription(description string) AppOption
- func WithAppEnvPrefix(prefix string) AppOption
- func WithAppErr(err io.Writer) AppOption
- func WithAppIn(in io.Reader) AppOption
- func WithAppOut(out io.Writer) AppOption
- func WithAppPrompter(prompter Prompter) AppOption
- func WithAppRoot(root *Command) AppOption
- func WithAppStyles(styles Styles) AppOption
- func WithAppVersion(version string) AppOption
- type Argument
- func (a *Argument) ApplyArgument(arg *Argument)
- func (a *Argument) PromptLabel() string
- func (a *Argument) SetDefault(defaultValue string) *Argument
- func (a *Argument) SetName(name string) *Argument
- func (a *Argument) SetPrompt(prompt string) *Argument
- func (a *Argument) SetRequired() *Argument
- func (a *Argument) SetValidate(validate func(string) error) *Argument
- type ArgumentOption
- type BoolValue
- type BoolVarOptions
- func (o BoolVarOptions) ApplyFlag(fo *FlagOptions)
- func (o *BoolVarOptions) SetEnvVar(envVar string) *BoolVarOptions
- func (o *BoolVarOptions) SetName(name string) *BoolVarOptions
- func (o *BoolVarOptions) SetShort(short string) *BoolVarOptions
- func (o *BoolVarOptions) SetUsage(usage string) *BoolVarOptions
- func (o *BoolVarOptions) SetValue(value *bool) *BoolVarOptions
- type Command
- func (c *Command) AddCommand(cmd *Command)
- func (c *Command) Commands() []*Command
- func (c *Command) Groups() []*Command
- func (c *Command) IsGroup() bool
- func (c *Command) IsLeaf() bool
- func (c *Command) Path() string
- func (c *Command) RequiredArgs() int
- func (c *Command) ResolvePath(path []string) *Command
- func (c *Command) SetAliases(aliases ...string) *Command
- func (c *Command) SetArguments(args ...*Argument) *Command
- func (c *Command) SetExample(example string) *Command
- func (c *Command) SetHidden(hidden bool) *Command
- func (c *Command) SetLong(long string) *Command
- func (c *Command) SetPostRun(postRun Hook) *Command
- func (c *Command) SetPreRun(preRun Hook) *Command
- func (c *Command) SetRun(run Handler) *Command
- func (c *Command) SetShort(short string) *Command
- func (c *Command) SetUsage(usage string) *Command
- func (c *Command) VisibleChildren() []*Command
- type CommandOption
- func WithCommandAliases(aliases ...string) CommandOption
- func WithCommandArguments(args ...*Argument) CommandOption
- func WithCommandExample(example string) CommandOption
- func WithCommandHidden(hidden bool) CommandOption
- func WithCommandLong(long string) CommandOption
- func WithCommandPostRun(postRun Hook) CommandOption
- func WithCommandPreRun(preRun Hook) CommandOption
- func WithCommandRun(run Handler) CommandOption
- func WithCommandShort(short string) CommandOption
- func WithCommandUsage(usage string) CommandOption
- type ConfigManager
- func (m *ConfigManager) Bool(key string) (bool, bool)
- func (m *ConfigManager) Delete(key string) bool
- func (m *ConfigManager) Float64(key string) (float64, bool)
- func (m *ConfigManager) Get(key string) (string, bool)
- func (m *ConfigManager) Int64(key string) (int64, bool)
- func (m *ConfigManager) Integer(key string) (int, bool)
- func (m *ConfigManager) Load(path string) error
- func (m *ConfigManager) NormalizeValue(key, value string) (string, error)
- func (m *ConfigManager) RegisterSchema(entries ...ConfigSchemaOption)
- func (m *ConfigManager) Reset()
- func (m *ConfigManager) Save(path string) error
- func (m *ConfigManager) Set(key, value string)
- func (m *ConfigManager) String(key string) (string, bool)
- func (m *ConfigManager) Values() map[string]string
- type ConfigSchema
- type ConfigSchemaOption
- type ConfigType
- type Context
- type DurationValue
- type DurationVarOptions
- type Extension
- type Flag
- type FlagOption
- func WithBoolValue(value *bool) FlagOption
- func WithDurationDefault(defaultValue string) FlagOption
- func WithDurationValue(value *time.Duration) FlagOption
- func WithFlagEnvVar(envVar string) FlagOption
- func WithFlagEnvVars(envVars ...string) FlagOption
- func WithFlagName(name string) FlagOption
- func WithFlagShort(short string) FlagOption
- func WithFlagUsage(usage string) FlagOption
- func WithFloat64Default(defaultValue string) FlagOption
- func WithFloat64Value(value *float64) FlagOption
- func WithInt64Default(defaultValue string) FlagOption
- func WithInt64Value(value *int64) FlagOption
- func WithIntegerDefault(defaultValue string) FlagOption
- func WithIntegerValue(value *int) FlagOption
- func WithStringDefault(defaultValue string) FlagOption
- func WithStringValue(value *string) FlagOption
- type FlagOptions
- type FlagSet
- func (fs *FlagSet) Bool(name string) (bool, bool)
- func (fs *FlagSet) BoolVar(opts ...FlagOption)
- func (fs *FlagSet) DurationVar(opts ...FlagOption)
- func (fs *FlagSet) Flags() []*Flag
- func (fs *FlagSet) Float64(name string) (float64, bool)
- func (fs *FlagSet) Float64Var(opts ...FlagOption)
- func (fs *FlagSet) Int64(name string) (int64, bool)
- func (fs *FlagSet) Int64Var(opts ...FlagOption)
- func (fs *FlagSet) IntVar(opts ...FlagOption)
- func (fs *FlagSet) Integer(name string) (int, bool)
- func (fs *FlagSet) Parse(args []string) ([]string, error)
- func (fs *FlagSet) String(name string) (string, bool)
- func (fs *FlagSet) StringVar(opts ...FlagOption)
- type Float64Value
- type Float64VarOptions
- type Handler
- type HelpRenderer
- type Hook
- type Int64Value
- type Int64VarOptions
- type IntValue
- type IntVarOptions
- func (o IntVarOptions) ApplyFlag(fo *FlagOptions)
- func (o *IntVarOptions) SetDefault(defaultValue string) *IntVarOptions
- func (o *IntVarOptions) SetEnvVar(envVar string) *IntVarOptions
- func (o *IntVarOptions) SetName(name string) *IntVarOptions
- func (o *IntVarOptions) SetShort(short string) *IntVarOptions
- func (o *IntVarOptions) SetUsage(usage string) *IntVarOptions
- func (o *IntVarOptions) SetValue(value *int) *IntVarOptions
- type PromptButtonStyles
- type PromptCommand
- type PromptCommandAction
- type PromptCommandContext
- type PromptCommandHandler
- type PromptCommandType
- type PromptConfig
- type PromptKeyBinding
- type PromptKeyMap
- type PromptKeyState
- type PromptOption
- func WithCommandHandler(handler PromptCommandHandler) PromptOption
- func WithConfirm() PromptOption
- func WithDefault(def string) PromptOption
- func WithKeyMap(m PromptKeyMap) PromptOption
- func WithLabel(label string) PromptOption
- func WithNoDefaultPlaceholder(text string) PromptOption
- func WithTheme(theme PromptTheme) PromptOption
- func WithValidate(validate func(string) error) PromptOption
- type PromptRequest
- func (r PromptRequest) Apply(cfg *PromptConfig)
- func (r *PromptRequest) SetCommandHandler(handler PromptCommandHandler) *PromptRequest
- func (r *PromptRequest) SetConfirm(confirm bool) *PromptRequest
- func (r *PromptRequest) SetContinueText(text string) *PromptRequest
- func (r *PromptRequest) SetDefault(defaultValue string) *PromptRequest
- func (r *PromptRequest) SetKeyMap(keyMap PromptKeyMap) *PromptRequest
- func (r *PromptRequest) SetLabel(label string) *PromptRequest
- func (r *PromptRequest) SetMultiSelect(multiSelect bool) *PromptRequest
- func (r *PromptRequest) SetNoDefaultPlaceholder(placeholder string) *PromptRequest
- func (r *PromptRequest) SetOptions(options ...SelectOption) *PromptRequest
- func (r *PromptRequest) SetTheme(theme PromptTheme) *PromptRequest
- func (r *PromptRequest) SetValidate(validate func(string) error) *PromptRequest
- type PromptTheme
- type Prompter
- type SelectOption
- type StringValue
- type StringVarOptions
- func (o StringVarOptions) ApplyFlag(fo *FlagOptions)
- func (o *StringVarOptions) SetDefault(defaultValue string) *StringVarOptions
- func (o *StringVarOptions) SetEnvVar(envVar string) *StringVarOptions
- func (o *StringVarOptions) SetName(name string) *StringVarOptions
- func (o *StringVarOptions) SetShort(short string) *StringVarOptions
- func (o *StringVarOptions) SetUsage(usage string) *StringVarOptions
- func (o *StringVarOptions) SetValue(value *string) *StringVarOptions
- type StyleFunc
- type StyleOption
- func WithAppFlagName(style TextStyle) StyleOption
- func WithAppFlagUsage(style TextStyle) StyleOption
- func WithAppTitle(style TextStyle) StyleOption
- func WithArgumentMarker(style TextStyle) StyleOption
- func WithArgumentName(style TextStyle) StyleOption
- func WithChildDesc(style TextStyle) StyleOption
- func WithChildName(style TextStyle) StyleOption
- func WithCommandFlagName(style TextStyle) StyleOption
- func WithCommandFlagUsage(style TextStyle) StyleOption
- func WithCommandTitle(style TextStyle) StyleOption
- func WithExample(style TextStyle) StyleOption
- func WithSectionHeading(style TextStyle) StyleOption
- func WithStyleAppDescription(style TextStyle) StyleOption
- func WithStyleFlagName(style TextStyle) StyleOption
- func WithStyleFlagUsage(style TextStyle) StyleOption
- func WithUsage(style TextStyle) StyleOption
- type Styles
- func (s *Styles) SetAppDescription(style TextStyle) *Styles
- func (s *Styles) SetAppFlagName(style TextStyle) *Styles
- func (s *Styles) SetAppFlagUsage(style TextStyle) *Styles
- func (s *Styles) SetAppTitle(style TextStyle) *Styles
- func (s *Styles) SetArgumentMarker(style TextStyle) *Styles
- func (s *Styles) SetArgumentName(style TextStyle) *Styles
- func (s *Styles) SetChildDesc(style TextStyle) *Styles
- func (s *Styles) SetChildName(style TextStyle) *Styles
- func (s *Styles) SetCommandFlagName(style TextStyle) *Styles
- func (s *Styles) SetCommandFlagUsage(style TextStyle) *Styles
- func (s *Styles) SetCommandTitle(style TextStyle) *Styles
- func (s *Styles) SetExample(style TextStyle) *Styles
- func (s *Styles) SetFlagName(style TextStyle) *Styles
- func (s *Styles) SetFlagUsage(style TextStyle) *Styles
- func (s *Styles) SetSectionHeading(style TextStyle) *Styles
- func (s *Styles) SetUsage(style TextStyle) *Styles
- type TextPromptOption
- type TextPrompter
- type TextStyle
- type Value
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultPromptTheme = PromptTheme{
Prefix: "? ",
Hint: "",
Error: "! ",
}
DefaultPromptTheme provides a sensible default for terminal prompts.
var DefaultStyles = Styles{}
DefaultStyles leaves all styles unset, producing plain text output.
Functions ¶
Types ¶
type App ¶
type App struct {
// Name is the application name, used in help output and configuration paths.
Name string
// Version is the application version, typically set by the version extension.
// Can be accessed via --version flag when the version extension is enabled.
Version string
// Description is a brief description of the application, shown in help output.
Description string
// Root is the root command of the application. Flags defined on the root
// command are accessible to all commands (via app.Flags()).
// NewApp automatically creates a minimal root command, but you can replace it.
Root *Command
// Config manages application configuration from YAML files and environment variables.
// Configuration values are automatically loaded and available via Context getters.
Config *ConfigManager
// Prompter handles interactive user input. Defaults to TextPrompter.
// Use the prompt extension to enable advanced prompts (select, multi-select).
Prompter Prompter
// Out is the writer for standard output (defaults to os.Stdout).
Out io.Writer
// Err is the writer for error output (defaults to os.Stderr).
Err io.Writer
// In is the reader for user input (defaults to os.Stdin).
In io.Reader
// EnvPrefix is the prefix for environment variable names.
// Defaults to the app name in uppercase with hyphens replaced by underscores.
// For example, "my-app" becomes "MY_APP".
EnvPrefix string
// DefaultTheme configures the default styling for prompts.
// Can be overridden per-prompt via PromptRequest.Theme.
DefaultTheme PromptTheme
// Styles configures text styling for help output and other CLI text.
// Use lipgloss-compatible styles or custom TextStyle implementations.
Styles Styles
// contains filtered or unexported fields
}
App represents a runnable CLI application. It wires together the root command, global flag set, configuration manager and prompting behaviour.
Example:
app := clix.NewApp("myapp")
app.Description = "A sample CLI application"
app.Root = clix.NewGroup("myapp", "Main command",
clix.NewCommand("hello", "Say hello", func(ctx *clix.Context) error {
fmt.Println("Hello, World!")
return nil
}),
)
app.Run(context.Background(), nil)
func NewApp ¶
NewApp constructs an application with sensible defaults. A minimal root command is created automatically to hold default flags (format, help). You can replace it with your own root command if needed: app.Root = clix.NewCommand("myroot")
Example - three API styles:
// 1. Struct-based (primary API)
app := clix.NewApp("myapp")
app.Description = "My application"
app.Version = "1.0.0"
// 2. Functional options
app := clix.NewApp("myapp",
clix.WithAppDescription("My application"),
clix.WithAppVersion("1.0.0"),
)
// 3. Builder-style
app := clix.NewApp("myapp").
SetDescription("My application").
SetVersion("1.0.0")
Note: While you can set Version directly, use the version extension to get `cli --version` and `cli version` commands. The extension will set this field.
Example ¶
ExampleNewApp demonstrates how to create a new CLI application.
package main
import (
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
app.Description = "A sample CLI application"
// Create a root command
root := clix.NewCommand("myapp")
root.Short = "Root command"
app.Root = root
// The app is now ready to use
_ = app
}
func (*App) AddDefaultCommands ¶
func (a *App) AddDefaultCommands()
AddDefaultCommands attaches built-in helper commands to the application.
Note: All commands are now extensions: - Help: clix/ext/help - Config: clix/ext/config - Autocomplete: clix/ext/autocomplete - Version: clix/ext/version No default commands are added automatically.
func (*App) AddExtension ¶
AddExtension registers an extension with the application. Extensions are applied lazily when the app runs, or can be applied immediately by calling ApplyExtensions().
func (*App) ApplyExtensions ¶
ApplyExtensions processes all registered extensions in order. This is typically called automatically during Run(), but can be called manually for testing or early initialization.
func (*App) ConfigDir ¶
ConfigDir returns the absolute path to the application's configuration directory. The directory will be created if it does not already exist.
Example ¶
ExampleApp_ConfigDir demonstrates how to work with configuration files.
package main
import (
"fmt"
"os"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
// Get the config directory (creates if it doesn't exist)
configDir, err := app.ConfigDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return
}
fmt.Printf("Config directory: %s\n", configDir)
// Get the config file path
configFile, err := app.ConfigFile()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return
}
fmt.Printf("Config file: %s\n", configFile)
// Set a config value
app.Config.Set("project", "my-project")
// Save to disk
if err := app.SaveConfig(); err != nil {
fmt.Fprintf(os.Stderr, "Error saving config: %v\n", err)
}
}
func (*App) ConfigFile ¶
ConfigFile returns the path to the main configuration file.
func (*App) Flags ¶
Flags returns the flag set for the root command. Flags defined on the root command apply to all commands (they are "global" by virtue of being on the root). This provides a symmetric API with cmd.Flags.
func (*App) FormatOutput ¶
FormatOutput formats data according to the app's output format setting. It supports "json", "yaml", and "text" formats. For maps/slices, it automatically formats them appropriately. For other types, it falls back to text formatting.
Example ¶
ExampleApp_FormatOutput demonstrates how to use structured output formatting.
package main
import (
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
root.Run = func(ctx *clix.Context) error {
data := map[string]interface{}{
"name": "John Doe",
"age": 30,
"active": true,
"tags": []string{"developer", "golang"},
}
// FormatOutput respects the --format flag (json, yaml, or text)
// Users can run: myapp --format=json
return ctx.App.FormatOutput(data)
}
}
func (*App) OutputFormat ¶
OutputFormat returns the currently selected output format. Valid values are "json", "yaml", or "text" (default).
func (*App) Run ¶
Run executes the CLI using the provided arguments. If args is nil the process arguments (os.Args[1:]) are used.
Example ¶
ExampleApp_Run demonstrates a complete application setup and execution.
package main
import (
"context"
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("greet")
app.Description = "A greeting application"
var name string
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "name",
Short: "n",
Usage: "Name to greet",
},
Value: &name,
Default: "World",
})
// Use the root command created by NewApp, just customize it
app.Root.Short = "Print a greeting"
app.Root.Run = func(ctx *clix.Context) error {
fmt.Fprintf(ctx.App.Out, "Hello, %s!\n", name)
return nil
}
// In a real application, you would call:
// if err := app.Run(context.Background(), nil); err != nil {
// fmt.Fprintln(app.Err, err)
// os.Exit(1)
// }
// For this example, we'll simulate running with arguments
ctx := context.Background()
args := []string{"--name", "Alice"}
_ = app.Run(ctx, args)
}
Output: Hello, Alice!
func (*App) SaveConfig ¶
SaveConfig persists the configuration manager's values to disk.
func (*App) SetDefaultTheme ¶
func (a *App) SetDefaultTheme(theme PromptTheme) *App
SetDefaultTheme sets the default prompt theme and returns the app for method chaining.
func (*App) SetDescription ¶
SetDescription sets the application description and returns the app for method chaining.
func (*App) SetEnvPrefix ¶
SetEnvPrefix sets the environment variable prefix and returns the app for method chaining.
func (*App) SetPrompter ¶
SetPrompter sets the prompter and returns the app for method chaining.
func (*App) SetStyles ¶
SetStyles sets the application styles and returns the app for method chaining.
func (*App) SetVersion ¶
SetVersion sets the application version and returns the app for method chaining. Note: While you can set Version directly, use the version extension to get `cli --version` and `cli version` commands. The extension will set this field.
type AppOption ¶
type AppOption interface {
// ApplyApp configures an App struct.
// Exported so extension packages can implement AppOption.
ApplyApp(*App)
}
AppOption configures an App using the functional options pattern. Options can be used to build apps:
// Using functional options
app := clix.NewApp("myapp",
clix.WithAppDescription("My application"),
clix.WithAppVersion("1.0.0"),
clix.WithAppEnvPrefix("MYAPP"),
)
// Using struct (primary API)
app := clix.NewApp("myapp")
app.Description = "My application"
func WithAppDefaultTheme ¶
func WithAppDefaultTheme(theme PromptTheme) AppOption
WithAppDefaultTheme sets the default prompt theme.
func WithAppDescription ¶
WithAppDescription sets the application description.
func WithAppEnvPrefix ¶
WithAppEnvPrefix sets the environment variable prefix.
func WithAppPrompter ¶
WithAppPrompter sets the prompter.
func WithAppStyles ¶
WithAppStyles sets the application styles.
func WithAppVersion ¶
WithAppVersion sets the application version. Note: While you can set Version directly, use the version extension to get `cli --version` and `cli version` commands. The extension will set this field.
type Argument ¶
type Argument struct {
// Name is the argument name, used for named argument access (key=value format)
// and for accessing via ctx.ArgNamed(name).
Name string
// Prompt is the text shown when prompting for this argument if it's missing.
// If empty, a default prompt is generated from the Name field.
Prompt string
// Default is the default value if the argument is not provided.
// Only used if Required is false.
Default string
// Required indicates whether this argument must be provided.
// Missing required arguments trigger interactive prompts (if available).
Required bool
// Validate is an optional validation function called when the argument is provided.
// Return an error if the value is invalid.
Validate func(string) error
}
Argument describes a positional argument for a command. This struct implements ArgumentOption, so it can be used alongside functional options.
Example:
// Struct-based (primary API)
cmd.Arguments = []*clix.Argument{
{
Name: "name",
Prompt: "Enter your name",
Required: true,
Validate: validation.NotEmpty,
},
{
Name: "email",
Prompt: "Enter your email",
Default: "[email protected]",
Validate: validation.Email,
},
}
// Functional options
cmd.Arguments = []*clix.Argument{
clix.NewArgument(
WithArgName("name"),
WithArgPrompt("Enter your name"),
WithArgRequired(),
WithArgValidate(validation.NotEmpty),
),
clix.NewArgument(
WithArgName("email"),
WithArgPrompt("Enter your email"),
WithArgDefault("[email protected]"),
WithArgValidate(validation.Email),
),
}
Example ¶
ExampleArgument demonstrates how to define positional arguments with prompting.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
cmd := clix.NewCommand("greet")
cmd.Short = "Print a greeting"
// Required argument with automatic prompting
cmd.Arguments = []*clix.Argument{
{
Name: "name",
Prompt: "What is your name?",
Required: true,
Validate: func(value string) error {
if len(value) < 2 {
return fmt.Errorf("name must be at least 2 characters")
}
return nil
},
},
{
Name: "title",
Prompt: "What is your title?",
Default: "Developer",
},
}
cmd.Run = func(ctx *clix.Context) error {
name := ctx.Args[0]
title := ctx.Args[1]
fmt.Fprintf(ctx.App.Out, "Hello %s, %s!\n", title, name)
return nil
}
}
func NewArgument ¶
func NewArgument(opts ...ArgumentOption) *Argument
NewArgument creates a new Argument using functional options. Supports three API styles:
// 1. Struct-based (primary API)
arg := &clix.Argument{
Name: "name",
Prompt: "Enter your name",
Required: true,
}
// 2. Functional options
arg := clix.NewArgument(
WithArgName("name"),
WithArgPrompt("Enter your name"),
WithArgRequired(),
)
// 3. Builder-style (fluent API)
arg := clix.NewArgument().
SetName("name").
SetPrompt("Enter your name").
SetRequired()
func (*Argument) ApplyArgument ¶
ApplyArgument implements ArgumentOption so Argument can be used directly.
func (*Argument) PromptLabel ¶
PromptLabel returns the prompt to display for this argument.
func (*Argument) SetDefault ¶
SetDefault sets the argument default value and returns the argument for method chaining.
func (*Argument) SetName ¶
SetName sets the argument name and returns the argument for method chaining.
func (*Argument) SetPrompt ¶
SetPrompt sets the argument prompt text and returns the argument for method chaining.
func (*Argument) SetRequired ¶
SetRequired marks the argument as required and returns the argument for method chaining.
type ArgumentOption ¶
type ArgumentOption interface {
// ApplyArgument configures an argument struct.
// Exported so extension packages can implement ArgumentOption.
ApplyArgument(*Argument)
}
ArgumentOption configures an argument using the functional options pattern. Options can be used to build arguments:
// Using functional options
cmd.Arguments = []*clix.Argument{
clix.NewArgument(
WithArgName("name"),
WithArgPrompt("Enter your name"),
WithArgRequired(),
WithArgValidate(validation.NotEmpty),
),
}
// Using struct (primary API)
cmd.Arguments = []*clix.Argument{{
Name: "name",
Prompt: "Enter your name",
Required: true,
Validate: validation.NotEmpty,
}}
func WithArgDefault ¶
func WithArgDefault(defaultValue string) ArgumentOption
WithArgDefault sets the argument default value.
func WithArgPrompt ¶
func WithArgPrompt(prompt string) ArgumentOption
WithArgPrompt sets the argument prompt text.
func WithArgRequired ¶
func WithArgRequired() ArgumentOption
WithArgRequired marks the argument as required.
func WithArgValidate ¶
func WithArgValidate(validate func(string) error) ArgumentOption
WithArgValidate sets the argument validation function.
type BoolValue ¶
type BoolValue struct {
// contains filtered or unexported fields
}
BoolValue implements Value for boolean flags.
type BoolVarOptions ¶
type BoolVarOptions struct {
FlagOptions
// Value is a pointer to the variable that will store the flag value.
Value *bool
}
BoolVarOptions describes the configuration for adding a bool flag. This struct implements FlagOption, so it can be used alongside functional options.
Example:
var verbose bool
// Struct-based (primary API)
cmd.Flags.BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "verbose",
Short: "v",
Usage: "Enable verbose output",
},
Value: &verbose,
})
// Functional options
cmd.Flags.BoolVar(
WithFlagName("verbose"),
WithFlagShort("v"),
WithFlagUsage("Enable verbose output"),
WithBoolValue(&verbose),
)
func (BoolVarOptions) ApplyFlag ¶
func (o BoolVarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so BoolVarOptions can be used directly.
func (*BoolVarOptions) SetEnvVar ¶
func (o *BoolVarOptions) SetEnvVar(envVar string) *BoolVarOptions
SetEnvVar sets the environment variable name and returns the options for method chaining.
func (*BoolVarOptions) SetName ¶
func (o *BoolVarOptions) SetName(name string) *BoolVarOptions
SetName sets the flag name and returns the options for method chaining.
func (*BoolVarOptions) SetShort ¶
func (o *BoolVarOptions) SetShort(short string) *BoolVarOptions
SetShort sets the flag shorthand and returns the options for method chaining.
func (*BoolVarOptions) SetUsage ¶
func (o *BoolVarOptions) SetUsage(usage string) *BoolVarOptions
SetUsage sets the flag usage text and returns the options for method chaining.
func (*BoolVarOptions) SetValue ¶
func (o *BoolVarOptions) SetValue(value *bool) *BoolVarOptions
SetValue sets the value pointer and returns the options for method chaining.
type Command ¶
type Command struct {
// Name is the command name, used for matching and in help output.
Name string
// Aliases are alternative names for the command (e.g., ["ls", "list"]).
Aliases []string
// Short is a brief one-line description shown in command lists.
Short string
// Long is a detailed multi-line description shown in command help.
Long string
// Usage is a usage string shown in help output (e.g., "myapp cmd [flags] [args]").
// If empty, a default usage string is generated.
Usage string
// Example shows example usage in help output.
Example string
// Hidden hides the command from help output and autocomplete.
Hidden bool
// Flags is the flag set for this command. Flags defined here are scoped to this command.
// Use app.Flags() for flags that apply to all commands.
Flags *FlagSet
// Arguments defines the positional arguments this command accepts.
// Arguments can be required or optional, and can prompt for missing values.
Arguments []*Argument
// Children are the child commands or groups of this command.
// Use NewGroup() to create groups, NewCommand() to create executable commands.
Children []*Command
// Run is the handler executed when this command is invoked.
// If the command has children and no Run handler, it shows help (group behavior).
// If the command has both children and a Run handler, the Run handler executes
// when called without matching child commands.
Run Handler
// PreRun is executed before Run. Useful for setup or validation.
PreRun Hook
// PostRun is executed after Run. Useful for cleanup or finalization.
PostRun Hook
// contains filtered or unexported fields
}
Command represents a CLI command. Commands can contain nested children (groups or commands), flags, argument definitions and execution hooks.
A Command can be one of three types:
- A Group: has children but no Run handler (interior node, shows help when called)
- A Leaf Command: has a Run handler but no children (executable leaf node)
- A Command with Children: has both a Run handler and children (executes Run handler when called without args, or routes to child commands when a child name is provided)
Example:
// Create a group (organizes child commands)
projectGroup := clix.NewGroup("project", "Manage projects",
clix.NewCommand("list", "List projects", listProjects),
clix.NewCommand("get", "Get a project", getProject),
)
// Create a command (executable)
helloCmd := clix.NewCommand("hello")
helloCmd.Short = "Say hello"
helloCmd.Run = func(ctx *clix.Context) error {
fmt.Println("Hello!")
return nil
}
func NewCommand ¶
func NewCommand(name string, opts ...CommandOption) *Command
NewCommand constructs a Command with an initialised flag set. This creates an executable command (leaf node) that can have a Run handler. Accepts optional CommandOption arguments for configuration.
Example - three API styles:
// 1. Struct-based (primary API)
cmd := clix.NewCommand("hello")
cmd.Short = "Say hello"
cmd.Run = func(ctx *clix.Context) error {
fmt.Println("Hello!")
return nil
}
// 2. Functional options
cmd := clix.NewCommand("hello",
clix.WithCommandShort("Say hello"),
clix.WithCommandRun(func(ctx *clix.Context) error {
fmt.Println("Hello!")
return nil
}),
)
// 3. Mixed (constructor + struct fields)
cmd := clix.NewCommand("hello",
clix.WithCommandShort("Say hello"),
)
cmd.Run = func(ctx *clix.Context) error { ... }
Example ¶
ExampleNewCommand demonstrates how to create commands.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
// Create an executable command (leaf node)
create := clix.NewCommand("create")
create.Short = "Create a new user"
create.Run = func(ctx *clix.Context) error {
fmt.Fprintf(ctx.App.Out, "Creating user...\n")
return nil
}
// Commands can have aliases
list := clix.NewCommand("list")
list.Aliases = []string{"ls", "l"}
list.Short = "List all users"
}
func NewGroup ¶
NewGroup constructs a Command that acts as a group (interior node). Groups organize child commands but do not execute (no Run handler). Groups are used to create hierarchical command structures. Accepts optional CommandOption arguments for additional configuration.
// Struct-based (primary API)
group := clix.NewGroup("project", "Manage projects",
clix.NewCommand("list", ...),
clix.NewCommand("get", ...),
)
group.Long = "Detailed description..."
// Functional options
group := clix.NewGroup("project", "Manage projects",
clix.NewCommand("list", ...),
clix.NewCommand("get", ...),
WithCommandLong("Detailed description..."),
)
Example ¶
ExampleNewGroup demonstrates how to create groups and organize commands.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
// Create executable commands (leaf nodes)
createUser := clix.NewCommand("create")
createUser.Short = "Create a new user"
createUser.Run = func(ctx *clix.Context) error {
fmt.Fprintf(ctx.App.Out, "Creating user...\n")
return nil
}
listUsers := clix.NewCommand("list")
listUsers.Short = "List all users"
listUsers.Run = func(ctx *clix.Context) error {
fmt.Fprintf(ctx.App.Out, "Listing users...\n")
return nil
}
// Create a group (interior node) that organizes child commands
users := clix.NewGroup("users", "Manage user accounts",
createUser,
listUsers,
)
// Groups can contain nested groups
listProjects := clix.NewCommand("list")
listProjects.Short = "List projects"
projects := clix.NewGroup("projects", "Manage projects", listProjects)
// Build a command tree with groups and commands
version := clix.NewCommand("version")
version.Short = "Show version"
root := clix.NewGroup("demo", "Demo application",
users,
projects,
version,
)
_ = root
}
func (*Command) AddCommand ¶
AddCommand registers a child command or group. The parent/child relationship is managed automatically.
func (*Command) IsGroup ¶
IsGroup returns true if this command is a group (has children but no Run handler). Groups are interior nodes that organize child commands.
func (*Command) IsLeaf ¶
IsLeaf returns true if this command is a leaf (has a Run handler). Leaf commands are executable commands, even if they have flags or arguments.
func (*Command) RequiredArgs ¶
RequiredArgs returns the number of required positional arguments.
func (*Command) ResolvePath ¶
ResolvePath resolves a path like ["config", "set"] into a command.
func (*Command) SetAliases ¶
SetAliases sets the command aliases and returns the command for method chaining.
func (*Command) SetArguments ¶
SetArguments sets the command arguments and returns the command for method chaining.
func (*Command) SetExample ¶
SetExample sets the command example string and returns the command for method chaining.
func (*Command) SetHidden ¶
SetHidden marks the command as hidden and returns the command for method chaining.
func (*Command) SetLong ¶
SetLong sets the command long description and returns the command for method chaining.
func (*Command) SetPostRun ¶
SetPostRun sets the command post-run hook and returns the command for method chaining.
func (*Command) SetPreRun ¶
SetPreRun sets the command pre-run hook and returns the command for method chaining.
func (*Command) SetRun ¶
SetRun sets the command run handler and returns the command for method chaining.
func (*Command) SetShort ¶
SetShort sets the command short description and returns the command for method chaining.
func (*Command) SetUsage ¶
SetUsage sets the command usage string and returns the command for method chaining.
func (*Command) VisibleChildren ¶
VisibleChildren returns a sorted slice of child commands and groups that are not hidden.
type CommandOption ¶
type CommandOption interface {
// ApplyCommand configures a command struct.
// Exported so extension packages can implement CommandOption.
ApplyCommand(*Command)
}
CommandOption configures a command using the functional options pattern. Options can be used to build commands:
// Using functional options
cmd := clix.NewCommand("hello",
WithCommandShort("Say hello"),
WithCommandRun(func(ctx *clix.Context) error {
fmt.Println("Hello!")
return nil
}),
)
// Using struct (primary API)
cmd := clix.NewCommand("hello")
cmd.Short = "Say hello"
cmd.Run = func(ctx *clix.Context) error { ... }
func WithCommandAliases ¶
func WithCommandAliases(aliases ...string) CommandOption
WithCommandAliases sets the command aliases.
func WithCommandArguments ¶
func WithCommandArguments(args ...*Argument) CommandOption
WithCommandArguments sets the command arguments.
func WithCommandExample ¶
func WithCommandExample(example string) CommandOption
WithCommandExample sets the command example string.
func WithCommandHidden ¶
func WithCommandHidden(hidden bool) CommandOption
WithCommandHidden marks the command as hidden.
func WithCommandLong ¶
func WithCommandLong(long string) CommandOption
WithCommandLong sets the command long description.
func WithCommandPostRun ¶
func WithCommandPostRun(postRun Hook) CommandOption
WithCommandPostRun sets the command post-run hook.
func WithCommandPreRun ¶
func WithCommandPreRun(preRun Hook) CommandOption
WithCommandPreRun sets the command pre-run hook.
func WithCommandRun ¶
func WithCommandRun(run Handler) CommandOption
WithCommandRun sets the command run handler.
func WithCommandShort ¶
func WithCommandShort(short string) CommandOption
WithCommandShort sets the command short description.
func WithCommandUsage ¶
func WithCommandUsage(usage string) CommandOption
WithCommandUsage sets the command usage string.
type ConfigManager ¶
type ConfigManager struct {
// contains filtered or unexported fields
}
ConfigManager loads and stores configuration from YAML files and environment variables. Configuration values are automatically loaded when App.Run is called and are accessible via Context getters with precedence: command flags > app flags > env > config > defaults.
Example:
app := clix.NewApp("myapp")
// Config is automatically created and loaded
// Access values via context:
cmd.Run = func(ctx *clix.Context) error {
if value, ok := ctx.String("key"); ok {
// Value from config file, env var, or default
}
return nil
}
func NewConfigManager ¶
func NewConfigManager(name string) *ConfigManager
NewConfigManager constructs a manager for the given application name.
func (*ConfigManager) Bool ¶
func (m *ConfigManager) Bool(key string) (bool, bool)
Bool retrieves a boolean value from persisted config.
func (*ConfigManager) Delete ¶
func (m *ConfigManager) Delete(key string) bool
Delete removes a key from the configuration. It returns true if the key existed. Keys are stored using dot-separated paths (e.g. "project.default").
func (*ConfigManager) Float64 ¶
func (m *ConfigManager) Float64(key string) (float64, bool)
Float64 retrieves a float64 value from persisted config.
func (*ConfigManager) Get ¶
func (m *ConfigManager) Get(key string) (string, bool)
Get retrieves a value.
func (*ConfigManager) Int64 ¶
func (m *ConfigManager) Int64(key string) (int64, bool)
Int64 retrieves an int64 value from persisted config.
func (*ConfigManager) Integer ¶
func (m *ConfigManager) Integer(key string) (int, bool)
Integer retrieves an int value from persisted config.
func (*ConfigManager) Load ¶
func (m *ConfigManager) Load(path string) error
Load reads configuration from the provided path. Missing files are ignored.
func (*ConfigManager) NormalizeValue ¶
func (m *ConfigManager) NormalizeValue(key, value string) (string, error)
NormalizeValue validates and canonicalises a value according to the schema (if present). The returned string is safe to persist. When no schema exists, the original value is returned.
func (*ConfigManager) RegisterSchema ¶
func (m *ConfigManager) RegisterSchema(entries ...ConfigSchemaOption)
RegisterSchema registers one or more schema entries for configuration keys. Registration is optional; keys without schema entries behave like raw strings. Accepts either ConfigSchema structs (primary API) or functional options (convenience layer).
Example - two API styles:
// 1. Struct-based (primary API)
app.Config.RegisterSchema(clix.ConfigSchema{
Key: "project.retries",
Type: clix.ConfigInteger,
Validate: validation.IntRange(1, 10),
})
// 2. Functional options
app.Config.RegisterSchema(
clix.WithConfigKey("project.retries"),
clix.WithConfigType(clix.ConfigInteger),
clix.WithConfigValidate(validation.IntRange(1, 10)),
)
// 3. Mixed (struct + functional options)
app.Config.RegisterSchema(
clix.ConfigSchema{Key: "project.retries"},
clix.WithConfigType(clix.ConfigInteger),
)
func (*ConfigManager) Save ¶
func (m *ConfigManager) Save(path string) error
Save writes the configuration to the provided path in YAML format.
func (*ConfigManager) String ¶
func (m *ConfigManager) String(key string) (string, bool)
String retrieves a raw string value directly from persisted config.
func (*ConfigManager) Values ¶
func (m *ConfigManager) Values() map[string]string
Values returns a copy of the stored values.
type ConfigSchema ¶
type ConfigSchema struct {
Key string
Type ConfigType
Validate func(string) error
}
ConfigSchema describes an expected type (and optional validator) for a config key. This struct implements ConfigSchemaOption, so it can be used alongside functional options. This is optional— schemas only apply when registered via RegisterSchema.
Example:
// Struct-based (primary API)
app.Config.RegisterSchema(clix.ConfigSchema{
Key: "project.retries",
Type: clix.ConfigInteger,
Validate: validation.IntRange(1, 10),
})
// Functional options
app.Config.RegisterSchema(
WithConfigKey("project.retries"),
WithConfigType(clix.ConfigInteger),
WithConfigValidate(validation.IntRange(1, 10)),
)
func (ConfigSchema) ApplyConfigSchema ¶
func (s ConfigSchema) ApplyConfigSchema(schema *ConfigSchema)
ApplyConfigSchema implements ConfigSchemaOption so ConfigSchema can be used directly.
func (*ConfigSchema) SetKey ¶
func (s *ConfigSchema) SetKey(key string) *ConfigSchema
SetKey sets the config schema key and returns the schema for method chaining.
func (*ConfigSchema) SetType ¶
func (s *ConfigSchema) SetType(typ ConfigType) *ConfigSchema
SetType sets the config schema type and returns the schema for method chaining.
func (*ConfigSchema) SetValidate ¶
func (s *ConfigSchema) SetValidate(validate func(string) error) *ConfigSchema
SetValidate sets the validation function and returns the schema for method chaining.
type ConfigSchemaOption ¶
type ConfigSchemaOption interface {
// ApplyConfigSchema configures a config schema struct.
// Exported so extension packages can implement ConfigSchemaOption.
ApplyConfigSchema(*ConfigSchema)
}
ConfigSchemaOption configures a config schema using the functional options pattern. Options can be used to build schemas:
// Using functional options
app.Config.RegisterSchema(
WithConfigKey("project.retries"),
WithConfigType(clix.ConfigInteger),
WithConfigValidate(validation.IntRange(1, 10)),
)
// Using struct (primary API)
app.Config.RegisterSchema(clix.ConfigSchema{
Key: "project.retries",
Type: clix.ConfigInteger,
Validate: validation.IntRange(1, 10),
})
func WithConfigKey ¶
func WithConfigKey(key string) ConfigSchemaOption
WithConfigKey sets the config schema key.
func WithConfigType ¶
func WithConfigType(typ ConfigType) ConfigSchemaOption
WithConfigType sets the config schema type.
func WithConfigValidate ¶
func WithConfigValidate(validate func(string) error) ConfigSchemaOption
WithConfigValidate sets the config schema validation function.
type ConfigType ¶
type ConfigType int
ConfigType represents the desired type for a configuration value.
const ( // ConfigString stores raw string values (default behaviour). ConfigString ConfigType = iota // ConfigBool stores canonical boolean values ("true"/"false"). ConfigBool // ConfigInteger stores 32-bit integers. ConfigInteger // ConfigInt64 stores 64-bit integers. ConfigInt64 // ConfigFloat64 stores floating-point numbers. ConfigFloat64 )
type Context ¶
type Context struct {
context.Context // Embedded for cancellation, deadlines, and context values
// App is the application instance executing this command.
App *App
// Command is the currently executing command.
Command *Command
// Args contains positional arguments passed to the command.
// Use Arg(index) or ArgNamed(name) for safer access with bounds checking.
Args []string
}
Context is passed to command handlers and provides convenient access to the resolved command, arguments, configuration and flags. Context provides CLI-specific context for command execution. It embeds context.Context for cancellation and deadlines, and adds CLI-specific data like the active command, arguments, and app instance.
Context is passed to all command handlers (Run, PreRun, PostRun) and provides access to flags, arguments, and configuration via type-specific getters that respect precedence: command flags > app flags > env > config > defaults.
Example:
cmd.Run = func(ctx *clix.Context) error {
// Access flags with precedence
if project, ok := ctx.String("project"); ok {
fmt.Printf("Using project: %s\n", project)
}
// Access arguments
if name, ok := ctx.ArgNamed("name"); ok {
fmt.Printf("Hello, %s!\n", name)
}
// Use context.Context for cancellation
select {
case <-ctx.Done():
return ctx.Err()
default:
// Continue execution
}
return nil
}
Context wraps the standard library context.Context with CLI metadata. It should be passed to any code that needs cancellation, deadlines, or values related to this command execution.
Because Context embeds context.Context, you can pass it anywhere a context.Context is required (e.g., to Prompter.Prompt).
func (*Context) AllArgs ¶
AllArgs returns all positional arguments as a slice. This provides a symmetric API with String()/Bool() for flags. You can also access ctx.Args directly if preferred.
func (*Context) Arg ¶
Arg returns the positional argument at the given index. Returns empty string if index is out of bounds.
func (*Context) ArgNamed ¶
ArgNamed returns the value of a named argument by its name. Returns the value and true if found, empty string and false otherwise. This looks up arguments by the Name field in the command's Arguments definition.
func (*Context) Bool ¶
Bool retrieves a boolean configuration value using the same precedence as String (command flags, root flags, env, config, defaults). This follows the log/slog naming pattern for type-specific getters. Precedence: command flags > app flags > env > config > defaults
Example ¶
ExampleContext_Bool demonstrates how to access boolean configuration values.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
var verbose bool
app.Flags().BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "verbose",
},
Value: &verbose,
})
root.Run = func(ctx *clix.Context) error {
if verbose, ok := ctx.Bool("verbose"); ok && verbose {
fmt.Fprintln(ctx.App.Out, "Verbose mode enabled")
}
return nil
}
}
func (*Context) String ¶
String retrieves a string configuration value with the given key, looking at command flags, root flags, environment variables, config file, then defaults. This follows the log/slog naming pattern for type-specific getters. Precedence: command flags > app flags > env > config > defaults
Example ¶
ExampleContext_String demonstrates how to access configuration values from context.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
var project string
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "project",
EnvVar: "MYAPP_PROJECT",
},
Value: &project,
})
root.Run = func(ctx *clix.Context) error {
// String checks flags, env vars, and config in precedence order
if project, ok := ctx.String("project"); ok {
fmt.Fprintf(ctx.App.Out, "Using project: %s\n", project)
} else {
fmt.Fprintln(ctx.App.Out, "No project specified")
}
return nil
}
}
type DurationValue ¶
type DurationValue struct {
// contains filtered or unexported fields
}
DurationValue implements Value using Go's duration parser.
func (*DurationValue) Set ¶
func (d *DurationValue) Set(value string) error
func (*DurationValue) String ¶
func (d *DurationValue) String() string
type DurationVarOptions ¶
type DurationVarOptions struct {
FlagOptions
// Default is the default value as a duration string (e.g., "30s", "5m").
Default string
// Value is a pointer to the variable that will store the flag value.
Value *time.Duration
}
DurationVarOptions describes the configuration for adding a duration flag. This struct implements FlagOption, so it can be used alongside functional options.
Example:
var timeout time.Duration
// Struct-based (primary API)
cmd.Flags.DurationVar(clix.DurationVarOptions{
FlagOptions: clix.FlagOptions{
Name: "timeout",
Usage: "Operation timeout",
},
Default: "30s",
Value: &timeout,
})
// Functional options
cmd.Flags.DurationVar(
WithFlagName("timeout"),
WithFlagUsage("Operation timeout"),
WithDurationValue(&timeout),
WithDurationDefault("30s"),
)
func (DurationVarOptions) ApplyFlag ¶
func (o DurationVarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so DurationVarOptions can be used directly.
type Extension ¶
type Extension interface {
// Extend is called during app initialization to register commands, hooks,
// or modify app behavior. Extensions are applied in the order they are added.
Extend(app *App) error
}
Extension is the interface that optional "batteries-included" features implement. Extensions allow features to be added to an App without requiring imports in the core package, keeping simple applications lightweight.
This design is inspired by goldmark's extension system: https://github.com/yuin/goldmark
Example:
type MyExtension struct{}
func (e MyExtension) Extend(app *clix.App) error {
if app.Root != nil {
cmd := clix.NewCommand("custom")
cmd.Short = "Custom command"
app.Root.AddCommand(cmd)
}
return nil
}
app.AddExtension(MyExtension{})
Example ¶
ExampleExtension demonstrates how to create and use extensions. Extensions implement the clix.Extension interface to add optional features.
package main
import (
"github.com/SCKelemen/clix"
)
func main() {
// Define a custom extension type
type MyExtension struct {
FeatureEnabled bool
}
// Implement the Extension interface
var ext clix.Extension = extensionImpl{enabled: true}
// Use the extension
app := clix.NewApp("myapp")
app.Root = clix.NewCommand("myapp")
app.AddExtension(ext)
// Extensions are applied when app.Run() is called
// They can add commands, modify behavior, etc.
_ = MyExtension{FeatureEnabled: true}
}
// extensionImpl is a helper type for the example
type extensionImpl struct {
enabled bool
}
func (e extensionImpl) Extend(app *clix.App) error {
return nil
}
type Flag ¶
type Flag struct {
// Name is the long flag name (e.g., "project" for --project).
Name string
// Short is the shorthand flag name (e.g., "p" for -p).
Short string
// Usage is the help text shown for this flag.
Usage string
// EnvVar is the environment variable name for this flag.
// If empty, defaults to APP_KEY format based on EnvPrefix.
EnvVar string
// Default is the default value for this flag (as a string).
Default string
// Value is the flag value implementation.
Value Value
// contains filtered or unexported fields
}
Flag describes a single CLI flag. Flags are created via FlagSet methods (StringVar, BoolVar, etc.).
type FlagOption ¶
type FlagOption interface {
// ApplyFlag configures a flag option struct.
// Exported so extension packages can implement FlagOption.
ApplyFlag(*FlagOptions)
}
FlagOption configures a flag using the functional options pattern. Options can be used to build flags:
// Using functional options
app.Flags().StringVar(WithFlagName("project"), WithFlagShort("p"), WithFlagUsage("Project name"), WithFlagValue(&project))
// Using struct (primary API)
app.Flags().StringVar(clix.StringVarOptions{...})
func WithBoolValue ¶
func WithBoolValue(value *bool) FlagOption
WithBoolValue sets the bool flag value pointer.
func WithDurationDefault ¶
func WithDurationDefault(defaultValue string) FlagOption
WithDurationDefault sets the duration flag default value.
func WithDurationValue ¶
func WithDurationValue(value *time.Duration) FlagOption
WithDurationValue sets the duration flag value pointer.
func WithFlagEnvVar ¶
func WithFlagEnvVar(envVar string) FlagOption
WithFlagEnvVar sets the flag environment variable name.
func WithFlagEnvVars ¶
func WithFlagEnvVars(envVars ...string) FlagOption
WithFlagEnvVars sets additional environment variable aliases.
func WithFlagShort ¶
func WithFlagShort(short string) FlagOption
WithFlagShort sets the flag shorthand.
func WithFlagUsage ¶
func WithFlagUsage(usage string) FlagOption
WithFlagUsage sets the flag usage text.
func WithFloat64Default ¶
func WithFloat64Default(defaultValue string) FlagOption
WithFloat64Default sets the float64 flag default value.
func WithFloat64Value ¶
func WithFloat64Value(value *float64) FlagOption
WithFloat64Value sets the float64 flag value pointer.
func WithInt64Default ¶
func WithInt64Default(defaultValue string) FlagOption
WithInt64Default sets the int64 flag default value.
func WithInt64Value ¶
func WithInt64Value(value *int64) FlagOption
WithInt64Value sets the int64 flag value pointer.
func WithIntegerDefault ¶
func WithIntegerDefault(defaultValue string) FlagOption
WithIntegerDefault sets the integer flag default value.
func WithIntegerValue ¶
func WithIntegerValue(value *int) FlagOption
WithIntegerValue sets the integer flag value pointer.
func WithStringDefault ¶
func WithStringDefault(defaultValue string) FlagOption
WithStringDefault sets the string flag default value.
func WithStringValue ¶
func WithStringValue(value *string) FlagOption
WithStringValue sets the string flag value pointer.
type FlagOptions ¶
type FlagOptions struct {
// Name is the long flag name (e.g., "project" for --project).
Name string
// Short is the optional shorthand flag name (e.g., "p" for -p).
Short string
// Usage is the help text shown for this flag.
Usage string
// EnvVar is the environment variable name for this flag.
// If empty, defaults to APP_KEY format based on the app's EnvPrefix.
EnvVar string
// EnvVars are optional additional environment variable aliases.
// All listed environment variables are checked in order.
EnvVars []string
}
FlagOptions contains common configuration for all flag types. This struct is embedded in all *VarOptions types to provide a unified API.
type FlagSet ¶
type FlagSet struct {
// contains filtered or unexported fields
}
FlagSet stores a collection of flags for a command or scope. Flags defined on the root command (via app.Flags()) apply to all commands. Flags defined on a command are scoped to that command.
Example:
// App-level flags (global)
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "project",
Short: "p",
Usage: "Project to operate on",
EnvVar: "MYAPP_PROJECT",
},
Default: "default-project",
Value: &project,
})
// Command-level flags
cmd.Flags.BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "verbose",
Short: "v",
Usage: "Enable verbose output",
},
Value: &verbose,
})
func (*FlagSet) BoolVar ¶
func (fs *FlagSet) BoolVar(opts ...FlagOption)
BoolVar registers a boolean flag. Accepts either a BoolVarOptions struct (primary API) or functional options (convenience layer).
Example ¶
ExampleFlagSet_BoolVar demonstrates how to register boolean flags.
package main
import (
"github.com/SCKelemen/clix"
)
func main() {
var verbose bool
var force bool
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
// Global boolean flag
app.Flags().BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "verbose",
Short: "v",
Usage: "Enable verbose output",
},
Value: &verbose,
})
// Command-level boolean flag
root.Flags.BoolVar(clix.BoolVarOptions{
FlagOptions: clix.FlagOptions{
Name: "force",
Short: "f",
Usage: "Force operation without confirmation",
},
Value: &force,
})
}
func (*FlagSet) DurationVar ¶
func (fs *FlagSet) DurationVar(opts ...FlagOption)
DurationVar registers a duration flag. Accepts either a DurationVarOptions struct (primary API) or functional options (convenience layer).
func (*FlagSet) Float64Var ¶
func (fs *FlagSet) Float64Var(opts ...FlagOption)
Float64Var registers a float64 flag. Accepts either a Float64VarOptions struct (primary API) or functional options (convenience layer).
func (*FlagSet) Int64Var ¶
func (fs *FlagSet) Int64Var(opts ...FlagOption)
Int64Var registers an int64 flag. Accepts either an Int64VarOptions struct (primary API) or functional options (convenience layer).
func (*FlagSet) IntVar ¶
func (fs *FlagSet) IntVar(opts ...FlagOption)
IntVar registers an int flag. Accepts either an IntVarOptions struct (primary API) or functional options (convenience layer).
func (*FlagSet) Parse ¶
Parse consumes recognised flags from args, returning remaining positional arguments.
func (*FlagSet) StringVar ¶
func (fs *FlagSet) StringVar(opts ...FlagOption)
StringVar registers a string flag. Accepts either a StringVarOptions struct (primary API) or functional options (convenience layer).
// Struct-based (primary API)
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{Name: "project", Short: "p"},
Value: &project,
})
// Functional options
app.Flags().StringVar(
WithFlagName("project"),
WithFlagShort("p"),
WithStringValue(&project),
)
Example ¶
ExampleFlagSet_StringVar demonstrates how to register string flags.
package main
import (
"github.com/SCKelemen/clix"
)
func main() {
var project string
var region string
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
// Global flags
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "project",
Short: "p",
Usage: "Project to operate on",
EnvVar: "MYAPP_PROJECT",
},
Value: &project,
Default: "default-project",
})
// Command-level flags
root.Flags.StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "region",
Short: "r",
Usage: "Region to deploy to",
EnvVar: "MYAPP_REGION",
},
Value: ®ion,
Default: "us-east-1",
})
}
type Float64Value ¶
type Float64Value struct {
// contains filtered or unexported fields
}
Float64Value implements Value for float64 flags.
func (*Float64Value) Set ¶
func (f *Float64Value) Set(value string) error
func (*Float64Value) String ¶
func (f *Float64Value) String() string
type Float64VarOptions ¶
type Float64VarOptions struct {
FlagOptions
// Default is the default value as a string (e.g., "0.5").
Default string
// Value is a pointer to the variable that will store the flag value.
Value *float64
}
Float64VarOptions describes the configuration for adding a float64 flag. This struct implements FlagOption, so it can be used alongside functional options.
Example:
var ratio float64
// Struct-based (primary API)
cmd.Flags.Float64Var(clix.Float64VarOptions{
FlagOptions: clix.FlagOptions{
Name: "ratio",
Usage: "Compression ratio",
},
Default: "0.5",
Value: &ratio,
})
// Functional options
cmd.Flags.Float64Var(
WithFlagName("ratio"),
WithFlagUsage("Compression ratio"),
WithFloat64Value(&ratio),
WithFloat64Default("0.5"),
)
func (Float64VarOptions) ApplyFlag ¶
func (o Float64VarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so Float64VarOptions can be used directly.
type HelpRenderer ¶
HelpRenderer prints help text for commands.
type Int64Value ¶
type Int64Value struct {
// contains filtered or unexported fields
}
Int64Value implements Value for int64 flags.
func (*Int64Value) Set ¶
func (i *Int64Value) Set(value string) error
func (*Int64Value) String ¶
func (i *Int64Value) String() string
type Int64VarOptions ¶
type Int64VarOptions struct {
FlagOptions
// Default is the default value as a string (e.g., "1024").
Default string
// Value is a pointer to the variable that will store the flag value.
Value *int64
}
Int64VarOptions describes the configuration for adding an int64 flag. This struct implements FlagOption, so it can be used alongside functional options.
Example:
var size int64
// Struct-based (primary API)
cmd.Flags.Int64Var(clix.Int64VarOptions{
FlagOptions: clix.FlagOptions{
Name: "size",
Usage: "Size in bytes",
},
Default: "1024",
Value: &size,
})
// Functional options
cmd.Flags.Int64Var(
WithFlagName("size"),
WithFlagUsage("Size in bytes"),
WithInt64Value(&size),
WithInt64Default("1024"),
)
func (Int64VarOptions) ApplyFlag ¶
func (o Int64VarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so Int64VarOptions can be used directly.
type IntValue ¶
type IntValue struct {
// contains filtered or unexported fields
}
IntValue implements Value for int flags.
type IntVarOptions ¶
type IntVarOptions struct {
FlagOptions
// Default is the default value as a string (e.g., "8080").
Default string
// Value is a pointer to the variable that will store the flag value.
Value *int
}
IntVarOptions describes the configuration for adding an int flag. This struct implements FlagOption, so it can be used alongside functional options.
Example:
var port int
// Struct-based (primary API)
cmd.Flags.IntVar(clix.IntVarOptions{
FlagOptions: clix.FlagOptions{
Name: "port",
Usage: "Server port",
},
Default: "8080",
Value: &port,
})
// Functional options
cmd.Flags.IntVar(
WithFlagName("port"),
WithFlagUsage("Server port"),
WithIntegerValue(&port),
WithIntegerDefault("8080"),
)
func (IntVarOptions) ApplyFlag ¶
func (o IntVarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so IntVarOptions can be used directly.
func (*IntVarOptions) SetDefault ¶
func (o *IntVarOptions) SetDefault(defaultValue string) *IntVarOptions
SetDefault sets the default value and returns the options for method chaining.
func (*IntVarOptions) SetEnvVar ¶
func (o *IntVarOptions) SetEnvVar(envVar string) *IntVarOptions
SetEnvVar sets the environment variable name and returns the options for method chaining.
func (*IntVarOptions) SetName ¶
func (o *IntVarOptions) SetName(name string) *IntVarOptions
SetName sets the flag name and returns the options for method chaining.
func (*IntVarOptions) SetShort ¶
func (o *IntVarOptions) SetShort(short string) *IntVarOptions
SetShort sets the flag shorthand and returns the options for method chaining.
func (*IntVarOptions) SetUsage ¶
func (o *IntVarOptions) SetUsage(usage string) *IntVarOptions
SetUsage sets the flag usage text and returns the options for method chaining.
func (*IntVarOptions) SetValue ¶
func (o *IntVarOptions) SetValue(value *int) *IntVarOptions
SetValue sets the value pointer and returns the options for method chaining.
type PromptButtonStyles ¶
type PromptButtonStyles struct {
// Active styles active button hints.
Active TextStyle
// Inactive styles inactive/grayed-out button hints.
Inactive TextStyle
// Hover styles hovered button hints.
Hover TextStyle
}
PromptButtonStyles groups button hint styles together for easier configuration. These styles are used for keyboard shortcut hints in prompts.
type PromptCommand ¶
type PromptCommand struct {
Type PromptCommandType
FunctionKey int
}
PromptCommand describes a high-level command initiated by the user. For function keys, FunctionKey contains the key index (1-12).
type PromptCommandAction ¶
type PromptCommandAction struct {
// Handled indicates the command was consumed and default handling should be skipped.
Handled bool
// Exit requests the prompter to exit immediately.
// If ExitErr is non-nil it will be returned from the prompt.
Exit bool
// ExitErr is returned from the prompt when Exit is true.
ExitErr error
}
PromptCommandAction instructs the prompter how to proceed after a command is handled.
type PromptCommandContext ¶
type PromptCommandContext struct {
PromptKeyState
SetInput func(string)
}
PromptCommandContext provides the handler context when a key binding is invoked.
type PromptCommandHandler ¶
type PromptCommandHandler func(PromptCommandContext) PromptCommandAction
PromptCommandHandler processes special key commands during an interactive prompt. Returning an action with Exit=true stops the prompt immediately.
type PromptCommandType ¶
type PromptCommandType int
PromptCommandType identifies a special key command intercepted by interactive prompts.
const ( // PromptCommandUnknown represents an unclassified key. PromptCommandUnknown PromptCommandType = iota // PromptCommandEscape indicates the escape key was pressed. PromptCommandEscape // PromptCommandTab indicates the tab key was pressed. PromptCommandTab // PromptCommandFunction indicates an F-key (F1-F12) was pressed. PromptCommandFunction // PromptCommandEnter indicates the enter key was pressed. PromptCommandEnter )
type PromptConfig ¶
type PromptConfig struct {
Label string
Default string
NoDefaultPlaceholder string
Validate func(string) error
Theme PromptTheme
Options []SelectOption
MultiSelect bool
Confirm bool
ContinueText string
CommandHandler PromptCommandHandler
KeyMap PromptKeyMap
}
PromptConfig holds all prompt configuration internally. Exported so extension packages can implement PromptOption.
type PromptKeyBinding ¶
type PromptKeyBinding struct {
Command PromptCommand
Description string
Handler PromptCommandHandler
Active func(PromptKeyState) bool
}
PromptKeyBinding maps a command to display metadata and optional handling.
type PromptKeyMap ¶
type PromptKeyMap struct {
Bindings []PromptKeyBinding
}
PromptKeyMap holds the configured key bindings for a prompt.
func (PromptKeyMap) BindingFor ¶
func (m PromptKeyMap) BindingFor(cmd PromptCommand) (PromptKeyBinding, bool)
BindingFor returns the configured binding for the given command, if any.
type PromptKeyState ¶
type PromptKeyState struct {
Command PromptCommand
Input string
Default string
Suggestion string
}
PromptKeyState describes the prompt state when evaluating key bindings.
type PromptOption ¶
type PromptOption interface {
// Apply configures the prompt config.
// Exported so extension packages can implement PromptOption.
Apply(*PromptConfig)
}
PromptOption configures a prompt using the functional options pattern. Options can be used to build prompts:
// Basic text prompt
prompter.Prompt(ctx, WithLabel("Name"), WithDefault("unknown"))
// Advanced prompts (require prompt extension):
// prompter.Prompt(ctx, WithLabel("Choose"), Select([]SelectOption{...}))
func WithCommandHandler ¶
func WithCommandHandler(handler PromptCommandHandler) PromptOption
WithCommandHandler registers a handler for special key commands during prompts. Command handlers can intercept escape, tab, function keys, and enter to provide custom behavior (e.g., autocomplete, help, cancellation).
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Enter value"),
clix.WithCommandHandler(func(ctx clix.PromptCommandContext) clix.PromptCommandAction {
if ctx.Command.Type == clix.PromptCommandEscape {
return clix.PromptCommandAction{Exit: true, ExitErr: errors.New("cancelled")}
}
return clix.PromptCommandAction{Handled: false}
}),
)
func WithConfirm ¶
func WithConfirm() PromptOption
WithConfirm enables yes/no confirmation prompt mode (functional option). Works with TextPrompter - it's just a text prompt with y/n validation. Returns "y" or "n" (or "yes"/"no").
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Continue?"),
clix.WithConfirm(),
)
if result == "y" {
// User confirmed
}
func WithDefault ¶
func WithDefault(def string) PromptOption
WithDefault sets the default value (functional option). The default is shown in the prompt and used if the user presses Enter without input.
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Color"),
clix.WithDefault("blue"),
)
func WithKeyMap ¶
func WithKeyMap(m PromptKeyMap) PromptOption
WithKeyMap configures the key bindings shown and invoked by the prompt. Key maps allow you to define keyboard shortcuts with descriptions and handlers.
Example:
keyMap := clix.PromptKeyMap{
Bindings: []clix.PromptKeyBinding{
{
Command: clix.PromptCommand{Type: clix.PromptCommandEscape},
Description: "Cancel",
Handler: func(ctx clix.PromptCommandContext) clix.PromptCommandAction {
return clix.PromptCommandAction{Exit: true}
},
},
},
}
result, err := prompter.Prompt(ctx,
clix.WithLabel("Enter value"),
clix.WithKeyMap(keyMap),
)
func WithLabel ¶
func WithLabel(label string) PromptOption
WithLabel sets the prompt label (functional option).
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Enter your name"),
)
Example ¶
ExampleWithLabel demonstrates how to use the functional options API for prompts.
package main
import (
"fmt"
"strings"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand(app.Name)
app.Root = root
root.Run = func(ctx *clix.Context) error {
// Basic text prompt using functional options
name, err := ctx.App.Prompter.Prompt(ctx,
clix.WithLabel("Enter your name"),
clix.WithDefault("Anonymous"),
)
if err != nil {
return err
}
// Prompt with validation using functional options
email, err := ctx.App.Prompter.Prompt(ctx,
clix.WithLabel("Enter your email"),
clix.WithValidate(func(value string) error {
if !strings.Contains(value, "@") {
return fmt.Errorf("invalid email address")
}
return nil
}),
)
if err != nil {
return err
}
// Confirm prompt using functional options
confirmed, err := ctx.App.Prompter.Prompt(ctx,
clix.WithLabel("Continue?"),
clix.WithConfirm(),
)
if err != nil {
return err
}
if confirmed == "yes" {
fmt.Fprintf(ctx.App.Out, "Hello %s (%s)!\n", name, email)
}
return nil
}
}
func WithNoDefaultPlaceholder ¶
func WithNoDefaultPlaceholder(text string) PromptOption
WithNoDefaultPlaceholder sets the placeholder text shown when no default exists. This is typically used by higher-level workflows (like surveys) to prompt the user that pressing enter will keep their existing value.
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Enter value"),
clix.WithNoDefaultPlaceholder("(press Enter to keep current value)"),
)
func WithTheme ¶
func WithTheme(theme PromptTheme) PromptOption
WithTheme sets the prompt theme (functional option). Themes control the visual appearance of prompts (prefix, hint, error indicators, styling). If not set, uses app.DefaultTheme.
Example:
theme := clix.PromptTheme{
Prefix: "> ",
Error: "✗ ",
}
result, err := prompter.Prompt(ctx,
clix.WithLabel("Name"),
clix.WithTheme(theme),
)
func WithValidate ¶
func WithValidate(validate func(string) error) PromptOption
WithValidate sets the validation function (functional option). The validation function is called when the user submits input. Return an error if the value is invalid; the prompt will re-prompt until valid.
Example:
result, err := prompter.Prompt(ctx,
clix.WithLabel("Enter email"),
clix.WithValidate(func(value string) error {
if !strings.Contains(value, "@") {
return errors.New("invalid email address")
}
return nil
}),
)
type PromptRequest ¶
type PromptRequest struct {
// Label is the prompt text shown to the user.
Label string
// Default is the default value shown in the prompt.
// For text prompts, this appears as placeholder text.
Default string
// NoDefaultPlaceholder is custom placeholder text when Default is empty.
NoDefaultPlaceholder string
// Validate is an optional validation function called when the user submits input.
// Return an error if the value is invalid.
Validate func(string) error
// Theme configures the styling for this prompt.
// If not set, uses app.DefaultTheme.
Theme PromptTheme
// Options are the choices for select/multi-select prompts.
// Requires the prompt extension for advanced prompt types.
Options []SelectOption
// MultiSelect enables multi-select mode (user can choose multiple options).
// Requires the prompt extension.
MultiSelect bool
// Confirm enables confirm mode (yes/no prompt).
// Returns "y" or "n" (or "yes"/"no").
Confirm bool
// ContinueText is the text shown for the continue button in select prompts.
ContinueText string
// CommandHandler allows custom command handling during prompts.
// Users can type commands that are processed by this handler.
CommandHandler PromptCommandHandler
// KeyMap configures keyboard shortcuts for the prompt.
KeyMap PromptKeyMap
}
PromptRequest is the struct-based API for prompts, consistent with the rest of the codebase. This is the primary API - functional options are a convenience layer.
Example:
// Basic text prompt
result, err := app.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Name",
Default: "unknown",
Validate: validation.NotEmpty,
})
// Select prompt (requires prompt extension)
result, err := app.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Choose an option",
Options: []clix.SelectOption{
{Label: "Option A", Value: "a"},
{Label: "Option B", Value: "b"},
},
})
// Confirm prompt
result, err := app.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Continue?",
Confirm: true,
})
Example ¶
ExamplePromptRequest demonstrates how to use the struct-based prompt API.
package main
import (
"fmt"
"strings"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
root.Run = func(ctx *clix.Context) error {
// Basic text prompt
name, err := ctx.App.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Enter your name",
Default: "Anonymous",
})
if err != nil {
return err
}
// Prompt with validation
email, err := ctx.App.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Enter your email",
Validate: func(value string) error {
if !strings.Contains(value, "@") {
return fmt.Errorf("invalid email address")
}
return nil
},
})
if err != nil {
return err
}
// Confirm prompt
confirmed, err := ctx.App.Prompter.Prompt(ctx, clix.PromptRequest{
Label: "Continue?",
Confirm: true,
})
if err != nil {
return err
}
if confirmed == "yes" {
fmt.Fprintf(ctx.App.Out, "Hello %s (%s)!\n", name, email)
}
return nil
}
}
func (PromptRequest) Apply ¶
func (r PromptRequest) Apply(cfg *PromptConfig)
Apply implements PromptOption so PromptRequest can be used directly.
func (*PromptRequest) SetCommandHandler ¶
func (r *PromptRequest) SetCommandHandler(handler PromptCommandHandler) *PromptRequest
SetCommandHandler sets the command handler and returns the request for method chaining.
func (*PromptRequest) SetConfirm ¶
func (r *PromptRequest) SetConfirm(confirm bool) *PromptRequest
SetConfirm enables confirm mode and returns the request for method chaining.
func (*PromptRequest) SetContinueText ¶
func (r *PromptRequest) SetContinueText(text string) *PromptRequest
SetContinueText sets the continue text and returns the request for method chaining.
func (*PromptRequest) SetDefault ¶
func (r *PromptRequest) SetDefault(defaultValue string) *PromptRequest
SetDefault sets the prompt default value and returns the request for method chaining.
func (*PromptRequest) SetKeyMap ¶
func (r *PromptRequest) SetKeyMap(keyMap PromptKeyMap) *PromptRequest
SetKeyMap sets the key map and returns the request for method chaining.
func (*PromptRequest) SetLabel ¶
func (r *PromptRequest) SetLabel(label string) *PromptRequest
SetLabel sets the prompt label and returns the request for method chaining.
func (*PromptRequest) SetMultiSelect ¶
func (r *PromptRequest) SetMultiSelect(multiSelect bool) *PromptRequest
SetMultiSelect enables multi-select mode and returns the request for method chaining.
func (*PromptRequest) SetNoDefaultPlaceholder ¶
func (r *PromptRequest) SetNoDefaultPlaceholder(placeholder string) *PromptRequest
SetNoDefaultPlaceholder sets the no-default placeholder and returns the request for method chaining.
func (*PromptRequest) SetOptions ¶
func (r *PromptRequest) SetOptions(options ...SelectOption) *PromptRequest
SetOptions sets the prompt options and returns the request for method chaining.
func (*PromptRequest) SetTheme ¶
func (r *PromptRequest) SetTheme(theme PromptTheme) *PromptRequest
SetTheme sets the prompt theme and returns the request for method chaining.
func (*PromptRequest) SetValidate ¶
func (r *PromptRequest) SetValidate(validate func(string) error) *PromptRequest
SetValidate sets the validation function and returns the request for method chaining.
type PromptTheme ¶
type PromptTheme struct {
// Prefix is the text shown before the prompt label (e.g., "? ", "> ").
Prefix string
// Hint is the text shown as a hint below the prompt (e.g., "(optional)").
Hint string
// Error is the text shown before error messages (e.g., "! ", "✗ ").
Error string
// PrefixStyle styles the prefix text.
PrefixStyle TextStyle
// LabelStyle styles the prompt label text.
LabelStyle TextStyle
// HintStyle styles the hint text.
HintStyle TextStyle
// DefaultStyle styles the default value text.
DefaultStyle TextStyle
// PlaceholderStyle styles placeholder/default text (e.g., bracketed defaults).
PlaceholderStyle TextStyle
// SuggestionStyle styles inline suggestion/ghost text.
SuggestionStyle TextStyle
// ErrorStyle styles error messages.
ErrorStyle TextStyle
// ButtonActiveStyle styles active button hints.
ButtonActiveStyle TextStyle
// ButtonInactiveStyle styles inactive/grayed-out button hints.
ButtonInactiveStyle TextStyle
// ButtonHoverStyle styles hovered button hints.
ButtonHoverStyle TextStyle
// Buttons groups button hint styles together for easier configuration.
Buttons PromptButtonStyles
}
PromptTheme configures the visual appearance of prompts. Themes control the prefix, hint, error indicators, and styling for all prompt elements.
Example:
theme := clix.PromptTheme{
Prefix: "> ",
Hint: "(press Enter to confirm)",
Error: "✗ ",
LabelStyle: lipgloss.NewStyle().Bold(true),
ErrorStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("9")),
}
result, err := prompter.Prompt(ctx, clix.PromptRequest{
Label: "Name",
Theme: theme,
})
type Prompter ¶
type Prompter interface {
Prompt(ctx context.Context, opts ...PromptOption) (string, error)
}
Prompter encapsulates interactive prompting. Accepts either functional options or a PromptRequest struct:
// Struct-based (primary API, consistent with rest of codebase)
prompter.Prompt(ctx, PromptRequest{Label: "Name", Default: "unknown"})
// Functional options (convenience layer)
prompter.Prompt(ctx, WithLabel("Name"), WithDefault("unknown"))
type SelectOption ¶
type SelectOption struct {
// Label is the text displayed to the user for this option.
Label string
// Value is the value returned when this option is selected.
Value string
// Description is optional additional text shown below the label.
Description string
}
SelectOption represents a choice in a select or multi-select prompt.
Example:
result, err := prompter.Prompt(ctx, clix.PromptRequest{
Label: "Choose an option",
Options: []clix.SelectOption{
{Label: "Option A", Value: "a", Description: "First option"},
{Label: "Option B", Value: "b", Description: "Second option"},
},
})
type StringValue ¶
type StringValue struct {
// contains filtered or unexported fields
}
StringValue implements Value for string flags.
func (*StringValue) Set ¶
func (s *StringValue) Set(value string) error
func (*StringValue) String ¶
func (s *StringValue) String() string
type StringVarOptions ¶
type StringVarOptions struct {
FlagOptions
// Default is the default value if the flag is not provided.
Default string
// Value is a pointer to the variable that will store the flag value.
Value *string
}
StringVarOptions describes the configuration for adding a string flag. This struct implements FlagOption, so it can be used alongside functional options.
Example - three API styles:
var project string
// 1. Struct-based (primary API)
app.Flags().StringVar(clix.StringVarOptions{
FlagOptions: clix.FlagOptions{
Name: "project",
Short: "p",
Usage: "Project to operate on",
EnvVar: "MYAPP_PROJECT",
},
Default: "default-project",
Value: &project,
})
// 2. Functional options
app.Flags().StringVar(
clix.WithFlagName("project"),
clix.WithFlagShort("p"),
clix.WithFlagUsage("Project to operate on"),
clix.WithFlagEnvVar("MYAPP_PROJECT"),
clix.WithStringValue(&project),
clix.WithStringDefault("default-project"),
)
// 3. Mixed (struct + functional options)
app.Flags().StringVar(
clix.StringVarOptions{Value: &project},
clix.WithFlagName("project"),
clix.WithFlagShort("p"),
)
func (StringVarOptions) ApplyFlag ¶
func (o StringVarOptions) ApplyFlag(fo *FlagOptions)
ApplyFlag implements FlagOption so StringVarOptions can be used directly.
func (*StringVarOptions) SetDefault ¶
func (o *StringVarOptions) SetDefault(defaultValue string) *StringVarOptions
SetDefault sets the default value and returns the options for method chaining.
func (*StringVarOptions) SetEnvVar ¶
func (o *StringVarOptions) SetEnvVar(envVar string) *StringVarOptions
SetEnvVar sets the environment variable name and returns the options for method chaining.
func (*StringVarOptions) SetName ¶
func (o *StringVarOptions) SetName(name string) *StringVarOptions
SetName sets the flag name and returns the options for method chaining.
func (*StringVarOptions) SetShort ¶
func (o *StringVarOptions) SetShort(short string) *StringVarOptions
SetShort sets the flag shorthand and returns the options for method chaining.
func (*StringVarOptions) SetUsage ¶
func (o *StringVarOptions) SetUsage(usage string) *StringVarOptions
SetUsage sets the flag usage text and returns the options for method chaining.
func (*StringVarOptions) SetValue ¶
func (o *StringVarOptions) SetValue(value *string) *StringVarOptions
SetValue sets the value pointer and returns the options for method chaining.
type StyleFunc ¶
StyleFunc adapts a plain function into a TextStyle. For compatibility with lipgloss.Style, the function accepts variadic strings. When called with a single string, it behaves as expected.
Example ¶
ExampleStyleFunc demonstrates how to use styling with lipgloss compatibility.
package main
import (
"fmt"
"github.com/SCKelemen/clix"
)
func main() {
app := clix.NewApp("myapp")
root := clix.NewCommand("myapp")
app.Root = root
// Create a simple style function
style := clix.StyleFunc(func(strs ...string) string {
if len(strs) == 0 {
return ""
}
return fmt.Sprintf(">>> %s <<<", strs[0])
})
// Apply to app styles
app.Styles.SectionHeading = style
app.Styles.CommandTitle = style
// StyleFunc is compatible with lipgloss.Style
// You can use lipgloss styles directly:
// import "github.com/charmbracelet/lipgloss"
// lipglossStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
// app.Styles.SectionHeading = clix.StyleFunc(lipglossStyle.Render)
}
type StyleOption ¶
type StyleOption interface {
ApplyStyle(*Styles)
}
StyleOption configures Styles using the functional options pattern.
func WithAppFlagName ¶
func WithAppFlagName(style TextStyle) StyleOption
WithAppFlagName sets the app-level flag name style.
func WithAppFlagUsage ¶
func WithAppFlagUsage(style TextStyle) StyleOption
WithAppFlagUsage sets the app-level flag usage style.
func WithAppTitle ¶
func WithAppTitle(style TextStyle) StyleOption
WithAppTitle sets the app title style.
func WithArgumentMarker ¶
func WithArgumentMarker(style TextStyle) StyleOption
WithArgumentMarker sets the argument marker style.
func WithArgumentName ¶
func WithArgumentName(style TextStyle) StyleOption
WithArgumentName sets the argument name style.
func WithChildDesc ¶
func WithChildDesc(style TextStyle) StyleOption
WithChildDesc sets the child description style.
func WithChildName ¶
func WithChildName(style TextStyle) StyleOption
WithChildName sets the child name style.
func WithCommandFlagName ¶
func WithCommandFlagName(style TextStyle) StyleOption
WithCommandFlagName sets the command-level flag name style.
func WithCommandFlagUsage ¶
func WithCommandFlagUsage(style TextStyle) StyleOption
WithCommandFlagUsage sets the command-level flag usage style.
func WithCommandTitle ¶
func WithCommandTitle(style TextStyle) StyleOption
WithCommandTitle sets the command title style.
func WithExample ¶
func WithExample(style TextStyle) StyleOption
WithExample sets the example style.
func WithSectionHeading ¶
func WithSectionHeading(style TextStyle) StyleOption
WithSectionHeading sets the section heading style.
func WithStyleAppDescription ¶
func WithStyleAppDescription(style TextStyle) StyleOption
WithStyleAppDescription sets the app description style.
func WithStyleFlagName ¶
func WithStyleFlagName(style TextStyle) StyleOption
WithStyleFlagName sets the flag name style (default for both app and command flags).
func WithStyleFlagUsage ¶
func WithStyleFlagUsage(style TextStyle) StyleOption
WithStyleFlagUsage sets the flag usage style (default for both app and command flags).
type Styles ¶
type Styles struct {
// AppTitle styles the application title in help output.
AppTitle TextStyle
// AppDescription styles the application description in help output.
AppDescription TextStyle
// CommandTitle styles command names in help output.
CommandTitle TextStyle
// SectionHeading styles section headings (e.g., "FLAGS", "ARGUMENTS") in help output.
SectionHeading TextStyle
// Usage styles usage strings in help output.
Usage TextStyle
// FlagName styles flag names (e.g., "--project") in help output.
// Used as the default for both global and local flag names.
FlagName TextStyle
// FlagUsage styles flag usage text in help output.
// Used as the default for both global and local flag usage.
FlagUsage TextStyle
// AppFlagName styles app-level flag names (root command flags shown everywhere).
// Falls back to FlagName when unset.
AppFlagName TextStyle
// AppFlagUsage styles app-level flag usage text.
// Falls back to FlagUsage when unset.
AppFlagUsage TextStyle
// CommandFlagName styles command-level flag names.
// Falls back to FlagName when unset.
CommandFlagName TextStyle
// CommandFlagUsage styles command-level flag usage text.
// Falls back to FlagUsage when unset.
CommandFlagUsage TextStyle
// ArgumentName styles argument names in help output.
ArgumentName TextStyle
// ArgumentMarker styles argument markers (e.g., "<name>", "[name]") in help output.
ArgumentMarker TextStyle
// ChildName styles child command and group names in help output.
// Used for both groups and commands in the GROUPS and COMMANDS sections.
ChildName TextStyle
// ChildDesc styles child command and group descriptions in help output.
// Used for both groups and commands in the GROUPS and COMMANDS sections.
ChildDesc TextStyle
// Example styles example text in help output.
Example TextStyle
}
Styles defines styling hooks for textual CLI output such as help screens. All fields are optional - unset styles produce plain text output. Styles are compatible with lipgloss and can use any TextStyle implementation.
Example:
app.Styles = clix.Styles{
AppTitle: lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("63")),
CommandTitle: lipgloss.NewStyle().Bold(true),
FlagName: lipgloss.NewStyle().Foreground(lipgloss.Color("205")),
}
func (*Styles) SetAppDescription ¶
SetAppDescription sets the app description style and returns the styles for method chaining.
func (*Styles) SetAppFlagName ¶
SetAppFlagName sets the app-level flag name style and returns the styles for method chaining.
func (*Styles) SetAppFlagUsage ¶
SetAppFlagUsage sets the app-level flag usage style and returns the styles for method chaining.
func (*Styles) SetAppTitle ¶
SetAppTitle sets the app title style and returns the styles for method chaining.
func (*Styles) SetArgumentMarker ¶
SetArgumentMarker sets the argument marker style and returns the styles for method chaining.
func (*Styles) SetArgumentName ¶
SetArgumentName sets the argument name style and returns the styles for method chaining.
func (*Styles) SetChildDesc ¶
SetChildDesc sets the child description style and returns the styles for method chaining.
func (*Styles) SetChildName ¶
SetChildName sets the child name style and returns the styles for method chaining.
func (*Styles) SetCommandFlagName ¶
SetCommandFlagName sets the command-level flag name style and returns the styles for method chaining.
func (*Styles) SetCommandFlagUsage ¶
SetCommandFlagUsage sets the command-level flag usage style and returns the styles for method chaining.
func (*Styles) SetCommandTitle ¶
SetCommandTitle sets the command title style and returns the styles for method chaining.
func (*Styles) SetExample ¶
SetExample sets the example style and returns the styles for method chaining.
func (*Styles) SetFlagName ¶
SetFlagName sets the flag name style and returns the styles for method chaining.
func (*Styles) SetFlagUsage ¶
SetFlagUsage sets the flag usage style and returns the styles for method chaining.
func (*Styles) SetSectionHeading ¶
SetSectionHeading sets the section heading style and returns the styles for method chaining.
type TextPromptOption ¶
type TextPromptOption func(*PromptConfig)
TextPromptOption implements PromptOption for basic text prompts. These options work with all prompters.
func (TextPromptOption) Apply ¶
func (o TextPromptOption) Apply(cfg *PromptConfig)
type TextPrompter ¶
type TextPrompter struct {
// In is the reader for user input (typically os.Stdin).
In io.Reader
// Out is the writer for prompt output (typically os.Stdout).
Out io.Writer
}
TextPrompter implements Prompter for basic text input only. This is the default prompter in core - it only handles text prompts. Advanced prompt options (Select, MultiSelect, Confirm) are rejected at runtime with clear error messages directing users to the prompt extension. TextPrompter is the default prompt implementation. It supports basic text input and confirm prompts. For advanced prompts (select, multi-select), use the prompt extension which provides TerminalPrompter.
Example:
app.Prompter = clix.TextPrompter{
In: os.Stdin,
Out: os.Stdout,
}
func (TextPrompter) Prompt ¶
func (p TextPrompter) Prompt(ctx context.Context, opts ...PromptOption) (string, error)
Prompt displays a text prompt and reads the user's response. Accepts both struct-based PromptRequest and functional options for flexibility. Advanced prompt options (Select, MultiSelect) are rejected - use the prompt extension for those.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic/cmd/demo
command
|
|
|
gcloud/cmd/gcloud
command
|
|
|
gh/cmd/gh
command
|
|
|
ext
|
|