warg

package module
v0.0.38 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2025 License: MIT Imports: 26 Imported by: 8

README

warg

An opinionated CLI framework:

  • declarative nested commands
  • detailed, colored --help output (including what a flag is currently set to)
  • update flags from os.Args, config files, environment variables, and app defaults
  • extend with new flag types, config file formats, or --help output
  • snapshot testing support

Project Status (2025-06-15)

warg is still a work in progress, but the "bones" are where I want them - I don't intend to change the basic way warg works, but I do plan to experiment with a few APIs (make the value and config APIs simpler), and add TUI generation. I think the largest breaking changes are behind me (see the CHANGELOG). Read Go Project Notes to help understand the tooling.

I'm watching issues; please open one for any questions and especially BEFORE submitting a Pull request.

Examples

All of the CLIs on my profile use warg.

See API docs (including code examples) at pkg.go.dev

Simple "butler" example (full source here):

app := warg.New(
  "butler",
  "v1.0.0",
  warg.NewSection(
    "A virtual assistant",
    warg.NewSubCmd(
      "present",
      "Formally present a guest (guests are never introduced, always presented).",
      present,
      warg.NewCmdFlag(
        "--name",
        "Guest to address.",
        scalar.String(),
        warg.Alias("-n"),
        warg.EnvVars("BUTLER_PRESENT_NAME", "USER"),
        warg.Required(),
      ),
    ),
  ),
)

Butler help screenshot

When to avoid warg

By design, warg apps have the following requirements:

  • must contain at least one subcommand. This makes it easy to add further subcommands, such as a version subcommand. It is not possible to design a warg app such that calling <appname> --flag <value> does useful work. Instead, <appname> <command> --flag <value> must be used.
  • warg does not support positional arguments. Instead, use a required flag: git clone <url> would be git clone --url <url>. This makes parsing much easier, and I like the simplicity of it, even though it's more to type/tab-complete.

Alternatives

  • cobra is by far the most popular CLI framework for Go.
  • cli is also very popular.
  • I haven't tried ff, but it looks similar to warg, though less batteries-included
  • I've used the now unmaintained kingpin fairly successfully.

Notes

See Go Project Notes for notes on development tooling.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConditionallyEnableColor added in v0.0.35

func ConditionallyEnableColor(pf PassedFlags, file *os.File) (gocolor.Color, error)

ConditionallyEnableColor looks for a passed --color flag with an underlying string value. If it exists and is set to "true", or if it exists, is set to "auto", and the passed file is a TTY, an enabled Color is returned.

func FindVersion added in v0.0.34

func FindVersion(version string) string

FindVersion returns the version of the app. If the version is already set (eg. via a build flag), it returns that. Otherwise, it tries to read the go module version from the runtime info, or returns "unknown" if that fails. This is called automatically when passing an empty string to New, but can also be used if you need the version independently of the app creation.

func GoldenTest added in v0.0.18

func GoldenTest(
	t *testing.T,
	args GoldenTestArgs,
	parseOpts ...ParseOpt)

GoldenTest runs the app and and captures stdout and stderr into files. If those differ than previously captured stdout/stderr, t.Fatalf will be called.

Passed `parseOpts` should not include OverrideStderr/OverrideStdout as GoldenTest overwrites those

Types

type Action added in v0.0.35

type Action func(CmdContext) error

An Action is run as the result of a command

func Unimplemented added in v0.0.36

func Unimplemented() Action

Unimplemented() is an Action that simply returns an error. Useful for prototyping

type App

type App struct {
	// Config
	ConfigFlagName  string
	NewConfigReader config.NewReader

	// Help
	HelpFlagName string
	HelpCmds     CmdMap

	GlobalFlags         FlagMap
	Name                string
	RootSection         Section
	SkipGlobalColorFlag bool
	SkipCompletionCmds  bool
	SkipValidation      bool
	SkipVersionCmd      bool
	SkipREPLCmd         bool
	Version             string
}

An App contains your defined sections, commands, and flags Create a new App with New()

func New

func New(name string, version string, rootSection Section, opts ...AppOpt) App

New creates a warg app. name is used for help output only (though generally it should match the name of the compiled binary). version is the app version - if empty, warg will attempt to set it to the go module version, or "unknown" if that fails.

Example
package main

import (
	"fmt"
	"os"

	"go.bbkane.com/warg"
	"go.bbkane.com/warg/value/scalar"
)

