cli

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2015 License: MIT, Apache-2.0 Imports: 11 Imported by: 0

README

Build Status

cli.go

cli.go is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.

You can view the API docs here: http://godoc.org/github.com/codegangsta/cli

Overview

Command line apps are usually so tiny that there is absolutely no reason why your code should not be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.

This is where cli.go comes into play. cli.go makes command line programming fun, organized, and expressive!

Installation

Make sure you have a working Go environment (go 1.1+ is required). See the install instructions.

To install cli.go, simply run:

$ go get github.com/codegangsta/cli

Make sure your PATH includes to the $GOPATH/bin directory so your commands can be easily used:

export PATH=$PATH:$GOPATH/bin

Getting Started

One of the philosophies behind cli.go is that an API should be playful and full of discovery. So a cli.go app can be as little as one line of code in main().

package main

import (
  "os"
  "github.com/codegangsta/cli"
)

func main() {
  cli.NewApp().Run(os.Args)
}

This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:

package main

import (
  "os"
  "github.com/codegangsta/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "boom"
  app.Usage = "make an explosive entrance"
  app.Action = func(c *cli.Context) {
    println("boom! I say!")
  }
  
  app.Run(os.Args)
}

Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below.

Example

Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!

Start by creating a directory named greet, and within it, add a file, greet.go with the following code in it:

package main

import (
  "os"
  "github.com/codegangsta/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "greet"
  app.Usage = "fight the loneliness!"
  app.Action = func(c *cli.Context) {
    println("Hello friend!")
  }

  app.Run(os.Args)
}

Install our command to the $GOPATH/bin directory:

$ go install

Finally run our new command:

$ greet
Hello friend!

cli.go also generates some bitchass help text:

$ greet help
NAME:
    greet - fight the loneliness!

USAGE:
    greet [global options] command [command options] [arguments...]

VERSION:
    0.0.0

COMMANDS:
    help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS
    --version	Shows version information
Arguments

You can lookup arguments by calling the Args function on cli.Context.

...
app.Action = func(c *cli.Context) {
  println("Hello", c.Args()[0])
}
...
Flags

Setting and querying flags is simple.

...
app.Flags = []cli.Flag {
  cli.StringFlag{
    Name: "lang",
    Value: "english",
    Usage: "language for the greeting",
  },
}
app.Action = func(c *cli.Context) {
  name := "someone"
  if len(c.Args()) > 0 {
    name = c.Args()[0]
  }
  if c.String("lang") == "spanish" {
    println("Hola", name)
  } else {
    println("Hello", name)
  }
}
...
Alternate Names

You can set alternate (or short) names for flags by providing a comma-delimited list for the Name. e.g.

app.Flags = []cli.Flag {
  cli.StringFlag{
    Name: "lang, l",
    Value: "english",
    Usage: "language for the greeting",
  },
}

That flag can then be set with --lang spanish or -l spanish. Note that giving two different forms of the same flag in the same command invocation is an error.

Values from the Environment

You can also have the default value set from the environment via EnvVar. e.g.

app.Flags = []cli.Flag {
  cli.StringFlag{
    Name: "lang, l",
    Value: "english",
    Usage: "language for the greeting",
    EnvVar: "APP_LANG",
  },
}

The EnvVar may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.

app.Flags = []cli.Flag {
  cli.StringFlag{
    Name: "lang, l",
    Value: "english",
    Usage: "language for the greeting",
    EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
  },
}
Subcommands

Subcommands can be defined for a more git-like command line app.

