summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Flint <[email protected]>2016-09-08 21:18:19 -0700
committerAlex Flint <[email protected]>2016-09-08 21:18:19 -0700
commitc453aa1a28b0cc9baac51cf5cc04df2688d3cd25 (patch)
tree7503a5a4f6fad156748c240cb7bec498e8715204
parent34954f45cec4632059c6aa8ca6f769a748464cf7 (diff)
add support for version string
-rw-r--r--parse.go43
-rw-r--r--usage.go7
-rw-r--r--usage_test.go29
3 files changed, 68 insertions, 11 deletions
diff --git a/parse.go b/parse.go
index b1193d0..f5fdd7f 100644
--- a/parse.go
+++ b/parse.go
@@ -27,6 +27,9 @@ type spec struct {
// ErrHelp indicates that -h or --help were provided
var ErrHelp = errors.New("help requested by user")
+// ErrVersion indicates that --version was provided
+var ErrVersion = errors.New("version requested by user")
+
// MustParse processes command line arguments and exits upon failure
func MustParse(dest ...interface{}) *Parser {
p, err := NewParser(Config{}, dest...)
@@ -39,6 +42,10 @@ func MustParse(dest ...interface{}) *Parser {
p.WriteHelp(os.Stdout)
os.Exit(0)
}
+ if err == ErrVersion {
+ fmt.Println(p.version)
+ os.Exit(0)
+ }
if err != nil {
p.Fail(err.Error())
}
@@ -61,14 +68,28 @@ type Config struct {
// Parser represents a set of command line options with destination values
type Parser struct {
- spec []*spec
- config Config
+ spec []*spec
+ config Config
+ version string
+}
+
+// Versioned is the interface that the destination struct should implement to
+// make a version string appear at the top of the help message.
+type Versioned interface {
+ // Version returns the version string that will be printed on a line by itself
+ // at the top of the help message.
+ Version() string
}
// NewParser constructs a parser from a list of destination structs
func NewParser(config Config, dests ...interface{}) (*Parser, error) {
- var specs []*spec
+ p := Parser{
+ config: config,
+ }
for _, dest := range dests {
+ if dest, ok := dest.(Versioned); ok {
+ p.version = dest.Version()
+ }
v := reflect.ValueOf(dest)
if v.Kind() != reflect.Ptr {
panic(fmt.Sprintf("%s is not a pointer (did you forget an ampersand?)", v.Type()))
@@ -138,19 +159,16 @@ func NewParser(config Config, dests ...interface{}) (*Parser, error) {
}
}
}
- specs = append(specs, &spec)
+ p.spec = append(p.spec, &spec)
}
}
- if config.Program == "" {
- config.Program = "program"
+ if p.config.Program == "" {
+ p.config.Program = "program"
if len(os.Args) > 0 {
- config.Program = filepath.Base(os.Args[0])
+ p.config.Program = filepath.Base(os.Args[0])
}
}
- return &Parser{
- spec: specs,
- config: config,
- }, nil
+ return &p, nil
}
// Parse processes the given command line option, storing the results in the field
@@ -161,6 +179,9 @@ func (p *Parser) Parse(args []string) error {
if arg == "-h" || arg == "--help" {
return ErrHelp
}
+ if arg == "--version" {
+ return ErrVersion
+ }
if arg == "--" {
break
}
diff --git a/usage.go b/usage.go
index 2ee3953..f096f58 100644
--- a/usage.go
+++ b/usage.go
@@ -29,6 +29,10 @@ func (p *Parser) WriteUsage(w io.Writer) {
}
}
+ if p.version != "" {
+ fmt.Fprintln(w, p.version)
+ }
+
fmt.Fprintf(w, "usage: %s", p.config.Program)
// write the option component of the usage message
@@ -97,6 +101,9 @@ func (p *Parser) WriteHelp(w io.Writer) {
// write the list of built in options
printOption(w, &spec{boolean: true, long: "help", short: "h", help: "display this help and exit"})
+ if p.version != "" {
+ printOption(w, &spec{boolean: true, long: "version", help: "display version and exit"})
+ }
}
func printOption(w io.Writer, spec *spec) {
diff --git a/usage_test.go b/usage_test.go
index b63a7d0..e60efdb 100644
--- a/usage_test.go
+++ b/usage_test.go
@@ -100,3 +100,32 @@ options:
p.WriteHelp(&help)
assert.Equal(t, expectedHelp, help.String())
}
+
+type versioned struct{}
+
+// Version returns the version for this program
+func (versioned) Version() string {
+ return "example 3.2.1"
+}
+
+func TestUsageWithVersion(t *testing.T) {
+ expectedHelp := `example 3.2.1
+usage: example
+
+options:
+ --help, -h display this help and exit
+ --version display version and exit
+`
+ os.Args[0] = "example"
+ p, err := NewParser(Config{}, &versioned{})
+ require.NoError(t, err)
+
+ var help bytes.Buffer
+ p.WriteHelp(&help)
+ actual := help.String()
+ t.Logf("Expected:\n%s", expectedHelp)
+ t.Logf("Actual:\n%s", actual)
+ if expectedHelp != actual {
+ t.Fail()
+ }
+}