func login(ctx warg.CmdContext) error {
	url := ctx.Flags["--url"].(string)

	// timeout doesn't have a default value,
	// so we can't rely on it being passed.
	timeout, exists := ctx.Flags["--timeout"]
	if exists {
		timeout := timeout.(int)
		fmt.Printf("Logging into %s with timeout %d\n", url, timeout)
		return nil
	}

	fmt.Printf("Logging into %s\n", url)
	return nil
}

func main() {
	commonFlags := warg.FlagMap{
		"--timeout": warg.NewFlag(
			"Optional timeout. Defaults to no timeout",
			scalar.Int(),
		),
		"--url": warg.NewFlag(
			"URL of the blog",
			scalar.String(
				scalar.Default("https://www.myblog.com"),
			),
			warg.EnvVars("BLOG_URL"),
		),
	}
	app := warg.New(
		"newAppName",
		"v1.0.0",
		warg.NewSection(
			"work with a fictional blog platform",
			warg.NewSubCmd(
				"login",
				"Login to the platform",
				login,
				warg.CmdFlagMap(commonFlags),
			),
			warg.NewSubSection(
				"comments",
				"Deal with comments",
				warg.NewSubCmd(
					"list",
					"List all comments",
					// still prototyping how we want this
					// command to look,
					// so use a provided stub action
					warg.Unimplemented(),
					warg.CmdFlagMap(commonFlags),
				),
			),
		),
	)

	// normally we would rely on the user to set the environment variable,
	// bu this is an example
	err := os.Setenv("BLOG_URL", "https://envvar.com")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	app.MustRun(warg.ParseWithArgs([]string{"blog.exe", "login"}))
}
Output:

Logging into https://envvar.com

func (*App) Completions added in v0.0.35

func (a *App) Completions(opts ...ParseOpt) (*completion.Candidates, error)

Completions returns completion candidates for the app for shell completion. It parses as much as it can.

func (*App) MustRun

func (app *App) MustRun(opts ...ParseOpt)

MustRun runs the app. Any flag parsing errors will be printed to stderr and os.Exit(64) (EX_USAGE) will be called. Any errors on an Action will be printed to stderr and os.Exit(1) will be called.

func (*App) Parse

func (app *App) Parse(opts ...ParseOpt) (*ParseResult, error)

Parse parses command line arguments, environment variables, and configuration files to produce a ParseResult. expects ParseOpts.Args to be like os.Args (i.e., first arg is app name). It returns an error if parsing fails or required flags are missing.

Example (Flag_value_options)

ExampleApp_Parse_flag_value_options shows a couple combinations of flag/value options. It's also possible to use '--help detailed' to see the current value of a flag and what set it.

package main

import (
	"fmt"
	"log"
	"os"

	"go.bbkane.com/warg"
	"go.bbkane.com/warg/config/yamlreader"
	"go.bbkane.com/warg/path"
	"go.bbkane.com/warg/value/scalar"
	"go.bbkane.com/warg/value/slice"
)

func main() {

	action := func(ctx warg.CmdContext) error {
		// flag marked as Required(), so no need to check for existance
		scalarVal := ctx.Flags["--scalar-flag"].(string)
		// flag might not exist in config, so check for existance
		// TODO: does this panic on nil?
		sliceVal, sliceValExists := ctx.Flags["--slice-flag"].([]int)

		fmt.Printf("--scalar-flag: %#v\n", scalarVal)
		if sliceValExists {
			fmt.Printf("--slice-flag: %#v\n", sliceVal)
		} else {
			fmt.Printf("--slice-flag value not filled!\n")
		}
		return nil
	}

	app := warg.New(
		"flag-overrides",
		"v1.0.0",
		warg.NewSection(
			"demo flag overrides",
			warg.NewSubCmd(
				string("show"),
				"Show final flag values",
				action,
				warg.NewCmdFlag(
					"--scalar-flag",
					"Demo scalar flag",
					scalar.String(
						scalar.Choices("a", "b"),
						scalar.Default("a"),
					),
					warg.ConfigPath("args.scalar-flag"),
					warg.Required(),
				),
				warg.NewCmdFlag(
					"--slice-flag",
					"Demo slice flag",
					slice.Int(
						slice.Choices(1, 2, 3),
					),
					warg.Alias("-slice"),
					warg.ConfigPath("args.slice-flag"),
					warg.EnvVars("SLICE", "SLICE_ARG"),
				),
			),
		),
		warg.ConfigFlag(
			yamlreader.New,
			warg.FlagMap{
				"--config": warg.NewFlag(
					"Path to YAML config file",
					scalar.Path(
						scalar.Default(path.New("~/.config/flag-overrides.yaml")),
					),
					warg.Alias("-c"),
				),
			},
		),
	)

	err := os.WriteFile(
		"testdata/ExampleFlagValueOptions/config.yaml",
		[]byte(`args:
  slice-flag:
    - 1
    - 2
    - 3
`),
		0644,
	)
	if err != nil {
		log.Fatalf("write error: %e", err)
	}
	app.MustRun(
		warg.ParseWithArgs([]string{"calc", "show", "-c", "testdata/ExampleFlagValueOptions/config.yaml", "--scalar-flag", "b"}),
	)
}
Output:

--scalar-flag: "b"
--slice-flag: []int{1, 2, 3}

func (*App) Validate added in v0.0.13

func (app *App) Validate() error

Validate checks app for creation errors. It checks:

  • the help flag is the right type
  • Sections and commands don't start with "-" (needed for parsing)
  • Flag names and aliases do start with "-" (needed for parsing)
  • Flag names and aliases don't collide

type AppOpt

type AppOpt func(*App)

AppOpt let's you customize the app. Most AppOpts panic if incorrectly called

func ConfigFlag

func ConfigFlag(reader config.NewReader, flagMap FlagMap) AppOpt

ConfigFlag adds a flag that will be used to read a config file. If the passed flagMap is nil, DefaultConfigFlagMap will be used. The flag will be added to the app's global flags. When parsed, the config flag will be parsed before other flags, any config file found will be read, and any values found will be used to update other flags. This allows users to override flag defaults with values from a config file.

Example
package main

import (
	"fmt"
	"log"
	"os"

	"go.bbkane.com/warg"
	"go.bbkane.com/warg/config/yamlreader"
	"go.bbkane.com/warg/path"
	"go.bbkane.com/warg/value/scalar"
	"go.bbkane.com/warg/value/slice"
)

func exampleConfigFlagTextAdd(ctx warg.CmdContext) error {
	addends := ctx.Flags["--addend"].([]int)
	sum := 0
	for _, a := range addends {
		sum += a
	}
	fmt.Printf("Sum: %d\n", sum)
	return nil
}

func main() {
	app := warg.New(
		"newAppName",
		"v1.0.0",
		warg.NewSection(
			"do math",
			warg.NewSubCmd(
				string("add"),
				"add integers",
				exampleConfigFlagTextAdd,
				warg.NewCmdFlag(
					string("--addend"),
					"Integer to add. Flag is repeatible",
					slice.Int(),
					warg.ConfigPath("add.addends"),
					warg.Required(),
				),
			),
		),
		warg.ConfigFlag(
			yamlreader.New,
			warg.FlagMap{
				"--config": warg.NewFlag(
					"Path to YAML config file",
					scalar.Path(
						scalar.Default(path.New("~/.config/calc.yaml")),
					),
					warg.Alias("-c"),
				),
			},
		),
	)

	err := os.WriteFile(
		"testdata/ExampleConfigFlag/calc.yaml",
		[]byte(`add:
  addends:
    - 1
    - 2
    - 3
`),
		0644,
	)
	if err != nil {
		log.Fatalf("write error: %e", err)
	}
	app.MustRun(
		warg.ParseWithArgs([]string{"calc", "add", "-c", "testdata/ExampleConfigFlag/calc.yaml"}),
	)
}
Output:

Sum: 6

func GlobalFlag added in v0.0.24

func GlobalFlag(name string, value Flag) AppOpt

GlobalFlag adds an existing flag to a Cmd. It panics if a flag with the same name exists

func GlobalFlagMap added in v0.0.28

func GlobalFlagMap(flagMap FlagMap) AppOpt

GlobalFlagMap adds existing flags to a Cmd. It panics if a flag with the same name exists

func HelpFlag added in v0.0.30

func HelpFlag(helpCmds CmdMap, helpFlags FlagMap) AppOpt

HelpFlag customizes your help This option is only needed if you're also writing a custom help function. helpFlags be either `nil` to autogenerate or a flag map with one flat that with the followng properties:

  • scalar string type
  • choices that match the names in helpCommands
  • default value set to one of the choices

These properties are checked at runtime with app.Validate().

