implement-modules #43
36
cli/cli.go
36
cli/cli.go
@ -6,11 +6,16 @@ import "errors"
|
|||||||
import "strings"
|
import "strings"
|
||||||
import "strconv"
|
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 {
|
type Cli struct {
|
||||||
// Description describes the application.
|
// Description describes the application.
|
||||||
Description string
|
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
|
Syntax string
|
||||||
|
|
||||||
// Flag is a set of flags to parse.
|
// Flag is a set of flags to parse.
|
||||||
@ -20,6 +25,9 @@ type Cli struct {
|
|||||||
Args []string
|
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 {
|
func New (description string, flags ...*Flag) *Cli {
|
||||||
return &Cli {
|
return &Cli {
|
||||||
Description: description,
|
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 {
|
func (this *Cli) Parse (args []string) error {
|
||||||
// strip out program name
|
// strip out program name
|
||||||
if len(args) > 0 { args = args[1:] }
|
if len(args) > 0 { args = args[1:] }
|
||||||
@ -95,6 +106,8 @@ func (this *Cli) Parse (args []string) error {
|
|||||||
return nil
|
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) {
|
func (this *Cli) ParseOrExit (args []string) {
|
||||||
err := this.Parse(args)
|
err := this.Parse(args)
|
||||||
if err != nil {
|
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) {
|
func (this *Cli) ShortFlag (short rune) (*Flag, bool) {
|
||||||
if short == 0 { return nil, false }
|
if short == 0 { return nil, false }
|
||||||
for _, flag := range this.Flags {
|
for _, flag := range this.Flags {
|
||||||
@ -112,6 +127,8 @@ func (this *Cli) ShortFlag (short rune) (*Flag, bool) {
|
|||||||
return nil, false
|
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) {
|
func (this *Cli) LongFlag (long string) (*Flag, bool) {
|
||||||
if long == "" { return nil, false }
|
if long == "" { return nil, false }
|
||||||
for _, flag := range this.Flags {
|
for _, flag := range this.Flags {
|
||||||
@ -120,6 +137,7 @@ func (this *Cli) LongFlag (long string) (*Flag, bool) {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Usage prints out usage/help information.
|
||||||
func (this *Cli) Usage () {
|
func (this *Cli) Usage () {
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s ", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage: %s ", os.Args[0])
|
||||||
if this.Syntax == "" {
|
if this.Syntax == "" {
|
||||||
@ -149,6 +167,7 @@ func (this *Cli) Usage () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flag is a command line option.
|
||||||
type Flag struct {
|
type Flag struct {
|
||||||
Short rune // The short form of the flag (-l)
|
Short rune // The short form of the flag (-l)
|
||||||
Long string // Long form of the flag (--long-form)
|
Long string // Long form of the flag (--long-form)
|
||||||
@ -167,6 +186,7 @@ type Flag struct {
|
|||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns --<LongForm> if specified, and if not returns -<ShortForm>
|
||||||
func (this *Flag) String () string {
|
func (this *Flag) String () string {
|
||||||
if this.Long == "" {
|
if this.Long == "" {
|
||||||
return fmt.Sprintf("-%c", this.Short)
|
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 {
|
return &Flag {
|
||||||
Short: short,
|
Short: short,
|
||||||
Long: long,
|
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 {
|
return &Flag {
|
||||||
Short: short,
|
Short: short,
|
||||||
Long: long,
|
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 {
|
func ValString (value string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValInt is a validation function that returns an error if the value is not an
|
||||||
|
// integer.
|
||||||
func ValInt (value string) error {
|
func ValInt (value string) error {
|
||||||
_, err := strconv.Atoi(value)
|
_, err := strconv.Atoi(value)
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user