add support for description string
This commit is contained in:
parent
7c77c70f85
commit
db27431153
27
README.md
27
README.md
|
@ -263,6 +263,33 @@ usage: example [--name NAME]
|
||||||
error: error processing --name: missing period in "oops"
|
error: error processing --name: missing period in "oops"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Description strings
|
||||||
|
|
||||||
|
```go
|
||||||
|
type args struct {
|
||||||
|
Foo string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (args) Description() string {
|
||||||
|
return "this program does this and that"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var args args
|
||||||
|
arg.MustParse(&args)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ ./example -h
|
||||||
|
this program does this and that
|
||||||
|
usage: example [--foo FOO]
|
||||||
|
|
||||||
|
options:
|
||||||
|
--foo FOO
|
||||||
|
--help, -h display this help and exit
|
||||||
|
```
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
https://godoc.org/github.com/alexflint/go-arg
|
https://godoc.org/github.com/alexflint/go-arg
|
||||||
|
|
18
parse.go
18
parse.go
|
@ -67,9 +67,10 @@ type Config struct {
|
||||||
|
|
||||||
// Parser represents a set of command line options with destination values
|
// Parser represents a set of command line options with destination values
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
spec []*spec
|
spec []*spec
|
||||||
config Config
|
config Config
|
||||||
version string
|
version string
|
||||||
|
description string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Versioned is the interface that the destination struct should implement to
|
// Versioned is the interface that the destination struct should implement to
|
||||||
|
@ -80,6 +81,14 @@ type Versioned interface {
|
||||||
Version() string
|
Version() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Described is the interface that the destination struct should implement to
|
||||||
|
// make a description string appear at the top of the help message.
|
||||||
|
type Described interface {
|
||||||
|
// Description returns the string that will be printed on a line by itself
|
||||||
|
// at the top of the help message.
|
||||||
|
Description() string
|
||||||
|
}
|
||||||
|
|
||||||
// walkFields calls a function for each field of a struct, recursively expanding struct fields.
|
// walkFields calls a function for each field of a struct, recursively expanding struct fields.
|
||||||
func walkFields(v reflect.Value, visit func(field reflect.StructField, val reflect.Value, owner reflect.Type) bool) {
|
func walkFields(v reflect.Value, visit func(field reflect.StructField, val reflect.Value, owner reflect.Type) bool) {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
|
@ -102,6 +111,9 @@ func NewParser(config Config, dests ...interface{}) (*Parser, error) {
|
||||||
if dest, ok := dest.(Versioned); ok {
|
if dest, ok := dest.(Versioned); ok {
|
||||||
p.version = dest.Version()
|
p.version = dest.Version()
|
||||||
}
|
}
|
||||||
|
if dest, ok := dest.(Described); ok {
|
||||||
|
p.description = dest.Description()
|
||||||
|
}
|
||||||
v := reflect.ValueOf(dest)
|
v := reflect.ValueOf(dest)
|
||||||
if v.Kind() != reflect.Ptr {
|
if v.Kind() != reflect.Ptr {
|
||||||
panic(fmt.Sprintf("%s is not a pointer (did you forget an ampersand?)", v.Type()))
|
panic(fmt.Sprintf("%s is not a pointer (did you forget an ampersand?)", v.Type()))
|
||||||
|
|
3
usage.go
3
usage.go
|
@ -29,6 +29,9 @@ func (p *Parser) WriteUsage(w io.Writer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.description != "" {
|
||||||
|
fmt.Fprintln(w, p.description)
|
||||||
|
}
|
||||||
if p.version != "" {
|
if p.version != "" {
|
||||||
fmt.Fprintln(w, p.version)
|
fmt.Fprintln(w, p.version)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,3 +129,31 @@ options:
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type described struct{}
|
||||||
|
|
||||||
|
// Described returns the description for this program
|
||||||
|
func (described) Description() string {
|
||||||
|
return "this program does this and that"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsageWithDescription(t *testing.T) {
|
||||||
|
expectedHelp := `this program does this and that
|
||||||
|
usage: example
|
||||||
|
|
||||||
|
options:
|
||||||
|
--help, -h display this help and exit
|
||||||
|
`
|
||||||
|
os.Args[0] = "example"
|
||||||
|
p, err := NewParser(Config{}, &described{})
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue