cli

package module
v0.1.0-beta Latest Latest
Warning

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

Go to latest
Published: May 18, 2025 License: 0BSD Imports: 9 Imported by: 0

Documentation

Overview

Input Sources and Precedence

This library will always parse a program's command line arguments for Inputs. However, inputs can additionally be parsed from environment variables or default values, in that order of precedence. For example, if an input can be parsed from all of those places (command line argument, environment variable, and default value), all will be parsed, but the value from the command line will take precedence over the value from the environment variable, and the value from the environment variable will take precedence over the default value.

Command Line Syntax

Command line arguments are classified as one of the following:

  1. Options: arguments that begin with "-" or "--" and may or may not require a value.
  2. Positional Arguments: arguments that are identified by the order in which they appear among other positional arguments.
  3. Subcommands: All arguments that follow belong to this command.

Command line arguments are parsed as options until a positional argument, subcommand, or an argument of just "--" is encountered. In other words, any options that belong to a command must come before any of that command's positional arguments or subcommands.

Positional arguments and subcommands are mutually exclusive since allowing both to exist at once would invite unnecessary ambiguity when parsing because there's no reliable way to tell if an argument would be a positional argument or the name of a subcommand. Furthermore, positional arguments that are required must appear before any optional ones since it would be impossible to tell when parsing whether a positional argument is filling the spot of a required one or an optional one. Therefore, the format of a command is structured like this:

command [options] [<required_pos_args> [optional_pos_args] [any_surplus_post_args...] | subcommand ...]

Options

There are only two types of options in terms of syntax:

  1. boolean: Rather than providing some value, the mere presence of this type of option means something. For example, the "--all" in "ls --all" does not take a value; it just modifies the list command to list "all" files.
  2. non-boolean: This type of option requires a value. For example, in "ls --hide go.sum", the option "--hide" requires a file name or pattern.

Non-boolean options must have a value attached. In other words, while options themselves can either be required or optional, there is no such thing as an option that may or may not have a value.

Options can have appear in one of two forms and can have a name for each form: long or short. Typically an option's long name is more than one character, but an option's short name can only be a single character. Long form options are provided by prefixing the option's name with two hyphens ("--"), and they must appear one at a time, separately. Short form options are provided by prefixing the options short name with a single hyphen ("-"), and they can be "stacked", meaning under certain conditions, they can appear one after the other in the same command line argument.

The following are some common ways of how options can be provided:

--opt      // long form boolean option
--opt=v    // long form non-boolean option with value of "v"
--opt v    // same as above, non-boolean options can provide their value as the next command line argument
-a         // short form boolean option "a"
-a -b      // two short form boolean option "a" and "b"
-ab        // either same as above, or short form non-boolean option "a" with value of "b" (depends on specified command structure)

Basic Usage

p := cli.NewCmd("full").
	Help("A full example program").
	Opt(cli.NewBoolOpt("yes").
		Short('y').
		Help("A boolean option on the root command.").
		Env("YES")).
	Opt(cli.NewOpt("str").
		Short('s').
		Help("A string option on the root command.").
		Env("STR")).
	Subcmd(cli.NewCmd("nodat").
		Help("Subcommand with no data")).
	Subcmd(cli.NewCmd("floats").
		Help("Print values for each supported float type (both options required).").
		Opt(cli.NewFloat32Opt("f32").Help("32 bit float").Required()).
		Opt(cli.NewFloat64Opt("f64").Help("64 bit float").Required())).
	Subcmd(cli.NewCmd("ints").
		Help("Print values for each supported signed integer type.").
		Opt(cli.NewIntOpt("int").Help("Print the given int value."))).
	Build().
	ParseOrExit()

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultHelpInput = NewBoolOpt("help").
	Short('h').
	Help("Show this help message and exit.").
	HelpGen(DefaultHelpGenerator)
View Source
var ErrNoSubcmd = errors.New("missing subcommand")

Functions

func DefaultFullHelp

func DefaultFullHelp(c *CommandInfo) string
Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		Opt(cli.NewOpt("aa").Env("AA").Default("def").Help("an option")).
		Opt(cli.NewOpt("bb").
			Help("another option that is required and has a really long blurb to show how it will be wrapped").
			Required()).
		Arg(cli.NewArg("cc").Help("a positional argument")).
		Opt(cli.NewBoolOpt("h").
			Help("will show how this command looks in the default full help message").
			HelpGen(func(_ cli.Input, c *cli.CommandInfo) string {
				return cli.DefaultFullHelp(c)
			}))

	_, err := in.Parse("-h")
	fmt.Println(err)
}
Output:
example - an example command