Example
package main

import (
	"fmt"

	"go.bbkane.com/warg"
)

func exampleHelpFlaglogin(_ warg.CmdContext) error {
	fmt.Println("Logging in")
	return nil
}

func customHelpCmd() warg.Cmd {
	return warg.NewCmd(
		"", // this command will be launched by the help flag, so users will never see the help
		func(ctx warg.CmdContext) error {
			file := ctx.Stdout
			fmt.Fprintln(file, "Custom help command output")
			return nil
		},
	)
}

func main() {

	// create a custom help command map by grabbing the default one
	// and adding our custom help command
	helpCommands := warg.DefaultHelpCmdMap()
	helpCommands["custom"] = customHelpCmd()

	app := warg.New(
		"newAppName",
		"v1.0.0",
		warg.NewSection(
			"work with a fictional blog platform",
			warg.NewSubCmd(
				"login",
				"Login to the platform",
				exampleHelpFlaglogin,
			),
		),
		warg.HelpFlag(
			helpCommands,
			nil,
		),
	)

	app.MustRun(warg.ParseWithArgs([]string{"blog.exe", "-h", "custom"}))
}
Output:

Custom help command output

func NewGlobalFlag added in v0.0.28

func NewGlobalFlag(name string, helpShort string, empty value.EmptyConstructor, opts ...FlagOpt) AppOpt

NewGlobalFlag adds a flag to the app. It panics if a flag with the same name exists

func SkipAll added in v0.0.34

func SkipAll() AppOpt

SkipAll skips adding:

  • the default completion commands (<app> completion)
  • the default color flag map (<app> --color)
  • the default version command map (<app> version)
  • the default validation checks

This is inteded for tests where you just want to assert against a minimal application

func SkipCompletionCmds added in v0.0.36

func SkipCompletionCmds() AppOpt

SkipCompletionCmds skips adding the default completion commands (<app> completion).

func SkipGlobalColorFlag added in v0.0.34

func SkipGlobalColorFlag() AppOpt

SkipColorFlag skips adding the default color flag map (<app> --color).

func SkipREPLCmd added in v0.0.38

func SkipREPLCmd() AppOpt

SkipREPLCmd skips adding the default REPL command (<app> repl). NOTE: this command is not as polished as the rest of warg. I hope to improve it over time.

func SkipValidation added in v0.0.13

func SkipValidation() AppOpt

SkipValidation skips (most of) the app's internal consistency checks when the app is created. If used, make sure to call app.Validate() in a test!

func SkipVersionCmd added in v0.0.36

func SkipVersionCmd() AppOpt

SkipVersionCmd skips adding the default version command (<app> version).

type Cmd added in v0.0.35

type Cmd struct {
	// Action to run when command is invoked
	Action Action

	// Parsed Flags
	Flags FlagMap

	// AllowForwardedArgs indicates whether or not extra args are allowed after flags and following `--`.
	// These args will be accessible in CmdContext.ForwardedArgs.
	AllowForwardedArgs bool

	// Footer is yet another optional longer description.
	Footer string

	// HelpLong is an optional longer description
	HelpLong string

	// HelpShort is a required one-line description
	HelpShort string
}

A Cmd will run code for you! The name of a Cmd should probably be a verb - add , edit, run, ... A Cmd should not be constructed directly. Use functions like NewCmd or NewSubCmd instead.

func NewCmd added in v0.0.35

func NewCmd(helpShort string, action Action, opts ...CmdOpt) Cmd

NewCmd builds a Cmd

type CmdContext added in v0.0.35

type CmdContext struct {
	App           *App
	Flags         PassedFlags
	ForwardedArgs []string

	ParseState *ParseState

	// Context to smuggle user-defined state (i.e., not flags) into an Action. I use this for mocks when testing
	Context context.Context

	Stderr *os.File
	Stdin  *os.File
	Stdout *os.File
}

CmdContext contains all information the app has parsed for the Cmd to pass to the Action.

type CmdMap added in v0.0.35

type CmdMap map[string]Cmd

A CmdMap contains strings to [Cmd]s.

func DefaultHelpCmdMap added in v0.0.36

func DefaultHelpCmdMap() CmdMap

func (CmdMap) Empty added in v0.0.35

func (fm CmdMap) Empty() bool

func (CmdMap) SortedNames added in v0.0.35

func (fm CmdMap) SortedNames() []string

type CmdOpt added in v0.0.35

