summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.go85
-rw-r--r--usage.go30
2 files changed, 40 insertions, 75 deletions
diff --git a/parse.go b/parse.go
index 119efbd..dfa3421 100644
--- a/parse.go
+++ b/parse.go
@@ -3,9 +3,7 @@ package arg
import (
"errors"
"fmt"
- "io"
"os"
- "path/filepath"
"reflect"
"strconv"
"strings"
@@ -23,10 +21,10 @@ type spec struct {
wasPresent bool
}
-// Parse returns this value to indicate that -h or --help were provided
+// ErrHelp indicates that -h or --help were provided
var ErrHelp = errors.New("help requested by user")
-// MustParse processes command line arguments and exits upon failure.
+// MustParse processes command line arguments and exits upon failure
func MustParse(dest ...interface{}) {
p, err := NewParser(dest...)
if err != nil {
@@ -34,19 +32,20 @@ func MustParse(dest ...interface{}) {
os.Exit(1)
}
err = p.Parse(os.Args[1:])
+ if err == ErrHelp {
+ p.WriteUsage(os.Stdout)
+ os.Exit(0)
+ }
if err != nil {
- fmt.Println(err)
- writeUsage(os.Stdout, filepath.Base(os.Args[0]), p.spec)
- os.Exit(1)
+ p.Fail(err.Error())
}
}
-// Parse processes command line arguments and stores them in dest.
+// Parse processes command line arguments and stores them in dest
func Parse(dest ...interface{}) error {
p, err := NewParser(dest...)
if err != nil {
- fmt.Println(err)
- os.Exit(1)
+ return err
}
return p.Parse(os.Args[1:])
}
@@ -57,44 +56,7 @@ type Parser struct {
}
// NewParser constructs a parser from a list of destination structs
-func NewParser(dest ...interface{}) (*Parser, error) {
- spec, err := extractSpec(dest...)
- if err != nil {
- return nil, err
- }
- return &Parser{spec: spec}, nil
-}
-
-// Parse processes the given command line option, storing the results in the field
-// of the structs from which NewParser was constructed
-func (p *Parser) Parse(args []string) error {
- // If -h or --help were specified then print usage
- for _, arg := range args {
- if arg == "-h" || arg == "--help" {
- return ErrHelp
- }
- if arg == "--" {
- break
- }
- }
-
- // Process all command line arguments
- err := process(p.spec, args)
- if err != nil {
- return err
- }
-
- // Validate
- return validate(p.spec)
-}
-
-// WriteUsage writes usage information to the given writer
-func (p *Parser) WriteUsage(w io.Writer) {
- writeUsage(w, filepath.Base(os.Args[0]), p.spec)
-}
-
-// extractSpec gets specifications for each argument from the tags in a struct
-func extractSpec(dests ...interface{}) ([]*spec, error) {
+func NewParser(dests ...interface{}) (*Parser, error) {
var specs []*spec
for _, dest := range dests {
v := reflect.ValueOf(dest)
@@ -169,10 +131,33 @@ func extractSpec(dests ...interface{}) ([]*spec, error) {
specs = append(specs, &spec)
}
}
- return specs, nil
+ return &Parser{spec: specs}, nil
+}
+
+// Parse processes the given command line option, storing the results in the field
+// of the structs from which NewParser was constructed
+func (p *Parser) Parse(args []string) error {
+ // If -h or --help were specified then print usage
+ for _, arg := range args {
+ if arg == "-h" || arg == "--help" {
+ return ErrHelp
+ }
+ if arg == "--" {
+ break
+ }
+ }
+
+ // Process all command line arguments
+ err := process(p.spec, args)
+ if err != nil {
+ return err
+ }
+
+ // Validate
+ return validate(p.spec)
}
-// process goes through arguments the arguments one-by-one, parses them, and assigns the result to
+// process goes through arguments one-by-one, parses them, and assigns the result to
// the underlying struct field
func process(specs []*spec, args []string) error {
// construct a map from --option to spec
diff --git a/usage.go b/usage.go
index fdc2248..689da73 100644
--- a/usage.go
+++ b/usage.go
@@ -9,37 +9,17 @@ import (
"strings"
)
-// Usage prints usage information to stdout and exits with status zero
-func Usage(dest ...interface{}) {
- if err := WriteUsage(os.Stdout, dest...); err != nil {
- fmt.Println(err)
- }
- os.Exit(0)
-}
-
// Fail prints usage information to stdout and exits with non-zero status
-func Fail(msg string, dest ...interface{}) {
+func (p *Parser) Fail(msg string) {
fmt.Println(msg)
- if err := WriteUsage(os.Stdout, dest...); err != nil {
- fmt.Println(err)
- }
+ p.WriteUsage(os.Stdout)
os.Exit(1)
}
// WriteUsage writes usage information to the given writer
-func WriteUsage(w io.Writer, dest ...interface{}) error {
- spec, err := extractSpec(dest...)
- if err != nil {
- return err
- }
- writeUsage(w, filepath.Base(os.Args[0]), spec)
- return nil
-}
-
-// writeUsage writes usage information to the given writer
-func writeUsage(w io.Writer, cmd string, specs []*spec) {
+func (p *Parser) WriteUsage(w io.Writer) {
var positionals, options []*spec
- for _, spec := range specs {
+ for _, spec := range p.spec {
if spec.positional {
positionals = append(positionals, spec)
} else {
@@ -47,7 +27,7 @@ func writeUsage(w io.Writer, cmd string, specs []*spec) {
}
}
- fmt.Fprint(w, "usage: %s ", cmd)
+ fmt.Fprintf(w, "usage: %s ", filepath.Base(os.Args[0]))
// write the option component of the one-line usage message
for _, spec := range options {