usage:
  example [options] [arguments]

options:
  --aa  <arg>
      an option

      [default: def]
      [env: AA]

  --bb  <arg>   (required)
      another option that is required and has a really long blurb to show how it will be
      wrapped

  -h
      will show how this command looks in the default full help message

arguments:
  [cc]
      a positional argument

func DefaultHelpGenerator

func DefaultHelpGenerator(src Input, c *CommandInfo) string

DefaultHelpGenerator will use DefaultShortHelp if src is the short option, or it'll use DefaultFullHelp if the src is the long option name.

func DefaultShortHelp

func DefaultShortHelp(c *CommandInfo) string
Example (Complex)
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		Opt(cli.NewOpt("aa").Env("AA").Default("def").Help("an option")).
		Opt(cli.NewOpt("bb").
			Help("another option that is required and has a really long blurb to show how it will be wrapped").
			Required()).
		Opt(cli.NewOpt("short-blurb-but-really-long-name").Help("another option")).
		Arg(cli.NewArg("posarg1").Required().Help("a required positional argument")).
		Arg(cli.NewArg("posarg2").Env("PA2").Help("an optional positional argument")).
		Opt(cli.NewBoolOpt("h").
			Help("will show the default short help message").
			HelpGen(func(_ cli.Input, c *cli.CommandInfo) string {
				return cli.DefaultShortHelp(c)
			}))

	_, err := in.Parse("-h")
	fmt.Println(err)
}
Output:
example - an example command

usage:
  example [options] [arguments]

options:
      --aa  <arg>   an option (default: def) [$AA]
      --bb  <arg>   another option that is required and has a really long blurb to show
                    how it will be wrapped (required)
  -h                will show the default short help message
      --short-blurb-but-really-long-name  <arg>
                    another option

arguments:
  <posarg1>   a required positional argument (required)
  [posarg2]   an optional positional argument [$PA2]
Example (Simple)
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		Opt(cli.NewOpt("aa").Short('a').Env("AA").Default("def").Help("an option")).
		Opt(cli.NewOpt("bb").Short('b').Required().Help("another option")).
		Arg(cli.NewArg("cc").Required().Help("a required positional argument")).
		Arg(cli.NewArg("dd").Env("PA2").Help("an optional positional argument")).
		Opt(cli.NewBoolOpt("h").
			Help("will show the default short help message").
			HelpGen(func(_ cli.Input, c *cli.CommandInfo) string {
				return cli.DefaultShortHelp(c)
			}))

	_, err := in.Parse("-h")
	fmt.Println(err)
}
Output:
example - an example command

usage:
  example [options] [arguments]

options:
  -a, --aa  <arg>   an option (default: def) [$AA]
  -b, --bb  <arg>   another option (required)
  -h                will show the default short help message

arguments:
  <cc>   a required positional argument (required)
  [dd]   an optional positional argument [$PA2]
Example (SimpleWithSubcommands)
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		Opt(cli.NewOpt("aa").Short('a').Env("AA").Default("def").Help("an option")).
		Opt(cli.NewOpt("bb").Short('b').Required().Help("another option")).
		Subcmd(cli.NewCmd("subcommand1").Help("a subcommand")).
		Subcmd(cli.NewCmd("subcommand2").Help("another subcommand")).
		Opt(cli.NewBoolOpt("h").
			Help("will show the default short help message").
			HelpGen(func(_ cli.Input, c *cli.CommandInfo) string {
				return cli.DefaultShortHelp(c)
			}))

	_, err := in.Parse("-h")
	fmt.Println(err)
}
Output:
example - an example command

usage:
  example [options] <command>

options:
  -a, --aa  <arg>   an option (default: def) [$AA]
  -b, --bb  <arg>   another option (required)
  -h                will show the default short help message

commands:
   subcommand1   a subcommand
   subcommand2   another subcommand

func GetArg

func GetArg[T any](c *Command, id string) T

