Feat: Add epilog after help text
Similar to the Description at the top of the help text an Epilog is added at the bottom. Resolves #189
This commit is contained in:
parent
ebd7a68a06
commit
c8b9567d1b
32
README.md
32
README.md
|
@ -462,6 +462,9 @@ Options:
|
||||||
|
|
||||||
### Description strings
|
### Description strings
|
||||||
|
|
||||||
|
A descriptive message can be added at the top of the help text by implementing
|
||||||
|
a `Description` function that returns a string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type args struct {
|
type args struct {
|
||||||
Foo string
|
Foo string
|
||||||
|
@ -487,6 +490,35 @@ Options:
|
||||||
--help, -h display this help and exit
|
--help, -h display this help and exit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Similarly an epilogue can be added at the end of the help text by implementing
|
||||||
|
the `Epilogue` function.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type args struct {
|
||||||
|
Foo string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (args) Epilogue() string {
|
||||||
|
return "For more information visit github.com/alexflint/go-arg"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var args args
|
||||||
|
arg.MustParse(&args)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ ./example -h
|
||||||
|
Usage: example [--foo FOO]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--foo FOO
|
||||||
|
--help, -h display this help and exit
|
||||||
|
|
||||||
|
For more information visit github.com/alexflint/go-arg
|
||||||
|
```
|
||||||
|
|
||||||
### Subcommands
|
### Subcommands
|
||||||
|
|
||||||
*Introduced in version 1.1.0*
|
*Introduced in version 1.1.0*
|
||||||
|
|
12
parse.go
12
parse.go
|
@ -134,6 +134,7 @@ type Parser struct {
|
||||||
config Config
|
config Config
|
||||||
version string
|
version string
|
||||||
description string
|
description string
|
||||||
|
epilogue string
|
||||||
|
|
||||||
// the following field changes during processing of command line arguments
|
// the following field changes during processing of command line arguments
|
||||||
lastCmd *command
|
lastCmd *command
|
||||||
|
@ -155,6 +156,14 @@ type Described interface {
|
||||||
Description() string
|
Description() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Epilogued is the interface that the destination struct should implement to
|
||||||
|
// add an epilogue string at the bottom of the help message.
|
||||||
|
type Epilogued interface {
|
||||||
|
// Epilogue returns the string that will be printed on a line by itself
|
||||||
|
// at the end of the help message.
|
||||||
|
Epilogue() 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(t reflect.Type, visit func(field reflect.StructField, owner reflect.Type) bool) {
|
func walkFields(t reflect.Type, visit func(field reflect.StructField, owner reflect.Type) bool) {
|
||||||
walkFieldsImpl(t, visit, nil)
|
walkFieldsImpl(t, visit, nil)
|
||||||
|
@ -236,6 +245,9 @@ func NewParser(config Config, dests ...interface{}) (*Parser, error) {
|
||||||
if dest, ok := dest.(Described); ok {
|
if dest, ok := dest.(Described); ok {
|
||||||
p.description = dest.Description()
|
p.description = dest.Description()
|
||||||
}
|
}
|
||||||
|
if dest, ok := dest.(Epilogued); ok {
|
||||||
|
p.epilogue = dest.Epilogue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &p, nil
|
return &p, nil
|
||||||
|
|
4
usage.go
4
usage.go
|
@ -290,6 +290,10 @@ func (p *Parser) writeHelpForSubcommand(w io.Writer, cmd *command) {
|
||||||
printTwoCols(w, subcmd.name, subcmd.help, "", "")
|
printTwoCols(w, subcmd.name, subcmd.help, "", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.epilogue != "" {
|
||||||
|
fmt.Fprintln(w, "\n"+p.epilogue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) printOption(w io.Writer, spec *spec) {
|
func (p *Parser) printOption(w io.Writer, spec *spec) {
|
||||||
|
|
|
@ -285,6 +285,37 @@ Options:
|
||||||
assert.Equal(t, expectedUsage, strings.TrimSpace(usage.String()))
|
assert.Equal(t, expectedUsage, strings.TrimSpace(usage.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type epilogued struct{}
|
||||||
|
|
||||||
|
// Epilogued returns the epilogue for this program
|
||||||
|
func (epilogued) Epilogue() string {
|
||||||
|
return "For more information visit github.com/alexflint/go-arg"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsageWithEpilogue(t *testing.T) {
|
||||||
|
expectedUsage := "Usage: example"
|
||||||
|
|
||||||
|
expectedHelp := `
|
||||||
|
Usage: example
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--help, -h display this help and exit
|
||||||
|
|
||||||
|
For more information visit github.com/alexflint/go-arg
|
||||||
|
`
|
||||||
|
os.Args[0] = "example"
|
||||||
|
p, err := NewParser(Config{}, &epilogued{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var help bytes.Buffer
|
||||||
|
p.WriteHelp(&help)
|
||||||
|
assert.Equal(t, expectedHelp[1:], help.String())
|
||||||
|
|
||||||
|
var usage bytes.Buffer
|
||||||
|
p.WriteUsage(&usage)
|
||||||
|
assert.Equal(t, expectedUsage, strings.TrimSpace(usage.String()))
|
||||||
|
}
|
||||||
|
|
||||||
func TestUsageForRequiredPositionals(t *testing.T) {
|
func TestUsageForRequiredPositionals(t *testing.T) {
|
||||||
expectedUsage := "Usage: example REQUIRED1 REQUIRED2\n"
|
expectedUsage := "Usage: example REQUIRED1 REQUIRED2\n"
|
||||||
var args struct {
|
var args struct {
|
||||||
|
|
Loading…
Reference in New Issue