Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand All @@ -31,7 +31,7 @@ Usage:
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--speed=<kn> Speed in knots [default: 10, env: SPEED].
--moored Moored (anchored) mine.
--drifting Drifting mine.`

Expand All @@ -47,13 +47,13 @@ Options:
⚠ Use the alias "docopt-go". To use docopt in your Go code:

```go
import "github.com/docopt/docopt-go"
import "github.com/ps78674/docopt.go"
```

To install docopt in your `$GOPATH`:

```console
$ go get github.com/docopt/docopt-go
$ go get github.com/ps78674/docopt.go
```

## API
Expand Down Expand Up @@ -103,7 +103,7 @@ var config struct {
opts.Bind(&config)
```

More documentation is available at [godoc.org](https://godoc.org/github.com/docopt/docopt-go).
More documentation is available at [godoc.org](https://godoc.org/github.com/ps78674/docopt.go).

## Unit Testing

Expand Down
15 changes: 11 additions & 4 deletions docopt.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ func parseOption(optionDescription string) *pattern {
var value interface{}
value = false

reDefault := regexp.MustCompile(`(?i)\[default: (.*)\]`)
reDefault := regexp.MustCompile(`(?i)\[.*default: ([^,]*).*[\]]`)
reEnv := regexp.MustCompile(`(?i)\[.*env: ([^,]*).*[\]]`)
for _, s := range strings.Fields(options) {
if strings.HasPrefix(s, "--") {
long = s
Expand All @@ -297,10 +298,16 @@ func parseOption(optionDescription string) *pattern {
argcount = 1
}
if argcount > 0 {
matched := reDefault.FindAllStringSubmatch(description, -1)
if len(matched) > 0 {
if matched := reDefault.FindAllStringSubmatch(description, -1); len(matched) > 0 {
value = matched[0][1]
} else {
}
if matched := reEnv.FindAllStringSubmatch(description, -1); len(matched) > 0 {
v, ok := os.LookupEnv(matched[0][1])
if ok {
value = v
}
}
if value == false {
value = nil
}
}
Expand Down
9 changes: 9 additions & 0 deletions docopt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,15 @@ func TestDefaultValueForPositionalArguments(t *testing.T) {
}
}

func TestEnvValueForPositionalArguments(t *testing.T) {
os.Setenv("DATA", "a b")
defer os.Unsetenv("DATA")
doc := "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [env: DATA]"
if v, err := testParser.ParseArgs(doc, []string{}, ""); reflect.DeepEqual(v, Opts{"--data": []string{"a", "b"}}) != true {
t.Error(err)
}
}

func TestIssue59(t *testing.T) {
if v, err := testParser.ParseArgs("usage: prog --long=<a>", []string{"--long="}, ""); reflect.DeepEqual(v, Opts{"--long": ""}) != true {
t.Error(err)
Expand Down
2 changes: 1 addition & 1 deletion examples/arguments/arguments.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

var usage = `Usage: arguments [-vqrh] [FILE] ...
Expand Down
2 changes: 1 addition & 1 deletion examples/arguments/arguments_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"github.com/docopt/docopt-go/examples"
"github.com/ps78674/docopt.go/examples"
)

func Example() {
Expand Down
2 changes: 1 addition & 1 deletion examples/calculator/calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

var usage = `Not a serious example.
Expand Down
2 changes: 1 addition & 1 deletion examples/calculator/calculator_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"github.com/docopt/docopt-go/examples"
"github.com/ps78674/docopt.go/examples"
)

func Example() {
Expand Down
2 changes: 1 addition & 1 deletion examples/config_file/config_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
"strings"
)

Expand Down
2 changes: 1 addition & 1 deletion examples/counted/counted.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

var usage = `Usage: counted --help
Expand Down
2 changes: 1 addition & 1 deletion examples/counted/counted_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"github.com/docopt/docopt-go/examples"
"github.com/ps78674/docopt.go/examples"
)

func Example() {
Expand Down
2 changes: 1 addition & 1 deletion examples/examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"sort"
"strings"

"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

// TestUsage is a helper used to test the output from the examples in this folder.
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/branch/git_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/checkout/git_checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/clone/git_clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/fakegit.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
"os"
"os/exec"
)
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/push/git_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/fake-git/remote/git_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/naval_fate/naval_fate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/odd_even/odd_even.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/options_shortcut/options_shortcut.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/quick/quick.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/type_assert/type_assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"fmt"
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/unit_test/unit_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"github.com/docopt/docopt-go"
"github.com/ps78674/docopt.go"
"reflect"
"testing"
)
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/ps78674/docopt.go

go 1.17
21 changes: 16 additions & 5 deletions opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
"unicode"
)

Expand Down Expand Up @@ -162,11 +163,12 @@ func (o Opts) Bind(v interface{}) error {
}
return newError("mapping of %q is not found in given struct, or is an unexported field", k)
}
fieldVal := structVal.Field(i)
zeroVal := reflect.Zero(fieldVal.Type())
if !reflect.DeepEqual(fieldVal.Interface(), zeroVal.Interface()) {
return newError("%q field is non-zero, will be overwritten by value of %q", structType.Field(i).Name, k)
}
// Allow use of non-zero struct fields for bind
// fieldVal := structVal.Field(i)
// zeroVal := reflect.Zero(fieldVal.Type())
// if !reflect.DeepEqual(fieldVal.Interface(), zeroVal.Interface()) {
// return newError("%q field is non-zero, will be overwritten by value of %q", structType.Field(i).Name, k)
// }
indexMap[k] = i
}

Expand Down Expand Up @@ -199,6 +201,15 @@ func (o Opts) Bind(v interface{}) error {
// Try to convert the value and assign if able.
switch field.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ft := field.Type()
if ft.PkgPath() == "time" && ft.Name() == "Duration" {
if s, err := o.String(k); err == nil {
if d, err := time.ParseDuration(s); err == nil {
field.SetInt(int64(d))
continue
}
}
}
if x, err := o.Int(k); err == nil {
field.SetInt(int64(x))
continue
Expand Down
43 changes: 25 additions & 18 deletions opts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"reflect"
"strings"
"testing"
"time"
)

func TestOptsUsage(t *testing.T) {
Expand Down Expand Up @@ -141,13 +142,14 @@ func TestOptsBind(t *testing.T) {
type testTypedOptions struct {
secret int `docopt:"-s"`

V bool
Number int16
Idle float32
Pointer uintptr `docopt:"<ptr>"`
Ints []int `docopt:"<values>"`
Strings []string `docopt:"STRINGS"`
Iface interface{} `docopt:"IFACE"`
V bool
Number int16
Idle float32
Pointer uintptr `docopt:"<ptr>"`
Ints []int `docopt:"<values>"`
Strings []string `docopt:"STRINGS"`
Iface interface{} `docopt:"IFACE"`
Duration time.Duration
}

func TestBindErrors(t *testing.T) {
Expand Down Expand Up @@ -244,6 +246,10 @@ func TestBindSuccess(t *testing.T) {
`Usage: prog [--help]`,
`prog --help`,
},
{
`Usage: prog <duration>`,
`prog 10s`,
},
} {
argv := strings.Split(tc.command, " ")[1:]
opts, err := testParser.ParseArgs(tc.usage, argv, "")
Expand Down Expand Up @@ -273,17 +279,18 @@ func TestBindSimpleStruct(t *testing.T) {
}
}

func TestBindToStructWhichAlreadyHasValue(t *testing.T) {
var testParser = &Parser{HelpHandler: NoHelpHandler, SkipHelpFlags: true}
opts, err := testParser.ParseArgs("Usage: prog [--number=X]", []string{"--number=123"}, "")
if err != nil {
t.Fatal(err)
}
var opt = struct{ Number int }{1}
if err := opts.Bind(&opt); err == nil {
t.Fatal("error expected")
}
}
// Allow use of non-zero struct fields for bind
// func TestBindToStructWhichAlreadyHasValue(t *testing.T) {
// var testParser = &Parser{HelpHandler: NoHelpHandler, SkipHelpFlags: true}
// opts, err := testParser.ParseArgs("Usage: prog [--number=X]", []string{"--number=123"}, "")
// if err != nil {
// t.Fatal(err)
// }
// var opt = struct{ Number int }{1}
// if err := opts.Bind(&opt); err == nil {
// t.Fatal("error expected")
// }
// }

func TestBindDashTag(t *testing.T) {
var testParser = &Parser{HelpHandler: NoHelpHandler, SkipHelpFlags: true}
Expand Down
Loading