Categorygithub.com/bobg/subcmd/v2
modulepackage
2.3.0
Repository: https://github.com/bobg/subcmd.git
Documentation: pkg.go.dev

# README

Subcmd - command-line interfaces with subcommands and flags

Go Reference Go Report Card Tests Coverage Status

This is subcmd, a Go package for writing command-line programs that require flag parsing and that have “subcommands” that also require flag parsing.

Use it when you want your program to parse command lines that look like this:

command -globalopt subcommand -subopt1 FOO -subopt2 ARG1 ARG2

Subcommands may have sub-subcommands and so on. Subcommands may also be implemented as separate executables.

This is a layer on top of the standard Go flag package.

Usage

import (
  "context"
  "database/sql"
  "flag"

  "github.com/bobg/subcmd/v2"
)

func main() {
  // Parse global flags normally.
  dbname := flag.String("db", "", "database connection string")
  flag.Parse()

  db, err := sql.Open(dbdriver, *dbname)
  if err != nil { ... }

  // Stash global options in a top-level command object.
  c := command{db: db}

  // Run the subcommand given in the remainder of the command line.
  err = subcmd.Run(context.Background(), c, flag.Args())
  if err != nil { ... }
}

// The top-level command object.
type command struct {
  db *sql.DB
}

// To be used in subcmd.Run above, `command` must implement this method.
func (c command) Subcmds() subcmd.Map {
  return subcmd.Commands(
    // The "list" subcommand takes one flag, -reverse.
    "list", c.list, "list employees", subcmd.Params(
      "-reverse", subcmd.Bool, false, "reverse order of list",
    ),

    // The "add" subcommand takes no flags but one positional argument.
    "add", c.add, "add new employee", subcmd.Params(
      "name", subcmd.String, "", "employee name",
    )
  )
}

// Implementation of the "list" subcommand.
// The value of the -reverse flag is passed as an argument.
func (c command) list(ctx context.Context, reverse bool, _ []string) error {
  query := "SELECT name FROM employees ORDER BY name"
  if reverse {
    query += " DESC"
  }
  rows, err := c.db.QueryContext(ctx, query)
  if err != nil { ... }
  defer rows.Close()
  for rows.Next() { ... }
  return rows.Err()
}

// Implementation of the "add" subcommand.
func (c command) add(ctx context.Context, name string, _ []string) error {
  _, err := c.db.ExecContext(ctx, "INSERT INTO employees (name) VALUES ($1)", name)
  return err
}

# Functions

Check checks that the type of subcmd.F matches the expectations set by subcmd.Params: - It must be a function; - It must return no more than one value; - If it returns a value, that value must be of type error; - It must take an initial context.Context parameter; - It must take a final []string or ...string parameter; - The length of subcmd.Params must match the number of parameters subcmd.F takes (not counting the initial context.Context and final []string parameters); - Each parameter in subcmd.Params must match the corresponding parameter in subcmd.F.
CheckMap calls [Check] on each of the entries in the Map.
Commands is a convenience function for producing the [Map] needed by an implementation of Cmd.Subcmd.
FlagSet produces the [flag.FlagSet] used in a call to a [Subcmd] function.
Params is a convenience function for producing the list of parameters needed by a Subcmd.
ParseEnv parses the value of the SUBCMD_ENV environment variable, placing the result in the value pointed to by ptr, which must be a pointer of a suitable type.
Run runs the subcommand of c named in args[0].
ToFlagSet takes a slice of [Param] and produces: - a [flag.FlagSet], - a list of properly typed pointers (or in the case of a [Value]-typed Param, a [flag.Value]) in which to store the results of calling Parse on the FlagSet, - a list of positional Params that are not part of the resulting FlagSet.

# Constants

Possible [Param] types.
Possible [Param] types.
EnvVar is the name of the environment variable used by [Run] to pass the JSON-encoded [Cmd] to a subprocess.
Possible [Param] types.
Possible [Param] types.
Possible [Param] types.
Possible [Param] types.
Possible [Param] types.
Possible [Param] types.
Possible [Param] types.

# Variables

ErrTooFewArgs is the error when not enough arguments are supplied for required positional parameters.

# Structs

FuncTypeErr means a [Subcmd]'s F field has a type that does not match the function signature implied by its Params field.
HelpRequestedErr is a usage error returned when the "help" pseudo-subcommand-name is used.
MissingSubcmdErr is a usage error returned when [Run] is called with an empty args list.
Param is one parameter of a [Subcmd].
ParamDefaultErr is the error when a [Param] has a default value that is not of the correct type.
ParseErr is the type of error returned when parsing a positional parameter according to its type fails.
Subcmd is one subcommand of a [Cmd], and the value type in the [Map] returned by Cmd.Subcmds.
UnknownSubcmdErr is a usage error returned when an unknown subcommand name is passed to [Run] as args[0].

# Interfaces

Cmd is a command that has subcommands.
Copier is a [flag.Value] that can copy itself.
Prefixer is an optional additional interface that a [Cmd] can implement.
UsageErr is the type of errors that give usage information.

# Type aliases

Map is the type of the data structure returned by Cmd.Subcmds and by [Commands].
Type is the type of a [Param].