implement-modules #43
36
cli/cli.go
36
cli/cli.go
@ -6,11 +6,16 @@ import "errors"
|
||||
import "strings"
|
||||
import "strconv"
|
||||
|
||||
// Cli represents a command line interface. It is not tied to os.Args, and it is
|
||||
// possible to create multiple Cli's to have so many sub-commands in one
|
||||
// program.
|
||||
type Cli struct {
|
||||
// Description describes the application.
|
||||
Description string
|
||||
|
||||
// The syntax description of the command.
|
||||
// The syntax description of the command. It appears in Usage after the
|
||||
// name of the program (os.Args[0]). If not specified, "[OPTIONS]..."
|
||||
// will be used instead.
|
||||
Syntax string
|
||||
|
||||
// Flag is a set of flags to parse.
|
||||
@ -20,6 +25,9 @@ type Cli struct {
|
||||
Args []string
|
||||
}
|
||||
|
||||
// New creates a new Cli from a command description and a set of flags. These
|
||||
// flags should be created as variables before passing them to New(), so that
|
||||
// their values can be extracted after Parse is called.
|
||||
func New (description string, flags ...*Flag) *Cli {
|
||||
return &Cli {
|
||||
Description: description,
|
||||
@ -27,6 +35,9 @@ func New (description string, flags ...*Flag) *Cli {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse parses the given set of command line arguments according to the flags
|
||||
// defined within the Cli. The first element of the argument slice is always
|
||||
// dropped, because it is assumed that it just contains the command name.
|
||||
func (this *Cli) Parse (args []string) error {
|
||||
// strip out program name
|
||||
if len(args) > 0 { args = args[1:] }
|
||||
@ -95,6 +106,8 @@ func (this *Cli) Parse (args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseOrExit is like Parse, but if an error occurs while parsing the argument
|
||||
// list, it prints out Usage and exits with error status 2.
|
||||
func (this *Cli) ParseOrExit (args []string) {
|
||||
err := this.Parse(args)
|
||||
if err != nil {
|
||||
@ -104,6 +117,8 @@ func (this *Cli) ParseOrExit (args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// ShortFlag searches for and returns the flag with the given short form. If it
|
||||
// was found, it returns true. If it was not found, it returns nil, false.
|
||||
func (this *Cli) ShortFlag (short rune) (*Flag, bool) {
|
||||
if short == 0 { return nil, false }
|
||||
for _, flag := range this.Flags {
|
||||
@ -112,6 +127,8 @@ func (this *Cli) ShortFlag (short rune) (*Flag, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// LongFlag searches for and returns the flag with the given long form. If it
|
||||
// was found, it returns true. If it was not found, it returns nil, false.
|
||||
func (this *Cli) LongFlag (long string) (*Flag, bool) {
|
||||
if long == "" { return nil, false }
|
||||
for _, flag := range this.Flags {
|
||||
@ -120,6 +137,7 @@ func (this *Cli) LongFlag (long string) (*Flag, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Usage prints out usage/help information.
|
||||
func (this *Cli) Usage () {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s ", os.Args[0])
|
||||
if this.Syntax == "" {
|
||||
@ -149,6 +167,7 @@ func (this *Cli) Usage () {
|
||||
}
|
||||
}
|
||||
|
||||
// Flag is a command line option.
|
||||
type Flag struct {
|
||||
Short rune // The short form of the flag (-l)
|
||||
Long string // Long form of the flag (--long-form)
|
||||
@ -167,6 +186,7 @@ type Flag struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
// String returns --<LongForm> if specified, and if not returns -<ShortForm>
|
||||
func (this *Flag) String () string {
|
||||
if this.Long == "" {
|
||||
return fmt.Sprintf("-%c", this.Short)
|
||||
@ -175,7 +195,8 @@ func (this *Flag) String () string {
|
||||
}
|
||||
}
|
||||
|
||||
func NewFlag(short rune, long string, help string) *Flag {
|
||||
// NewFlag creates a new flag that does not take in a value.
|
||||
func NewFlag (short rune, long string, help string) *Flag {
|
||||
return &Flag {
|
||||
Short: short,
|
||||
Long: long,
|
||||
@ -183,7 +204,12 @@ func NewFlag(short rune, long string, help string) *Flag {
|
||||
}
|
||||
}
|
||||
|
||||
func NewInputFlag(short rune, long string, help string, defaul string, validate func (string) error) *Flag {
|
||||
// NewInputFlag creates a new flag that does take in a value. This function will
|
||||
// panic if the given validation function is nil.
|
||||
func NewInputFlag (short rune, long string, help string, defaul string, validate func (string) error) *Flag {
|
||||
if validate != nil {
|
||||
panic("validate must be non-nil for a flag to take in a value")
|
||||
}
|
||||
return &Flag {
|
||||
Short: short,
|
||||
Long: long,
|
||||
@ -193,10 +219,14 @@ func NewInputFlag(short rune, long string, help string, defaul string, validate
|
||||
}
|
||||
}
|
||||
|
||||
// ValString is a validation function that always returns nil, accepting any
|
||||
// string.
|
||||
func ValString (value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValInt is a validation function that returns an error if the value is not an
|
||||
// integer.
|
||||
func ValInt (value string) error {
|
||||
_, err := strconv.Atoi(value)
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user