type CmdOpt func(*Cmd)

A CmdOpt customizes a Cmd

func AllowForwardedArgs added in v0.0.37

func AllowForwardedArgs() CmdOpt

Allow forwarded args for a command. Useful for commands that wrap other commands.

Example app:

enventory exec --env prod -- go run .

func CmdFlag added in v0.0.35

func CmdFlag(name string, value Flag) CmdOpt

CmdFlag adds an existing flag to a Command. It panics if a flag with the same name exists

func CmdFlagMap added in v0.0.35

func CmdFlagMap(flagMap FlagMap) CmdOpt

CmdFlagMap adds existing flags to a Command. It panics if a flag with the same name exists

func CmdFooter added in v0.0.35

func CmdFooter(footer string) CmdOpt

CmdFooter adds an Help string to the command - useful from a help function

func CmdHelpLong added in v0.0.35

func CmdHelpLong(helpLong string) CmdOpt

CmdHelpLong adds an Help string to the command - useful from a help function

func NewCmdFlag added in v0.0.35

func NewCmdFlag(name string, helpShort string, empty value.EmptyConstructor, opts ...FlagOpt) CmdOpt

NewCmdFlag builds a flag and adds it to a Command. It panics if a flag with the same name exists

type CompletionsFunc added in v0.0.35

type CompletionsFunc func(CmdContext) (*completion.Candidates, error)

CompletionsFunc is a function that returns completion candidates for a flag. See warg.Completions[Type] for convenience functions to make this

func CompletionsDirectories added in v0.0.34

func CompletionsDirectories() CompletionsFunc

func CompletionsDirectoriesFiles added in v0.0.34

func CompletionsDirectoriesFiles() CompletionsFunc

func CompletionsNone added in v0.0.34

func CompletionsNone() CompletionsFunc

func CompletionsValues added in v0.0.34

func CompletionsValues(values []string) CompletionsFunc

func CompletionsValuesDescriptions added in v0.0.34

func CompletionsValuesDescriptions(values []completion.Candidate) CompletionsFunc

type Flag added in v0.0.35

type Flag struct {
	// Alias is an alternative name for a flag, usually shorter :)
	Alias string

	// Completions is a function that returns a list of completion candidates for this flag.
	// Note that some flags in the cli.Context Flags map may not be set, even if they're required.
	// TODO: get a comprehensive list of restrictions on the context.
	Completions CompletionsFunc

	// ConfigPath is the path from the config to the value the flag updates
	ConfigPath string

	// EmptyConstructor tells flag how to make a value
	EmptyValueConstructor value.EmptyConstructor

	// Envvars holds a list of environment variables to update this flag. Only the first one that exists will be used.
	EnvVars []string

	// HelpShort is a message for the user on how to use this flag
	HelpShort string

	// Required means the user MUST fill this flag
	Required bool

	// When UnsetSentinal is passed as a flag value, Value is reset and SetBy is set to ""
	UnsetSentinel *string
}

func NewFlag added in v0.0.35

func NewFlag(helpShort string, empty value.EmptyConstructor, opts ...FlagOpt) Flag

NewFlag creates a NewFlag with options!

type FlagMap added in v0.0.35

type FlagMap map[string]Flag

FlagMap holds flags - used by Commands and Sections

func DefaultHelpFlagMap added in v0.0.35

func DefaultHelpFlagMap(defaultChoice string, choices []string) FlagMap

func (FlagMap) AddFlag added in v0.0.35

func (fm FlagMap) AddFlag(name string, value Flag)

AddFlag adds a new flag and panics if it already exists

func (FlagMap) AddFlags added in v0.0.35

func (fm FlagMap) AddFlags(flagMap FlagMap)

AddFlags adds another FlagMap to this one and and panics if a flag name already exists

func (*FlagMap) SortedNames added in v0.0.35

func (fm *FlagMap) SortedNames() []string

type FlagOpt added in v0.0.35

type FlagOpt func(*Flag)

FlagOpt customizes a Flag on creation

func Alias added in v0.0.35

func Alias(alias string) FlagOpt

Alias is an alternative name for a flag, usually shorter :)

func ConfigPath added in v0.0.35

func ConfigPath(path string) FlagOpt

ConfigPath adds a configpath to a flag

func EnvVars added in v0.0.35

func EnvVars(name ...string) FlagOpt