GetArg gets the positional argument value with the given id in the given Command and converts the value to the given type T through an untested type assertion. This function will panic if the value isn't found or if the value can't be converted to type T. To check whether the value is found instead of panicking, see LookupArg.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Arg(cli.NewArg("a")).
		Arg(cli.NewArg("b")).
		ParseOrExit("hello")

	// The following line would panic because 'a' isn't present.
	// b := cli.GetArg[string](c, "b")

	a := cli.GetArg[string](c, "a")
	fmt.Printf("a: %q\n", a)
}
Output:
a: "hello"

func GetArgOr

func GetArgOr[T any](c *Command, id string, fallback T) T

GetArgOr looks for a positional argument value with the given id in the given Command and converts the value to the given type T through an untested type assertion (so this will panic if the value is found and can't be converted to type T). If the value isn't found, the given fallback value will be returned. To check whether the value is found instead of using a fallback value, see LookupArg.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Arg(cli.NewArg("a")).
		Arg(cli.NewArg("b")).
		ParseOrExit("hello")

	a := cli.GetArg[string](c, "a")
	b := cli.GetArgOr(c, "b", "world")

	fmt.Printf("a: %q\n", a)
	fmt.Printf("b: %q\n", b)
}
Output:
a: "hello"
b: "world"

func GetOpt

func GetOpt[T any](c *Command, id string) T

GetOpt gets the option value with the given id in the given Command and converts the value to the given type T through an untested type assertion. This function will panic if the value isn't found or if the value can't be converted to type T. To check whether the value is found instead of panicking, see LookupOpt.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Opt(cli.NewOpt("a")).
		Opt(cli.NewOpt("b")).
		ParseOrExit("-b=hello")

	// The following line would panic because 'a' isn't present.
	// a := cli.GetOpt[string](c, "a")

	b := cli.GetOpt[string](c, "b")
	fmt.Printf("b: %q\n", b)
}
Output:
b: "hello"

func GetOptOr

func GetOptOr[T any](c *Command, id string, fallback T) T

GetOptOr looks for an option value with the given id in the given Command and converts the value to the given type T through an untested type assertion (so this will panic if the value is found and can't be converted to type T). If the value isn't found, the given fallback value will be returned. To check whether the value is found instead of using a fallback value, see LookupOpt.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Opt(cli.NewOpt("a")).
		Opt(cli.NewOpt("b")).
		ParseOrExit("-a=hello")

	a := cli.GetOpt[string](c, "a")
	b := cli.GetOptOr(c, "b", "world")

	fmt.Printf("a: %q\n", a)
	fmt.Printf("b: %q\n", b)
}
Output:
a: "hello"
b: "world"

func LookupArg

func LookupArg[T any](c *Command, id string) (T, bool)

LookupArg looks for a positional argument value with the given id in the given Command and converts the value to the given type T through an untested type assertion (so this will panic if the value is found and can't be converted to type T). So if the positional argument is present, the typed value will be returned and the boolean will be true. Otherwise, the zero value of type T will be returned and the boolean will be false.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Arg(cli.NewArg("a")).
		Arg(cli.NewArg("b")).
		ParseOrExit("hello")

	a, hasA := cli.LookupArg[string](c, "a")
	b, hasB := cli.LookupArg[string](c, "b")

	fmt.Printf("a: %q, %v\n", a, hasA)
	fmt.Printf("b: %q, %v\n", b, hasB)
}
Output:
a: "hello", true
b: "", false

func LookupOpt

func LookupOpt[T any](c *Command, id string) (T, bool)

LookupOpt looks for an option value with the given id in the given Command and converts the value to the given type T through an untested type assertion (so this will panic if the value is found and can't be converted to type T). So if the option is present, the typed value will be returned and the boolean will be true. Otherwise, the zero value of type T will be returned and the boolean will be false.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	c := cli.NewCmd("example").
		Opt(cli.NewOpt("a")).
		Opt(cli.NewOpt("b")).
		ParseOrExit("-b=hello")

	a, hasA := cli.LookupOpt[string](c, "a")
	b, hasB := cli.LookupOpt[string](c, "b")

	fmt.Printf("a: %q, %v\n", a, hasA)
	fmt.Printf("b: %q, %v\n", b, hasB)
}
Output:
a: "", false
b: "hello", true

func ParseBool

func ParseBool(s string) (any, error)

