subcommands

package
Version: v0.0.0-...-810cf82 Latest Latest
Warning

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

Go to latest
Published: Dec 29, 2019 License: MIT Imports: 11 Imported by: 26

Documentation

Overview

Package subcommands is a framework for creating command-based interfaces with hierarchical commands.

Each command is in a separate package, and the package import path hierarchy is used to create the command hierarchy. For example, the package github.com/myuser/myproject/foo/bar/baz could be the subcommand "bar baz" under the top-level command "foo".

TODO(tv) this API is not considered final yet

BUG(tv) multiple use leaves state around -> not currently useful for more than command line parsing. maybe should instantiate new command values, instead of using the registered ones?

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Register

func Register(cmd interface{})

Register this command on the default Shell.

Types

type Description

type Description string

Description contains a short description of the command it is embedded in.

Example
package main

import (
	"bazil.org/bazil/cliutil/subcommands"
)

func main() {
	type frobCommand struct {
		subcommands.Description
	}

	var frob = frobCommand{
		Description: "Frobnicate the bizbaz",
	}
	_ = frob
}
Output:

func (Description) GetDescription

func (d Description) GetDescription() string

GetDescription returns the description. See DescriptionGetter.

type DescriptionGetter

type DescriptionGetter interface {
	GetDescription() string
}

DescriptionGetter is used to give a short description of the command when showing a list of subcommands.

The typical way to implement this is to embed Description in the command struct, and give the description when declaring the variable. See Description for an example.

type ErrMissingCommand

type ErrMissingCommand struct{}

ErrMissingCommand indicates that a subcommand is needed but was not seen in the arguments.

func (ErrMissingCommand) Error

func (ErrMissingCommand) Error() string

type FlagParser

type FlagParser interface {
	Parse(args []string) error
	Args() []string
}

FlagParser is implemented by commands that wish to process their arguments before subcommand traversal continues.

The typical way to implement this is to embed flag.FlagSet in the command struct.

Example
package main

import (
	"flag"
)

func main() {
	type myCommand struct {
		flag.FlagSet
	}
}
Output:

type FlagSetter

type FlagSetter interface {
	Init(name string, errorHandling flag.ErrorHandling)
	SetOutput(w io.Writer)
}

FlagSetter is used to recognize a flag.FlagSet (even when embedded in a struct). It is used to disable the undesired behavior of the flag library: to prevent program termination and control stderr output.

type Overview

type Overview string

Overview contains one or more paragraphs of text giving an overview of the command.

func (Overview) GetOverview

func (s Overview) GetOverview() string

GetOverview returns the overview text. See Overviewer.

type Overviewer

type Overviewer interface {
	GetOverview() string
}

Overviewer is used to give an overview explanation of the command. This is displayed in the usage message after the synopsis, before options.

The typical way to implement this is to embed Overview in the command struct, and give the overview when declaring the variable. See Overview examples.

Leading newlines are removed, to make writing multi-line raw strings more convenient. A trailing newline is added if one is not present, to make writing single-line strings more convenient.

type Result

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

Result is the result of parsing the arguments given to a command.

TODO(tv) this API may change a lot

func Parse

func Parse(cmd interface{}, name string, args []string) (Result, error)

Parse the command line using the default Shell.

In typical use, cmd is the address of a registered command at the top of the package hierarchy where the commands reside, name is the name of the application running, and args is `os.Args[1:]`.

func (*Result) ListCommands

func (r *Result) ListCommands() []interface{}

ListCommands returns a list of the subcommands encountered. Index 0 is the topmost parent, last item is the active subcommand.

func (*Result) Name

func (r *Result) Name() string

Name returns the full name of the subcommand being executed, including all the parents.

func (*Result) Usage

func (r *Result) Usage()

Usage writes a usage message for the active subcommand to standard error.

func (*Result) UsageTo

func (r *Result) UsageTo(w io.Writer)

UsageTo writes a usage message for the active subcommand to the given Writer.

type Runner

