summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWlazlo, Matt <[email protected]>2018-04-13 14:46:24 +1000
committerWlazlo, Matt <[email protected]>2018-04-13 14:46:24 +1000
commitd4cc703210ff08d7bc4f73bfbec1e51eda29a5a4 (patch)
tree3e554efc7cbda3dd03ae15a73bb4a54782fc23fb
parent0cc8e30fd64c8c71d094be299ad424da93ef9aed (diff)
Custom parsers implementing encoding.TextMarshaler() can have default values printed via --help
-rw-r--r--README.md18
-rw-r--r--usage.go11
-rw-r--r--usage_test.go31
3 files changed, 56 insertions, 4 deletions
diff --git a/README.md b/README.md
index 18dc556..f3d1bfc 100644
--- a/README.md
+++ b/README.md
@@ -265,15 +265,33 @@ func (n *NameDotName) UnmarshalText(b []byte) error {
return nil
}
+// optional, implement in case you want to use defaults
+func (n *NameDotName) MarshalText() (text []byte, err error) {
+ text = []byte(fmt.Sprintf("%s.%s", n.Head, n.Tail))
+ return
+}
+
func main() {
var args struct {
Name *NameDotName
}
+ // set default
+ args.Name = &NameDotName{"file", "txt"}
arg.MustParse(&args)
fmt.Printf("%#v\n", args.Name)
}
```
```shell
+$ ./example --help
+Usage: test [--name NAME]
+
+Options:
+ --name NAME [default: file.txt]
+ --help, -h display this help and exit
+
+$ ./example
+&main.NameDotName{Head:"file", Tail:"txt"}
+
$ ./example --name=foo.bar
&main.NameDotName{Head:"foo", Tail:"bar"}
diff --git a/usage.go b/usage.go
index 4652b36..656ee9a 100644
--- a/usage.go
+++ b/usage.go
@@ -6,6 +6,7 @@ import (
"os"
"reflect"
"strings"
+ "encoding"
)
// the width of the left column
@@ -134,7 +135,15 @@ func printOption(w io.Writer, spec *spec) {
if v.IsValid() {
z := reflect.Zero(v.Type())
if (v.Type().Comparable() && z.Type().Comparable() && v.Interface() != z.Interface()) || v.Kind() == reflect.Slice && !v.IsNil() {
- fmt.Fprintf(w, " [default: %v]", v)
+ if scalar, ok := v.Interface().(encoding.TextMarshaler); ok {
+ if value, err := scalar.MarshalText(); err != nil {
+ fmt.Fprintf(w, " [default: error: %v]", err)
+ } else {
+ fmt.Fprintf(w, " [default: %v]", string(value))
+ }
+ } else {
+ fmt.Fprintf(w, " [default: %v]", v)
+ }
}
}
fmt.Fprint(w, "\n")
diff --git a/usage_test.go b/usage_test.go
index 940bf40..4aa2f24 100644
--- a/usage_test.go
+++ b/usage_test.go
@@ -7,12 +7,34 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "strings"
+ "fmt"
)
+type NameDotName struct {
+ Head, Tail string
+}
+
+func (n *NameDotName) UnmarshalText(b []byte) error {
+ s := string(b)
+ pos := strings.Index(s, ".")
+ if pos == -1 {
+ return fmt.Errorf("missing period in %s", s)
+ }
+ n.Head = s[:pos]
+ n.Tail = s[pos+1:]
+ return nil
+}
+
+func (n *NameDotName) MarshalText() (text []byte, err error) {
+ text = []byte(fmt.Sprintf("%s.%s", n.Head, n.Tail))
+ return
+}
+
func TestWriteUsage(t *testing.T) {
- expectedUsage := "Usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--values VALUES] [--workers WORKERS] INPUT [OUTPUT [OUTPUT ...]]\n"
+ expectedUsage := "Usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--values VALUES] [--workers WORKERS] [--file FILE] INPUT [OUTPUT [OUTPUT ...]]\n"
- expectedHelp := `Usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--values VALUES] [--workers WORKERS] INPUT [OUTPUT [OUTPUT ...]]
+ expectedHelp := `Usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--values VALUES] [--workers WORKERS] [--file FILE] INPUT [OUTPUT [OUTPUT ...]]
Positional arguments:
INPUT
@@ -29,6 +51,7 @@ Options:
--values VALUES Values [default: [3.14 42 256]]
--workers WORKERS, -w WORKERS
number of workers to start
+ --file FILE, -f FILE File with mandatory extension [default: scratch.txt]
--help, -h display this help and exit
`
var args struct {
@@ -42,11 +65,13 @@ Options:
Ids []int64 `help:"Ids"`
Values []float64 `help:"Values"`
Workers int `arg:"-w,env:WORKERS" help:"number of workers to start"`
+ File *NameDotName `arg:"-f" help:"File with mandatory extension"`
}
args.Name = "Foo Bar"
args.Value = 42
args.Values = []float64{3.14, 42, 256}
- p, err := NewParser(Config{}, &args)
+ args.File = &NameDotName{"scratch", "txt"}
+ p, err := NewParser(Config{"example"}, &args)
require.NoError(t, err)
os.Args[0] = "example"