EnvVars adds a list of environmental variables to search through to update this flag. The first one that exists will be used to update the flag. Further existing envvars will be ignored.

func FlagCompletions added in v0.0.35

func FlagCompletions(CompletionsFunc CompletionsFunc) FlagOpt

func Required added in v0.0.35

func Required() FlagOpt

Required means the user MUST fill this flag

func UnsetSentinel added in v0.0.35

func UnsetSentinel(name string) FlagOpt

UnsetSentinel is a bit of an advanced feature meant to allow overriding a default, config, or environmental value with a command line flag. When UnsetSentinel is passed as a flag value, Value is reset and SetBy is set to "". It it recommended to set `name` to "UNSET" for consistency among warg apps. Scalar example:

app --flag UNSET  // undoes anything that sets --flag

Slice example:

app --flag a --flag b --flag UNSET --flag c --flag d // ends up with []string{"c", "d"}

type GoldenTestArgs added in v0.0.23

type GoldenTestArgs struct {
	App *App

	// UpdateGolden files for captured stderr/stdout
	UpdateGolden bool

	// Whether the action should return an error
	ExpectActionErr bool
}

type LookupEnv added in v0.0.35

type LookupEnv func(key string) (string, bool)

Look up keys (meant for environment variable parsing) - fulfillable with os.LookupEnv or warg.LookupMap(map)

func LookupMap

func LookupMap(m map[string]string) LookupEnv

LookupMap loooks up keys from a provided map. Useful to mock os.LookupEnv when parsing

type ParseArgState added in v0.0.36

type ParseArgState string

ParseArgState represents the current "thing" we want from the args. It transitions as we parse each incoming argument and match it to the expected application structure

const (
	ParseArgState_WantSectionOrCmd  ParseArgState = "ParseArgState_WantSectionOrCmd"
	ParseArgState_WantFlagNameOrEnd ParseArgState = "ParseArgState_WantFlagNameOrEnd"
	ParseArgState_WantFlagValue     ParseArgState = "ParseArgState_WantFlagValue"
)

type ParseOpt added in v0.0.21

type ParseOpt func(*ParseOpts)

func ParseWithArgs added in v0.0.35

func ParseWithArgs(args []string) ParseOpt

func ParseWithContext added in v0.0.35

func ParseWithContext(ctx context.Context) ParseOpt

func ParseWithLookupEnv added in v0.0.35

func ParseWithLookupEnv(lookup LookupEnv) ParseOpt

func ParseWithStderr added in v0.0.35

func ParseWithStderr(stderr *os.File) ParseOpt

func ParseWithStdin added in v0.0.38

func ParseWithStdin(stdin *os.File) ParseOpt

func ParseWithStdout added in v0.0.35

func ParseWithStdout(stdout *os.File) ParseOpt

type ParseOpts added in v0.0.35

type ParseOpts struct {
	Args []string

	// Context for unstructured data. Useful for setting up mocks for tests (i.e., pass in in memory database and use it if it's here in the context)
	Context context.Context

	LookupEnv LookupEnv

	// Stderr will be passed to [CmdContext] for user commands to print to.
	// This file is never closed by warg, so if setting to something other than stderr/stdout,
	// remember to close the file after running the command.
	// Useful for saving output for tests. Defaults to os.Stderr if not passed
	Stderr *os.File

	// Stdin will be passed to [CmdContext] for user commands to read from.
	// This file is never closed by warg, so if setting to something other than stdin/stdout,
	// remember to close the file after running the command.
	// Useful for saving input for tests. Defaults to os.Stdin if not passed
	Stdin *os.File

	// Stdout will be passed to [CmdContext] for user commands to print to.
	// This file is never closed by warg, so if setting to something other than stderr/stdout,
	// remember to close the file after running the command.
	// Useful for saving output for tests. Defaults to os.Stdout if not passed
	Stdout *os.File
}

ParseOpts allows overriding the default inputs to the Parse function. Useful for tests. Create it using the go.bbkane.com/warg/parseopt package.

func NewParseOpts added in v0.0.35

func NewParseOpts(opts ...ParseOpt) ParseOpts

type ParseResult

type ParseResult struct {
	Context CmdContext
	// Action holds the passed command's action to execute.
	Action Action
}

ParseResult holds the result of parsing the command line.

type ParseState added in v0.0.26