ParseBool returns the boolean value represented by the given string. See strconv.ParseBool for more info.

func ParseDuration

func ParseDuration(s string) (any, error)

ParseDuration uses the standard library time.ParseDuration function to parse and return the time.Duration value represented by the given string.

Example
package main

import (
	"fmt"
	"time"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("d").WithParser(cli.ParseDuration))

	c := in.ParseOrExit("-d", "1h2m3s")
	fmt.Println(cli.GetOpt[time.Duration](c, "d"))

	_, err := in.Parse("-d", "not_a_duration")
	fmt.Println(err)
}
Output:
1h2m3s
parsing option 'd': time: invalid duration "not_a_duration"

func ParseFloat32

func ParseFloat32(s string) (any, error)

ParseFloat32 returns the float32 value represented by the given string. It unwraps any strconv.NumError returned by strconv.ParseFloat for a slightly cleaner error message.

func ParseFloat64

func ParseFloat64(s string) (any, error)

ParseFloat64 returns the float64 value represented by the given string. It unwraps any strconv.NumError returned by strconv.ParseFloat for a slightly cleaner error message.

func ParseInt

func ParseInt(s string) (any, error)

ParseInt returns the int value represented by the given string. It unwraps any strconv.NumError returned by strconv.ParseInt for a slightly cleaner error message.

func ParseURL

func ParseURL(s string) (any, error)

ParseURL uses the standard library url.Parse function to parse and return the *url.URL value represented by the given string.

Example
package main

import (
	"fmt"
	"net/url"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("u").WithParser(cli.ParseURL))

	c := in.ParseOrExit("-u", "https://pkg.go.dev/github.com/steverusso/cli#ParseURL")
	fmt.Println(cli.GetOpt[*url.URL](c, "u"))

	_, err := in.Parse("-u", "b@d://.com")
	fmt.Println(err)
}
Output:
https://pkg.go.dev/github.com/steverusso/cli#ParseURL
parsing option 'u': parse "b@d://.com": first path segment in URL cannot contain colon

func ParseUint

func ParseUint(s string) (any, error)

ParseUint returns the uint value represented by the given string. It unwraps any strconv.NumError returned by strconv.ParseUint for a slightly cleaner error message.

Types

type Command

type Command struct {
	Name    string
	Opts    []Input
	Args    []Input
	Surplus []string
	Subcmd  *Command
}

type CommandInfo

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

func NewCmd

func NewCmd(name string) CommandInfo

func (CommandInfo) Arg

func (CommandInfo) Help

func (c CommandInfo) Help(blurb string) CommandInfo

func (CommandInfo) HelpExtra

func (c CommandInfo) HelpExtra(extra string) CommandInfo

HelpExtra adds an "overview" section to the Command's help message. This is typically for longer-form content that wouldn't fit well within the 1-2 sentence "blurb."

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		HelpExtra("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")

	_, err := in.Parse("--help")
	fmt.Println(err)
}
Output:
example - an example command

overview:
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
  incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
  exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

usage:
  example [options]

options:
  -h, --help
      Show this help message and exit.

func (CommandInfo) HelpUsage

func (c CommandInfo) HelpUsage(lines ...string) CommandInfo

HelpUsage overrides the default "usage" lines in the command's help message. These are intended to show the user some different ways to invoke this command using whatever combinations of options / arguments / subcommands.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("an example command").
		HelpUsage(
			"example [--aa <arg>]",
			"example [-h]",
		).
		Opt(cli.NewOpt("aa").Help("an option"))

	_, err := in.Parse("--help")
	fmt.Println(err)
}
Output:
example - an example command

usage:
  example [--aa <arg>]
  example [-h]

options:
  --aa  <arg>
      an option

  -h, --help
      Show this help message and exit.

func (CommandInfo) Opt

func (*CommandInfo) Parse

func (in *CommandInfo) Parse(args ...string) (*Command, error)

ParseOrExit will parse input based on this CommandInfo. If no function arguments are provided, the os.Args will be used.

func (CommandInfo) ParseOrExit

func (in CommandInfo) ParseOrExit(args ...string) *Command

ParseOrExit will parse input based on this CommandInfo. If help was requested, it will print the help message and exit the program successfully (status code 0). If there is any other error, it will print the error and exit the program with failure (status code 1). The input parameter semantics are the same as CommandInfo.Parse.

