opts

package module
v1.2.3 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2022 License: MIT Imports: 22 Imported by: 915

README

logo
A Go (golang) package for building frictionless command-line interfaces

GoDoc CI


Creating command-line interfaces should be simple:

package main

import (
	"log"

	"github.com/jpillora/opts"
)

func main() {
	type config struct {
		File  string `opts:"help=file to load"`
		Lines int    `opts:"help=number of lines to show"`
	}
	c := config{}
	opts.Parse(&c)
	log.Printf("%+v", c)
}
$ go build -o my-prog
$ ./my-prog --help

  Usage: my-prog [options]

  Options:
  --file, -f   file to load
  --lines, -l  number of lines to show
  --help, -h   display help

$ ./my-prog -f foo.txt -l 42
{File:foo.txt Lines:42}

Try it out https://play.golang.org/p/D0jWFwmxRgt

Features (with examples)

  • Easy to use (eg-helloworld)
  • Promotes separation of CLI code and library code (eg-app)
  • Automatically generated --help text via struct tags (eg-help)
  • Default values by modifying the struct prior to Parse() (eg-defaults)
  • Default values from a JSON config file, unmarshalled via your config struct (eg-config)
  • Default values from environment, defined by your field names (eg-env)
  • Repeated flags using slices (eg-repeated-flag)
  • Group your flags in the help output (eg-groups)
  • Sub-commands by nesting structs (eg-commands-inline)
  • Sub-commands by providing child Opts (eg-commands-main)
  • Infers program name from executable name
  • Infers command names from struct or package name
  • Define custom flags types via opts.Setter or flag.Value (eg-custom-flag)
  • Customizable help text by modifying the default templates (eg-help)
  • Built-in shell auto-completion (eg-complete)

Find these examples and more in the opts-examples repository.

Package API

See https://godoc.org/github.com/jpillora/opts#Opts

GoDoc

Struct Tag API

opts tries to set sane defaults so, for the most part, you'll get the desired behaviour by simply providing a configuration struct.

However, you can customise this behaviour by providing the opts struct tag with a series of settings in the form of key=value:

`opts:"key=value,key=value,..."`

Where key must be one of:

  • - (dash) - Like json:"-", the dash character will cause opts to ignore the struct field. Unexported fields are always ignored.

  • name - Name is used to display the field in the help text. By default, the flag name is infered by converting the struct field name to lowercase and adding dashes between words.

  • help - The help text used to summaryribe the field. It will be displayed next to the flag name in the help output.

    Note: help can also be set as a stand-alone struct tag (i.e. help:"my text goes here"). You must use the stand-alone tag if you wish to use a comma , in your help string.

  • mode - The opts mode assigned to the field. All fields will be given a mode. Where the mode value must be one of:

    • flag - The field will be treated as a flag: an optional, named, configurable field. Set using ./program --<flag-name> <flag-value>. The struct field must be a flag-value type. flag is the default mode for any flag-value.

    • arg - The field will be treated as an argument: a required, positional, unamed, configurable field. Set using ./program <argument-value>. The struct field must be a flag-value type.

    • embedded - A special mode which causes the fields of struct to be used in the current struct. Useful if you want to split your command-line options across multiple files (default for struct fields). The struct field must be a struct. embedded is the default mode for a struct. Tip You can play group all fields together placing an group tag on the struct field.

    • cmd - A inline command, shorthand for .AddCommmand(opts.New(&field)), which also implies the struct field must be a struct.

    • cmdname - A special mode which will assume the name of the selected command. The struct field must be a string.

  • short - One letter to be used a flag's "short" name. By default, the first letter of name will be used. It will remain unset if there is a duplicate short name or if opts:"short=-". Only valid when mode is flag.

  • group - The name of the flag group to store the field. Defining this field will create a new group of flags in the help text (will appear as "<group> options"). The default flag group is the empty string (which will appear as "Options"). Only valid when mode is flag or embedded.

  • env - An environent variable to use as the field's default value. It can always be overridden by providing the appropriate flag. Only valid when mode is flag.

    For example, opts:"env=FOO". It can also be infered using the field name with simply opts:"env". You can enable inference on all flags with the opts.Opts method UseEnv().

  • min max - A minimum or maximum length of a slice. Only valid when mode is arg, and the struct field is a slice.

flag-values:

In general an opts flag-value type aims to be any type that can be get and set using a string. Currently, opts supports the following types:

  • string
  • bool
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • opts.Setter
    • The interface func Set(string) error
  • flag.Value
    • Is an opts.Setter
  • time.Duration
  • encoding.TextUnmarshaler
    • Includes time.Time and net.IP
  • encoding.BinaryUnmarshaler
    • Includes url.URL

