Back to godoc.org
github.com/genuinetools/pkg/cli

package cli

v0.0.0 (2fcf164)
Latest Go to latest
Published: Oct 22, 2018 | License: MIT | Module: github.com/genuinetools/pkg

Overview

Package cli provides a minimal framework for creating and organizing command line Go programs. It is designed to be easy to understand and write.

Index

Examples

type Command

type Command interface {
	Name() string      // "foobar"
	Args() string      // "<baz> [quux...]"
	ShortHelp() string // "Foo the first bar"
	LongHelp() string  // "Foo the first bar meeting the following conditions..."

	// Hidden indicates whether the command should be hidden from the help output.
	Hidden() bool

	// Register command specific flags.
	Register(*flag.FlagSet)
	// Run executes the function for the command with a context and the command arguments.
	Run(context.Context, []string) error
}

Command defines the interface for each command in a program.

type ContextKey

type ContextKey string

ContextKey defines the type for holding keys in the context.

const (
	// GitCommitKey is the key for the program's GitCommit data.
	GitCommitKey ContextKey = "program.GitCommit"
	// NameKey is the key for the program's name.
	NameKey ContextKey = "program.Name"
	// VersionKey is the key for the program's Version data.
	VersionKey ContextKey = "program.Version"
)

type Program

type Program struct {
	// Name of the program. Defaults to path.Base(os.Args[0]).
	Name string
	// Description of the program.
	Description string
	// Version of the program.
	Version string
	// GitCommit information for the program.
	GitCommit string

	// Commands in the program.
	Commands []Command
	// FlagSet holds the common/global flags for the program.
	FlagSet *flag.FlagSet

	// Before defines a function to execute before any subcommands are run,
	// but after the context is ready.
	// If a non-nil error is returned, no subcommands are run.
	Before func(context.Context) error
	// After defines a function to execute after any commands or action is run
	// and has finished.
	// It is run _only_ if the subcommand exits without an error.
	After func(context.Context) error

	// Action is the function to execute when no subcommands are specified.
	// It gives the user back the arguments after the flags have been parsed.
	Action func(context.Context, []string) error
}

Program defines the struct for holding information about the program.

func NewProgram

func NewProgram() *Program

NewProgram creates a new Program with some reasonable defaults for Name, Description, and Version.

Example (WithCommand)

Code:

package cli_test

import (
	"context"
	"flag"
	"fmt"
	"os"

	"github.com/genuinetools/pkg/cli"
)

const yoHelp = `Send "yo" to the program.`

func (cmd *yoCommand) Name() string      { return "yo" }
func (cmd *yoCommand) Args() string      { return "" }
func (cmd *yoCommand) ShortHelp() string { return yoHelp }
func (cmd *yoCommand) LongHelp() string  { return yoHelp }
func (cmd *yoCommand) Hidden() bool      { return false }

func (cmd *yoCommand) Register(fs *flag.FlagSet) {}

type yoCommand struct{}

func (cmd *yoCommand) Run(ctx context.Context, args []string) error {
	fmt.Fprintln(os.Stdout, "yo")
	return nil
}

func ExampleNewProgram_withCommand() {
	// Create a new cli program.
	p := cli.NewProgram()
	p.Name = "yo"
	p.Description = `A tool that prints "yo" when you run the command "yo"`

	// Set the GitCommit and Version.
	p.GitCommit = "ef2f64f"
	p.Version = "v0.1.0"

	// Setup the global flags.
	var (
		debug bool
	)
	p.FlagSet = flag.NewFlagSet("global", flag.ExitOnError)
	p.FlagSet.BoolVar(&debug, "d", false, "enable debug logging")

	// Set the before function.
	p.Before = func(ctx context.Context) error {
		// Set the log level.
		if debug {
			// Setup your logger here...
		}

		return nil
	}

	// Add our commands.
	p.Commands = []cli.Command{
		&yoCommand{},
	}

	// Run our program.
	p.Run()
	// Output: yo
}

Output:

yo
Example (WithSingleAction)

Code:

package cli_test

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"testing"

	"github.com/genuinetools/pkg/cli"
)

func TestMain(m *testing.M) {
	flag.Parse()
	resetForTesting()
	os.Exit(m.Run())
}

var defaultUsage = flag.Usage

// resetTesting clears all flag state and sets the usage function as directed.
// After calling resetForTesting, parse errors in flag handling will not
// exit the program.
// It also resets the args passed.
func resetForTesting() {
	flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
	flag.CommandLine.Usage = defaultUsage
	os.Args = []string{"yo", "yo"}
}

func ExampleNewProgram_withSingleAction() {
	// Create a new cli program.
	p := cli.NewProgram()
	p.Name = "yo"
	p.Description = `A tool that prints "yo"`

	// Set the GitCommit and Version.
	p.GitCommit = "ef2f64f"
	p.Version = "v0.1.0"

	// Setup the global flags.
	var (
		debug bool
	)
	p.FlagSet = flag.NewFlagSet("global", flag.ExitOnError)
	p.FlagSet.BoolVar(&debug, "d", false, "enable debug logging")

	// Set the before function.
	p.Before = func(ctx context.Context) error {
		// Set the log level.
		if debug {
			// Setup your logger here...
		}

		return nil
	}

	// Set the main program action.
	p.Action = func(ctx context.Context, args []string) error {
		// On ^C, or SIGTERM handle exit.
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		signal.Notify(c, syscall.SIGTERM)
		go func() {
			for sig := range c {
				log.Printf("Received %s, exiting.", sig.String())
				os.Exit(0)
			}
		}()

		fmt.Fprintln(os.Stdout, "yo")
		return nil
	}

	// Run our program.
	p.Run()
	// Output: yo
}

Output:

yo

func (*Program) Run

func (p *Program) Run()

Run is the entry point for the program. It parses the arguments and executes the commands.

Documentation was rendered with GOOS=linux and GOARCH=amd64.

Jump to identifier

Keyboard shortcuts

? : This menu
f or F : Jump to identifier