func (CommandInfo) Subcmd

func (c CommandInfo) Subcmd(sc CommandInfo) CommandInfo

type HelpGenerator

type HelpGenerator = func(Input, *CommandInfo) string

type HelpRequestError

type HelpRequestError struct {
	HelpMsg string
}

func (HelpRequestError) Error

func (h HelpRequestError) Error() string

type Input

type Input struct {
	Value    any
	ID       string
	RawValue string
	From     ParsedFrom
}

type InputInfo

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

func NewArg

func NewArg(id string) InputInfo

NewArg returns a new positional argument input. By default, the arg's display name will be the provided id, but this can be overidden with InputInfo.ValueName method.

func NewBoolOpt

func NewBoolOpt(id string) InputInfo

NewBoolOpt returns a new boolean option. If no value is provided to this option when parsing, it will have a "parsed" value of true. If any value is provided, the ParseBool value parser is used. Any other parser set by the user for this option will be ignored.

func NewFloat32Opt

func NewFloat32Opt(id string) InputInfo

NewFloat32Opt returns a new option that uses the ParseFloat32 value parser.

func NewFloat64Opt

func NewFloat64Opt(id string) InputInfo

NewFloat64Opt returns a new option that uses the ParseFloat64 value parser.

func NewIntOpt

func NewIntOpt(id string) InputInfo

NewIntOpt returns a new option that uses the ParseInt value parser.

func NewOpt

func NewOpt(id string) InputInfo

NewOpt returns a new non-boolean option with no parser, which means it will just receive the raw string of any provided value. If id is more than a single character long, it will be this option's long name. If id is only a single character, it will be this option's short name instead. In either case, the long name can be reset using the InputInfo.Long method.

func NewUintOpt

func NewUintOpt(id string) InputInfo

NewUintOpt returns a new option that uses the ParseUint value parser.

func (InputInfo) Default

func (in InputInfo) Default(v string) InputInfo

func (InputInfo) Env

func (in InputInfo) Env(e string) InputInfo

func (InputInfo) Help

func (in InputInfo) Help(blurb string) InputInfo

func (InputInfo) HelpGen

func (in InputInfo) HelpGen(hg HelpGenerator) InputInfo

func (InputInfo) Long

func (in InputInfo) Long(name string) InputInfo

func (InputInfo) Required

func (in InputInfo) Required() InputInfo

func (InputInfo) Short

func (in InputInfo) Short(c byte) InputInfo

Short sets this option's short name to the given character. In order to create an option that has a short name but no long name, see InputInfo.ShortOnly.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("flag").Short('f'))

	c1 := in.ParseOrExit("-f", "hello")
	fmt.Println(cli.GetOpt[string](c1, "flag"))

	c2 := in.ParseOrExit("--flag", "world")
	fmt.Println(cli.GetOpt[string](c2, "flag"))
}
Output:
hello
world

func (InputInfo) ShortOnly

func (in InputInfo) ShortOnly(c byte) InputInfo

ShortOnly sets this option's short name to the given character and removes any long name it may have had at this point. In order to create an option that has both a short and long name, see InputInfo.Short. Use InputInfo.Long to add a long name back.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("flag").ShortOnly('f'))

	c := in.ParseOrExit("-f", "hello")
	fmt.Println(cli.GetOpt[string](c, "flag"))

	_, err := in.Parse("--flag", "helloworld")
	fmt.Println(err)
}
Output:
hello
unknown option '--flag'

func (InputInfo) ValueName

func (in InputInfo) ValueName(name string) InputInfo

ValueName sets the display name of this InputInfo's argument value. For non-boolean options, it's the argument of the option. For positional arguments, it's the argument name itself.

Example (Option)
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("example program").
		Opt(cli.NewOpt("aa").ValueName("str").Help("it says '<str>' above instead of '<arg>'"))

	_, err := in.Parse("--help")
	fmt.Println(err)
}
Output:
example - example program

usage:
  example [options]

options:
  --aa  <str>
      it says '<str>' above instead of '<arg>'

  -h, --help
      Show this help message and exit.
Example (PositionalArgument)
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Help("example program").
		Arg(cli.NewArg("aa").ValueName("filename").Help("it says '[filename]' above instead of '[aa]'"))

	_, err := in.Parse("--help")
	fmt.Println(err)
}
Output:
example - example program