type ParseState struct {
	ParseArgState ParseArgState

	SectionPath    []string
	CurrentSection *Section

	CurrentCmdName          string
	CurrentCmd              *Cmd
	CurrentCmdForwardedArgs []string

	CurrentFlagName string
	CurrentFlag     *Flag

	// FlagValues holds all flag values, including global and command flags, keyed by flag name. It is always non-nil, and is filled with empty values for global flags at the start of parsing, and for command flags when a command is selected (state != [ParseArgState_WantSectionOrCmd]). These flags are updated with non-empty values as flags are resolved.
	FlagValues     ValueMap
	UnsetFlagNames set.Set[string]

	HelpPassed bool
}

ParseState holds the current state of parsing the command line arguments, as well as fully resolving all flag values (including from config/env/defaults).

See ParseArgState for which fields are valid:

type PassedFlags added in v0.0.35

type PassedFlags map[string]interface{} // This can just stay a string for the convenience of the user.

PassedFlags holds a map of flag names to flag Values

type Section added in v0.0.35

type Section struct {
	// Cmds holds the Cmds under this Section
	Cmds CmdMap
	// Sections holds the Sections under this Section
	Sections SectionMap
	// HelpShort is a required one-line descripiton of this section
	HelpShort string
	// HelpLong is an optional longer description of this section
	HelpLong string
	// Footer is yet another optional longer description.
	Footer string
}

Sections are like "folders" for Commmands. They should usually have noun names. Sections should not be be created directly, but with the APIs in go.bbkane.com/warg/section.

func NewSection added in v0.0.35

func NewSection(helpShort string, opts ...SectionOpt) Section

NewSection creates a standalone Section. All section options are in the go.bbkane.com/warg/section package

type SectionMap added in v0.0.35

type SectionMap map[string]Section

SectionMap holds Sections - used by other Sections

func (SectionMap) Empty added in v0.0.35

func (fm SectionMap) Empty() bool

func (SectionMap) SortedNames added in v0.0.35

func (fm SectionMap) SortedNames() []string

type SectionOpt added in v0.0.35

type SectionOpt func(*Section)

SectionOpt customizes a Section on creation

func NewSubCmd added in v0.0.35

func NewSubCmd(name string, helpShort string, action Action, opts ...CmdOpt) SectionOpt

NewSubCmd creates a new Command as a child of this Section. Panics if a NewSubCmd with the same name already exists

func NewSubSection added in v0.0.35

func NewSubSection(name string, helpShort string, opts ...SectionOpt) SectionOpt

NewSubSection creates a new Section as a child of this Section. Panics if a NewSubSection with the same name already exists

func SectionFooter added in v0.0.35

func SectionFooter(footer string) SectionOpt

SectionFooter adds an optional help string to this Section

func SectionHelpLong added in v0.0.35

func SectionHelpLong(helpLong string) SectionOpt

SectionHelpLong adds an optional help string to this Section

func SubCmd added in v0.0.35

func SubCmd(name string, value Cmd) SectionOpt

SubCmd adds an existing SubCmd as a child of this Section. Panics if a SubCmd with the same name already exists

func SubCmdMap added in v0.0.35

func SubCmdMap(commands CmdMap) SectionOpt

SubCmdMap adds existing Commands as a child of this Section. Panics if a Command with the same name already exists

func SubSection added in v0.0.35

func SubSection(name string, value Section) SectionOpt

SubSection adds an existing SubSection as a child of this SubSection. Panics if a SubSection with the same name already exists

func SubSectionMap added in v0.0.35

func SubSectionMap(sections SectionMap) SectionOpt

SubSectionMap adds existing Sections as a child of this Section. Panics if a Section with the same name already exists

type ValueMap added in v0.0.37

type ValueMap map[string]value.Value

ValueMap holds flag values. If produced as part of ParseState, it will be fully resolved (i.e., config/env/defaults applied if possible).

func (ValueMap) IsSet added in v0.0.37

func (m ValueMap) IsSet(flagName string) bool

IsSet returns true if the flag with the given name has been set to a non-empty value (i.e., not its empty constructor value). Assumes the flag exists in the map.

func (ValueMap) ToPassedFlags added in v0.0.37

func (m ValueMap) ToPassedFlags() PassedFlags

Directories

Path Synopsis
examples
butler command
fling command
grabbit command
starghaze command
package path provides a simple wrapper around a string path that can expand the users home directory, a common CLI need.
package path provides a simple wrapper around a string path that can expand the users home directory, a common CLI need.

Jump to

Keyboard shortcuts

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