implement-modules #43

Closed
sashakoshka wants to merge 502 commits from implement-modules into main
Showing only changes of commit 385657a5c1 - Show all commits

View File

@ -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