...
app.Commands = []cli.Command{
  {
    Name:      "add",
    Aliases:     []string{"a"},
    Usage:     "add a task to the list",
    Action: func(c *cli.Context) {
      println("added task: ", c.Args().First())
    },
  },
  {
    Name:      "complete",
    Aliases:     []string{"c"},
    Usage:     "complete a task on the list",
    Action: func(c *cli.Context) {
      println("completed task: ", c.Args().First())
    },
  },
  {
    Name:      "template",
    Aliases:     []string{"r"},
    Usage:     "options for task templates",
    Subcommands: []cli.Command{
      {
        Name:  "add",
        Usage: "add a new template",
        Action: func(c *cli.Context) {
            println("new task template: ", c.Args().First())
        },
      },
      {
        Name:  "remove",
        Usage: "remove an existing template",
        Action: func(c *cli.Context) {
          println("removed task template: ", c.Args().First())
        },
      },
    },
  },
}
...
Bash Completion

You can enable completion commands by setting the EnableBashCompletion flag on the App object. By default, this setting will only auto-complete to show an app's subcommands, but you can write your own completion methods for the App or its subcommands.

...
var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
app := cli.NewApp()
app.EnableBashCompletion = true
app.Commands = []cli.Command{
  {
    Name:  "complete",
    Aliases: []string{"c"},
    Usage: "complete a task on the list",
    Action: func(c *cli.Context) {
       println("completed task: ", c.Args().First())
    },
    BashComplete: func(c *cli.Context) {
      // This will complete if no args are passed
      if len(c.Args()) > 0 {
        return
      }
      for _, t := range tasks {
        fmt.Println(t)
      }
    },
  }
}
...
To Enable

Source the autocomplete/bash_autocomplete file in your .bashrc file while setting the PROG variable to the name of your program:

PROG=myprogram source /.../cli/autocomplete/bash_autocomplete

To Distribute

Copy and modify autocomplete/bash_autocomplete to use your program name rather than $PROG and have the user copy the file into /etc/bash_completion.d/ (or automatically install it there if you are distributing a package). Alternatively you can just document that users should source the generic autocomplete/bash_autocomplete with $PROG set to your program name in their bash configuration.

Contribution Guidelines

Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.

If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.

If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.

Documentation

Overview

Package cli provides a minimal framework for creating and organizing command line Go applications. cli is designed to be easy to understand and write, the most simple cli application can be written as follows:

func main() {
  cli.NewApp().Run(os.Args)
}

Of course this application does not do much, so let's make this an actual application:

func main() {
  app := cli.NewApp()
  app.Name = "greet"
  app.Usage = "say a greeting"
  app.Action = func(c *cli.Context) {
    println("Greetings")
  }

  app.Run(os.Args)
}
Example
package main

import (
	"os"

	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "todo"
	app.Usage = "task list on the command line"
	app.Commands = []cli.Command{
		{
			Name:    "add",
			Aliases: []string{"a"},
			Usage:   "add a task to the list",
			Action: func(c *cli.Context) {
				println("added task: ", c.Args().First())
			},
		},
		{
			Name:    "complete",
			Aliases: []string{"c"},
			Usage:   "complete a task on the list",
			Action: func(c *cli.Context) {
				println("completed task: ", c.Args().First())
			},
		},
	}

	app.Run(os.Args)
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var AppHelpTemplate = `` /* 409-byte string literal not displayed */

The text template for the Default help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable.

View Source
var BashCompletionFlag = BoolFlag{
	Name: "generate-bash-completion",
}

This flag enables bash-completion for all commands and subcommands

View Source
var CommandHelpTemplate = `` /* 242-byte string literal not displayed */

The text template for the command help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable.

View Source
var HelpFlag = BoolFlag{
	Name:  "help, h",
	Usage: "show help",
}

This flag prints the help for all commands and subcommands Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand unless HideHelp is set to true)

View Source
var HelpPrinter helpPrinter = printHelp
View Source
var SubcommandHelpTemplate = `` /* 264-byte string literal not displayed */

The text template for the subcommand help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable.

View Source
var VersionFlag = BoolFlag{
	Name:  "version, v",
	Usage: "print the version",
}

This flag prints the version for the application

View Source
var VersionPrinter = printVersion

Prints version for the App

Functions

func DefaultAppComplete

func DefaultAppComplete(c *Context)

Prints the list of subcommands as the default app completion method

func ShowAppHelp

func ShowAppHelp(c *Context)