type Runner interface {
	Run() error
}

Runner is used as a marker interface to distinguish commands that are valid by themselves, even when they have subcommands. Run is never actually called.

It is also intended as a convenience interface for the caller, to convert the interface{} returned from Result.Command() into something that can be acted upon.

type Shell

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

Shell is a collection of commands, identified by the package that defines them.

var Default Shell

Default is a single global instance of Shell used for command-line argument parsing.

func (*Shell) Parse

func (s *Shell) Parse(cmd interface{}, name string, args []string) (Result, error)

Parse examines the command line from args based on the top-level command cmd with the given name. It returns a Result that describes the result of the parsing, and an error. Result is valid even when error is not nil.

func (*Shell) Register

func (s *Shell) Register(cmd interface{})

Register a new command.

Each command is a singleton value of a unique type that has its address given to Shell.Register. Commands are identified by the package that defined the type; each command should be in a separate package.

Commands may implement optional interfaces to enable more functionality. The recognized interfaces are:

  • DescriptionGetter: short description to show when listing subcommands
  • FlagParser: will be called to process "-foo" style flags
  • FlagSetter: used to recognize a flag.FlagSet and to control its behavior
  • VisiterAll: used to generate a help message for "-foo" style flags

Additionally, the command can define a struct named Arguments and bazil.org/bazil/cliutil/positional will be used to parse positional arguments into it.

type Synopses

type Synopses []string

Synopses contains a list of synopses snippets, short summaries of the arguments that can be passed in.

If you have just one synopsis, use Synopsis instead.

Example
package main

import (
	"fmt"
	"os"

	"bazil.org/bazil/cliutil/subcommands"
)

func main() {
	type compressCommand struct {
		subcommands.Synopses
	}

	var compress = compressCommand{
		Synopses: []string{
			// compress refuses to output compressed data to a tty
			">FILE",
			"-o FILE",
		},
	}

	result, err := subcommands.Parse(&compress, "compress", []string{})
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	result.UsageTo(os.Stdout)
}
Output:

Usage:
  compress >FILE
  compress -o FILE

func (Synopses) GetSynopses

func (s Synopses) GetSynopses() []string

GetSynopses returns the list of synopses. See SynopsesGetter.

type SynopsesGetter

type SynopsesGetter interface {
	GetSynopses() []string
}

SynopsesGetter is used to give a list of synopses snippets, short summaries of the arguments that can be passed in.

The typical way to implement this is to embed Synopsis or Synopses in the command struct, and give the synopses when declaring the variable. See Synopsis and Synopses for examples.

type Synopsis

type Synopsis string

Synopsis contains a synopsis snippet, a short summary of the arguments that can be passed in.

To show multiple alternative calling conventions, use Synopses.

Example
package main

import (
	"fmt"
	"os"

	"bazil.org/bazil/cliutil/subcommands"
)

func main() {
	type frobCommand struct {
		subcommands.Synopsis
	}

	var frob = frobCommand{
		Synopsis: "POLARITY PARTICLE <FILE",
	}

	result, err := subcommands.Parse(&frob, "frob", []string{"reverse", "neutron"})
	if err != nil {
		fmt.Printf("error: %v", err)
		return
	}
	result.UsageTo(os.Stdout)
}
Output:

Usage:
  frob POLARITY PARTICLE <FILE

func (Synopsis) GetSynopses

func (s Synopsis) GetSynopses() []string

GetSynopses returns the list of synopses. See SynopsesGetter.

type VisiterAll

type VisiterAll interface {
	VisitAll(fn func(*flag.Flag))
}

VisiterAll is an interface that lets commands report what "-foo" style flags they support. This is used for help output.

The typical way to implement this is to embed flag.FlagSet in the command struct.

Notes

Bugs

  • multiple use leaves state around -> not currently useful for more than command line parsing. maybe should instantiate new command values, instead of using the registered ones?

Directories

Path Synopsis
test

Jump to

Keyboard shortcuts

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