In addition, flags and args can also be a slice of any flag-value type. Slices allow multiple flags/args. For example, a struct field flag Foo []int could be set with --foo 1 --foo 2, and would result in []int{1,2}.

Help text

By default, opts attempts to output well-formatted help text when the user provides the --help (-h) flag. The examples repositories shows various combinations of this default help text, resulting from using various features above.

Modifications be made by customising the underlying Go templates found here DefaultTemplates.

Talk

I gave a talk on opts at the Go Meetup Sydney (golang-syd) on the 23rd of May, 2019. You can find the slides here https://github.com/jpillora/opts-talk.

Other projects

Other related projects which infer flags from struct tags but aren't as feature-complete:

MIT License

Copyright © 2019 <dev@jpillora.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Documentation

Overview

Package opts defines a struct-tag based API for rapidly building command-line interfaces. For example:

package main

import (
	"log"
	"github.com/jpillora/opts"
)

func main() {
	type config struct {
		File  string `opts:"help=file to load"`
		Lines int    `opts:"help=number of lines to show"`
	}
	c := config{}
	opts.Parse(&c)
	log.Printf("%+v", c)
}

Build and run:

$ go build -o my-prog
$ ./my-prog --help

  Usage: my-prog [options]

  Options:
  --file, -f   file to load
  --lines, -l  number of lines to show
  --help, -h   display help

$ ./my-prog -f foo.txt -l 42
{File:foo.txt Lines:42}

See https://github.com/jpillora/opts for more information and more examples.

Index

Constants

This section is empty.

Variables

View Source
var DefaultOrder = []string{
	"usage",
	"summary",
	"args",
	"flaggroups",
	"cmds",
	"author",
	"version",
	"repo",
	"errmsg",
}

DefaultOrder defines which templates get rendered in which order. This list is referenced in the "help" template below.

View Source
var DefaultTemplates = map[string]string{
	"help":          `{{ $root := . }}{{range $t := .Order}}{{ templ $t $root }}{{end}}`,
	"usage":         `Usage: {{.Name }} [options]{{template "usageargs" .}}{{template "usagecmd" .}}` + "\n",
	"usageargs":     `{{range .Args}} {{.Name}}{{end}}`,
	"usagecmd":      `{{if .Cmds}} <command>{{end}}`,
	"extradefault":  `{{if .}}default {{.}}{{end}}`,
	"extraenv":      `{{if .}}env {{.}}{{end}}`,
	"extramultiple": `{{if .}}allows multiple{{end}}`,
	"summary":       "{{if .Summary}}\n{{ .Summary }}\n{{end}}",
	"args":          `{{range .Args}}{{template "arg" .}}{{end}}`,
	"arg":           "{{if .Help}}\n{{.Help}}\n{{end}}",
	"flaggroups":    `{{ range $g := .FlagGroups}}{{template "flaggroup" $g}}{{end}}`,
	"flaggroup": "{{if .Flags}}\n{{if .Name}}{{.Name}} options{{else}}Options{{end}}:\n" +
		`{{ range $f := .Flags}}{{template "flag" $f}}{{end}}{{end}}`,
	"flag":    `{{.Name}}{{if .Help}}{{.Pad}}{{.Help}}{{end}}` + "\n",
	"cmds":    "{{if .Cmds}}\nCommands:\n" + `{{ range $sub := .Cmds}}{{template "cmd" $sub}}{{end}}{{end}}`,
	"cmd":     "· {{ .Name }}{{if .Help}}{{.Pad}}  {{ .Help }}{{end}}\n",
	"version": "{{if .Version}}\nVersion:\n{{.Pad}}{{.Version}}\n{{end}}",
	"repo":    "{{if .Repo}}\nRead more:\n{{.Pad}}{{.Repo}}\n{{end}}",
	"author":  "{{if .Author}}\nAuthor:\n{{.Pad}}{{.Author}}\n{{end}}",
	"errmsg":  "{{if .ErrMsg}}\nError:\n{{.Pad}}{{.ErrMsg}}\n{{end}}",
}

DefaultTemplates define a set of individual templates that get rendered in DefaultOrder. You can replace templates or insert templates before or after existing templates using the DocSet, DocBefore and DocAfter methods. For example, you can insert a string after the usage text with:

DocAfter("usage", "this is a string, and if it is very long, it will be wrapped")

The entire help text is simply the "help" template listed below, which renders a set of these templates in the order defined above. All templates can be referenced using the keys in this map:

Functions

This section is empty.

Types

type Completer added in v1.0.1

type Completer interface {
	//Complete is given user's input and should
	//return a corresponding set of valid inputs.
	//Note: all result strings must be prefixed
	//with the user's input.
	Complete(user string) []string
}