func ShowCommandCompletions

func ShowCommandCompletions(ctx *Context, command string)

Prints the custom completions for a given command

func ShowCommandHelp

func ShowCommandHelp(ctx *Context, command string)

Prints help for the given command

func ShowCompletions

func ShowCompletions(c *Context)

Prints the lists of commands within a given context

func ShowSubcommandHelp

func ShowSubcommandHelp(c *Context)

Prints help for the given subcommand

func ShowVersion

func ShowVersion(c *Context)

Prints the version number of the App

Types

type App

type App struct {
	// The name of the program. Defaults to os.Args[0]
	Name string
	// Description of the program.
	Usage string
	// Version of the program
	Version string
	// List of commands to execute
	Commands []Command
	// List of flags to parse
	Flags []Flag
	// Boolean to enable bash completion commands
	EnableBashCompletion bool
	// Boolean to hide built-in help command
	HideHelp bool
	// Boolean to hide built-in version flag
	HideVersion bool
	// An action to execute when the bash-completion flag is set
	BashComplete func(context *Context)
	// An action 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
	// An action to execute after any subcommands are run, but after the subcommand has finished
	// It is run even if Action() panics
	After func(context *Context) error
	// The action to execute when no subcommands are specified
	Action func(context *Context)
	// Execute this function if the proper command cannot be found
	CommandNotFound func(context *Context, command string)
	// Compilation date
	Compiled time.Time
	// List of all authors who contributed
	Authors []Author
	// Name of Author (Note: Use App.Authors, this is deprecated)
	Author string
	// Email of Author (Note: Use App.Authors, this is deprecated)
	Email string
	// Writer writer to write output to
	Writer io.Writer
}

App is the main structure of a cli application. It is recomended that and app be created with the cli.NewApp() function

Example
package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
)