usage:
  example [options] [arguments]

options:
  -h, --help
      Show this help message and exit.

arguments:
  [filename]
      it says '[filename]' above instead of '[aa]'

func (InputInfo) WithParser

func (in InputInfo) WithParser(vp ValueParser) InputInfo

WithParser sets the InputInfo's parser to the given ValueParser. This will override any parser that has been set up until this point. Providing nil as the parser will restore the default behavior of just using the plain string value when this InputInfo is parsed.

Example
package main

import (
	"fmt"
	"image"
	"strconv"
	"strings"

	"github.com/steverusso/cli"
)

func main() {
	pointParser := func(s string) (any, error) {
		comma := strings.IndexByte(s, ',')
		x, _ := strconv.Atoi(s[:comma])
		y, _ := strconv.Atoi(s[comma+1:])
		return image.Point{X: x, Y: y}, nil
	}

	c := cli.NewCmd("example").
		Opt(cli.NewOpt("aa").WithParser(pointParser)).
		ParseOrExit("--aa", "3,7")

	fmt.Printf("%+#v\n", cli.GetOpt[image.Point](c, "aa"))
}
Output:
image.Point{X:3, Y:7}

type MissingArgsError

type MissingArgsError struct{ Names []string }

func (MissingArgsError) Error

func (mae MissingArgsError) Error() string

func (MissingArgsError) Is

func (mae MissingArgsError) Is(err error) bool

type MissingOptionValueError

type MissingOptionValueError struct{ Name string }

func (MissingOptionValueError) Error

func (mov MissingOptionValueError) Error() string

type MissingOptionsError

type MissingOptionsError struct{ Names []string }

func (MissingOptionsError) Error

func (moe MissingOptionsError) Error() string

func (MissingOptionsError) Is

func (moe MissingOptionsError) Is(err error) bool

type ParsedFrom

type ParsedFrom struct {
	Env        string // the env var's name
	Opt        string // the provided option name
	Arg        int    // the position starting from 1
	RawDefault bool
}

type UnknownOptionError

type UnknownOptionError struct{ Name string }

func (UnknownOptionError) Error

func (uoe UnknownOptionError) Error() string

type UnknownSubcmdError

type UnknownSubcmdError struct{ Name string }

func (UnknownSubcmdError) Error

func (usce UnknownSubcmdError) Error() string

type ValueParser

type ValueParser = func(string) (any, error)

func NewFileParser

func NewFileParser(vp ValueParser) ValueParser

NewFileParser returns a ValueParser that will treat an input string as a file path and use given parser to parse the content of the file at that path.

Example
package main

import (
	"fmt"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("i").WithParser(cli.NewFileParser(cli.ParseInt))).
		Opt(cli.NewOpt("s").WithParser(cli.NewFileParser(nil)))

	c := in.ParseOrExit(
		"-i", "testdata/sample_int",
		"-s", "testdata/sample_int",
	)

	fmt.Println(cli.GetOpt[int](c, "i"))
	fmt.Printf("%q\n", cli.GetOpt[string](c, "s"))

	_, err := in.Parse("-i", "testdata/sample_empty")
	fmt.Println(err)

	_, err = in.Parse("-i", "path_that_doesnt_exist")
	fmt.Println(err)
}
Output:
12345
"12345"
parsing option 'i': invalid syntax
parsing option 'i': open path_that_doesnt_exist: no such file or directory

func NewTimeParser

func NewTimeParser(layout string) ValueParser

NewTimeParser returns a ValueParser that will use the standard library time.Parse function with the given layout string to parse and return a time.Time from a given string.

Example
package main

import (
	"fmt"
	"time"

	"github.com/steverusso/cli"
)

func main() {
	in := cli.NewCmd("example").
		Opt(cli.NewOpt("t").WithParser(cli.NewTimeParser("2006-01-02")))

	c := in.ParseOrExit("-t", "2025-04-12")
	fmt.Println(cli.GetOpt[time.Time](c, "t"))

	_, err := in.Parse("-t", "hello")
	fmt.Println(err)
}
Output:
2025-04-12 00:00:00 +0000 UTC
parsing option 't': parsing time "hello" as "2006-01-02": cannot parse "hello" as "2006"

Jump to

Keyboard shortcuts

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