Completer represents a shell-completion implementation for a single field. By default, all fields will auto-complete files and directories. Use a field type which implements this Completer interface to override this behaviour.

type Opts

type Opts interface {
	//Name of the command. For the root command, Name defaults to the executable's
	//base name. For subcommands, Name defaults to the package name, unless its the
	//main package, then it defaults to the struct name.
	Name(name string) Opts
	//Version of the command. Commonly set using a package main variable at compile
	//time using ldflags (for example, go build -ldflags -X main.version=42).
	Version(version string) Opts
	//ConfigPath is a path to a JSON file to use as defaults. This is useful in
	//global paths like /etc/my-prog.json. For a user-specified path. Use the
	//UserConfigPath method.
	ConfigPath(path string) Opts
	//UserConfigPath is the same as ConfigPath however an extra flag (--config-path)
	//is added to this Opts instance to give the user control of the filepath.
	//Configuration unmarshalling occurs after flag parsing.
	UserConfigPath() Opts
	//UseEnv enables the default environment variables on all fields. This is
	//equivalent to adding the opts tag "env" on all flag fields.
	UseEnv() Opts
	//Complete enables auto-completion for this command. When enabled, two extra
	//flags are added (--install and --uninstall) which can be used to install
	//a dynamic shell (bash, zsh, fish) completion for this command. Internally,
	//this adds a stub file which runs the Go binary to auto-complete its own
	//command-line interface. Note, the absolute path returned from os.Executable()
	//is used to reference to the Go binary.
	Complete() Opts
	//EmbedFlagSet embeds the given pkg/flag.FlagSet into
	//this Opts instance. Placing the flags defined in the FlagSet
	//along side the configuration struct flags.
	EmbedFlagSet(*flag.FlagSet) Opts
	//EmbedGlobalFlagSet embeds the global pkg/flag.CommandLine
	//FlagSet variable into this Opts instance.
	EmbedGlobalFlagSet() Opts

	//Summary adds a short sentence below the usage text
	Summary(summary string) Opts
	//Repo sets the source repository of the program and is displayed
	//at the bottom of the help text.
	Repo(repo string) Opts
	//Author sets the author of the program and is displayed
	//at the bottom of the help text.
	Author(author string) Opts
	//PkgRepo automatically sets Repo using the struct's package path.
	//This does not work for types defined in the main package.
	PkgRepo() Opts
	//PkgAuthor automatically sets Author using the struct's package path.
	//This does not work for types defined in the main package.
	PkgAuthor() Opts
	//DocSet replaces an existing template.
	DocSet(id, template string) Opts
	//DocBefore inserts a new template before an existing template.
	DocBefore(existingID, newID, template string) Opts
	//DocAfter inserts a new template after an existing template.
	DocAfter(existingID, newID, template string) Opts
	//DisablePadAll removes the padding from the help text.
	DisablePadAll() Opts
	//SetPadWidth alters the padding to specific number of spaces.
	//By default, pad width is 2.
	SetPadWidth(padding int) Opts
	//SetLineWidth alters the maximum number of characters in a
	//line (excluding padding). By default, line width is 96.
	SetLineWidth(width int) Opts

	//AddCommand adds another Opts instance as a subcommand.
	AddCommand(Opts) Opts
	//Parse calls ParseArgs(os.Args).
	Parse() ParsedOpts
	//ParseArgs parses the given strings and stores the results
	//in your provided struct. Assumes the executed program is
	//the first arg. Parse failures will call os.Exit.
	ParseArgs(args []string) ParsedOpts
	//ParseArgsError is the same as ParseArgs except you can
	//handle the error.
	ParseArgsError(args []string) (ParsedOpts, error)
}

Opts is a single configuration command instance. It represents a node in a tree of commands. Use the AddCommand method to add subcommands (child nodes) to this command instance.

func New

func New(config interface{}) Opts

New creates a new Opts instance using the given configuration struct pointer.

type ParsedOpts

type ParsedOpts interface {
	//Help returns the final help text
	Help() string
	//IsRunnable returns whether the matched command has a Run method
	IsRunnable() bool
	//Run assumes the matched command is runnable and executes its Run method.
	//The target Run method must be 'Run() error' or 'Run()'
	Run() error
	//RunFatal assumes the matched command is runnable and executes its Run method.
	//However, any error will be printed, followed by an exit(1).
	RunFatal()
	//Selected returns the subcommand picked when parsing the command line
	Selected() ParsedOpts
}

func Parse

func Parse(config interface{}) ParsedOpts

Parse is shorthand for

opts.New(config).Parse()

type Setter added in v1.0.1

type Setter interface {
	Set(string) error
}

Setter is any type which can be set from a string. This includes flag.Value.

Jump to

Keyboard shortcuts

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