func main() {
	// set args for examples sake
	os.Args = []string{"greet", "--name", "Jeremy"}

	app := cli.NewApp()
	app.Name = "greet"
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
	}
	app.Action = func(c *cli.Context) {
		fmt.Printf("Hello %v\n", c.String("name"))
	}
	app.Author = "Harrison"
	app.Email = "harrison@lolwut.com"
	app.Authors = []cli.Author{cli.Author{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
	app.Run(os.Args)
}
Output:

Hello Jeremy

func NewApp

func NewApp() *App

Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.

func (*App) Command

func (a *App) Command(name string) *Command

Returns the named command on App. Returns nil if the command does not exist

func (*App) Run

func (a *App) Run(arguments []string) (err error)

Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination

func (*App) RunAndExitOnError

func (a *App) RunAndExitOnError()

Another entry point to the cli app, takes care of passing arguments and error handling

func (*App) RunAsSubcommand

func (a *App) RunAsSubcommand(ctx *Context) (err error)

Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags

type Args

type Args []string

func (Args) First

func (a Args) First() string

Returns the first argument, or else a blank string

func (Args) Get

func (a Args) Get(n int) string

Returns the nth argument, or else a blank string

func (Args) Present

func (a Args) Present() bool

Checks if there are any arguments present

func (Args) Swap

func (a Args) Swap(from, to int) error

Swaps arguments at the given indexes

func (Args) Tail

func (a Args) Tail() []string

Return the rest of the arguments (not the first one) or else an empty string slice

type Author

type Author struct {
	Name  string // The Authors name
	Email string // The Authors email
}

Author represents someone who has contributed to a cli project.

func (Author) String

func (a Author) String() string

String makes Author comply to the Stringer interface, to allow an easy print in the templating process

type BoolFlag

type BoolFlag struct {
	Name   string
	Usage  string
	EnvVar string
}

func (BoolFlag) Apply

func (f BoolFlag) Apply(set *flag.FlagSet)

func (BoolFlag) String

func (f BoolFlag) String() string

type BoolTFlag

type BoolTFlag struct {
	Name   string
	Usage  string
	EnvVar string
}

func (BoolTFlag) Apply

func (f BoolTFlag) Apply(set *flag.FlagSet)

func (BoolTFlag) String

func (f BoolTFlag) String() string

type Command

type Command struct {
	// The name of the command
	Name string
	// short name of the command. Typically one character (deprecated, use `Aliases`)
	ShortName string
	// A list of aliases for the command
	Aliases []string
	// A short description of the usage of this command
	Usage string
	// A longer explanation of how the command works
	Description string
	// The function to call when checking for bash command completions
	BashComplete func(context *Context)
	// An action to execute before any sub-subcommands are run, but after the context is ready
	// If a non-nil error is returned, no sub-subcommands are run
	Before func(context *Context) error
	// An action to execute after any subcommands are run, but after the subcommand has finished
	// It is run even if Action() panics
	After func(context *Context) error
	// The function to call when this command is invoked
	Action func(context *Context)
	// List of child commands
	Subcommands []Command
	// List of flags to parse
	Flags []Flag
	// Treat all flags as normal arguments if true
	SkipFlagParsing bool
	// Boolean to hide built-in help command
	HideHelp bool
}

Command is a subcommand for a cli.App.

func (Command) HasName

func (c Command) HasName(name string) bool

Returns true if Command.Name or Command.ShortName matches given name

func (Command) Names

func (c Command) Names() []string

func (Command) Run

func (c Command) Run(ctx *Context) error

Invokes the command given the context, parses ctx.Args() to generate command-specific flags

type Context

type Context struct {
	App     *App
	Command Command
	// contains filtered or unexported fields
}

Context is a type that is passed through to each Handler action in a cli application. Context can be used to retrieve context-specific Args and parsed command-line options.

func NewContext

func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context

Creates a new context. For use in when invoking an App or Command action.

func (*Context) Args

func (c *Context) Args() Args

Returns the command line arguments associated with the context.

func (*Context) Bool

func (c *Context) Bool(name string) bool

Looks up the value of a local bool flag, returns false if no bool flag exists

func (*Context) BoolT

func (c *Context) BoolT(name string) bool

Looks up the value of a local boolT flag, returns false if no bool flag exists

func (*Context) Duration

func (c *Context) Duration(name string) time.Duration

Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists

func (*Context) FlagNames

func (c *Context) FlagNames() (names []string)

Returns a slice of flag names used in this context.

func (*Context) Float64

func (c *Context) Float64(name string) float64

Looks up the value of a local float64 flag, returns 0 if no float64 flag exists

func (*Context) Generic

func (c *Context) Generic(name string) interface{}

Looks up the value of a local generic flag, returns nil if no generic flag exists

func (*Context) GlobalBool

func (c *Context) GlobalBool(name string) bool

Looks up the value of a global bool flag, returns false if no bool flag exists

func (*Context) GlobalDuration

func (c *Context) GlobalDuration(name string) time.Duration

Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists

func (*Context) GlobalFlagNames

func (c *Context) GlobalFlagNames() (names []string)

Returns a slice of global flag names used by the app.

func (*Context) GlobalGeneric

func (c *Context) GlobalGeneric(name string) interface{}

Looks up the value of a global generic flag, returns nil if no generic flag exists

func (*Context) GlobalInt

func (c *Context) GlobalInt(name string) int

Looks up the value of a global int flag, returns 0 if no int flag exists

func (*Context) GlobalIntSlice

func (c *Context) GlobalIntSlice(name string) []int

Looks up the value of a global int slice flag, returns nil if no int slice flag exists

func (*Context) GlobalIsSet

func (c *Context) GlobalIsSet(name string) bool

Determines if the global flag was actually set

func (*Context) GlobalString

func (c *Context) GlobalString(name string) string

Looks up the value of a global string flag, returns "" if no string flag exists

func (*Context) GlobalStringSlice

func (c *Context) GlobalStringSlice(name string) []string

Looks up the value of a global string slice flag, returns nil if no string slice flag exists

func (*Context) Int

func (c *Context) Int(name string) int

Looks up the value of a local int flag, returns 0 if no int flag exists

func (*Context) IntSlice

func (c *Context) IntSlice(name string) []int

Looks up the value of a local int slice flag, returns nil if no int slice flag exists

func (*Context) IsSet

func (c *Context) IsSet(name string) bool

Determines if the flag was actually set

func (*Context) NumFlags

func (c *Context) NumFlags() int

Returns the number of flags set

func (*Context) String

func (c *Context) String(name string) string

Looks up the value of a local string flag, returns "" if no string flag exists

func (*Context) StringSlice

func (c *Context) StringSlice(name string) []string

Looks up the value of a local string slice flag, returns nil if no string slice flag exists

type DurationFlag

type DurationFlag struct {
	Name   string
	Value  time.Duration
	Usage  string
	EnvVar string
}

func (DurationFlag) Apply

func (f DurationFlag) Apply(set *flag.FlagSet)

func (DurationFlag) String

func (f DurationFlag) String() string

type Flag

type Flag interface {
	fmt.Stringer
	// Apply Flag settings to the given flag set
	Apply(*flag.FlagSet)
	// contains filtered or unexported methods
}

Flag is a common interface related to parsing flags in cli. For more advanced flag parsing techniques, it is recomended that this interface be implemented.

type Float64Flag

type Float64Flag struct {
	Name   string
	Value  float64
	Usage  string
	EnvVar string
}

func (Float64Flag) Apply

func (f Float64Flag) Apply(set *flag.FlagSet)

func (Float64Flag) String

func (f Float64Flag) String() string

type Generic

type Generic interface {
	Set(value string) error
	String() string
}

Generic is a generic parseable type identified by a specific flag

type GenericFlag

type GenericFlag struct {
	Name   string
	Value  Generic
	Usage  string
	EnvVar string
}

GenericFlag is the flag type for types implementing Generic

func (GenericFlag) Apply

func (f GenericFlag) Apply(set *flag.FlagSet)

Apply takes the flagset and calls Set on the generic flag with the value provided by the user for parsing by the flag

func (GenericFlag) String

func (f GenericFlag) String() string

String returns the string representation of the generic flag to display the help text to the user (uses the String() method of the generic flag to show the value)

type IntFlag

type IntFlag struct {
	Name   string
	Value  int
	Usage  string
	EnvVar string
}

func (IntFlag) Apply

func (f IntFlag) Apply(set *flag.FlagSet)

func (IntFlag) String

func (f IntFlag) String() string

type IntSlice

type IntSlice []int

func (*IntSlice) Set

func (f *IntSlice) Set(value string) error

func (*IntSlice) String

func (f *IntSlice) String() string

func (*IntSlice) Value

func (f *IntSlice) Value() []int

type IntSliceFlag

type IntSliceFlag struct {
	Name   string
	Value  *IntSlice
	Usage  string
	EnvVar string
}

func (IntSliceFlag) Apply

func (f IntSliceFlag) Apply(set *flag.FlagSet)

func (IntSliceFlag) String

func (f IntSliceFlag) String() string

type StringFlag

type StringFlag struct {
	Name   string
	Value  string
	Usage  string
	EnvVar string
}

func (StringFlag) Apply

func (f StringFlag) Apply(set *flag.FlagSet)

func (StringFlag) String

func (f StringFlag) String() string

type StringSlice

type StringSlice []string

func (*StringSlice) Set

func (f *StringSlice) Set(value string) error

func (*StringSlice) String

func (f *StringSlice) String() string

func (*StringSlice) Value

func (f *StringSlice) Value() []string

type StringSliceFlag

type StringSliceFlag struct {
	Name   string
	Value  *StringSlice
	Usage  string
	EnvVar string
}

func (StringSliceFlag) Apply

func (f StringSliceFlag) Apply(set *flag.FlagSet)

func (StringSliceFlag) String

func (f StringSliceFlag) String() string

Jump to

Keyboard shortcuts

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