Replace docopt (#20)

* Replace docopt with pflag
master
Ivan 3 years ago committed by GitHub
parent b0e2d1208b
commit b693c55fd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,3 +7,9 @@ test:
coverage:
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
release:
rm -rf dist
git tag -a $(version) -m '$(version)'
git push origin $(version)
goreleaser

@ -3,6 +3,6 @@ module github.com/ivaaaan/smug
go 1.13
require (
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/spf13/pflag v1.0.5
gopkg.in/yaml.v2 v2.4.0
)

@ -1,5 +1,5 @@
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

@ -6,14 +6,39 @@ import (
"log"
"os"
"path/filepath"
"github.com/docopt/docopt-go"
)
const version = "v0.1.5"
var usage = fmt.Sprintf(`Smug - tmux session manager. Version %s
Usage:
smug <command> <project> [-w <window>]... [--attach] [--debug]
Options:
-w, --windows %s
-a, --attach %s
-d, --debug %s
Examples:
$ smug start blog
$ smug start blog:win1
$ smug start blog -w win1
$ smug start blog:win1,win2
$ smug stop blog
$ smug start blog --attach
`, version, WindowsUsage, AttachUsage, DebugUsage)
func main() {
parser := docopt.Parser{}
options, err := ParseOptions(os.Args[1:], func() {
fmt.Fprintf(os.Stdout, usage)
os.Exit(0)
})
if err == ErrHelp {
os.Exit(0)
}
options, err := ParseOptions(parser, os.Args[1:])
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot parse command line otions: %q", err.Error())
os.Exit(1)
@ -51,7 +76,7 @@ func main() {
context := CreateContext()
switch options.Command {
case "start":
case CommandStart:
if len(options.Windows) == 0 {
fmt.Println("Starting a new session...")
} else {
@ -62,15 +87,13 @@ func main() {
fmt.Println("Oops, an error occurred! Rolling back...")
smug.Stop(*config, options, *context)
}
case "stop":
case CommandStop:
if len(options.Windows) == 0 {
fmt.Println("Terminating session...")
} else {
fmt.Println("Killing windows...")
}
err = smug.Stop(*config, options, *context)
default:
err = fmt.Errorf("Unknown command %q", options.Command)
}
if err != nil {

@ -1,26 +1,16 @@
package main
import (
"errors"
"strings"
"github.com/docopt/docopt-go"
"github.com/spf13/pflag"
)
const usage = `Smug - tmux session manager. Version v0.1.5
Usage:
smug <command> <project> [-w <window>]... [--attach] [--debug]
Options:
-w List of windows to start. If session exists, those windows will be attached to current session.
Examples:
$ smug start blog
$ smug start blog:win1
$ smug start blog -w win1
$ smug start blog:win1,win2
$ smug stop blog
`
const (
CommandStart = "start"
CommandStop = "stop"
)
type Options struct {
Command string
@ -30,41 +20,50 @@ type Options struct {
Debug bool
}
func ParseOptions(p docopt.Parser, argv []string) (Options, error) {
arguments, err := p.ParseArgs(usage, argv, "")
if err != nil {
return Options{}, err
}
var ErrHelp = errors.New("help requested")
cmd, err := arguments.String("<command>")
if err != nil {
return Options{}, err
}
const (
WindowsUsage = "List of windows to start. If session exists, those windows will be attached to current session."
AttachUsage = "Force switch client for a session"
DebugUsage = "Print all commands to ~/.config/smug/smug.log"
)
project, err := arguments.String("<project>")
if err != nil {
return Options{}, err
// Creates a new FlagSet.
// Moved it to a variable to be able to override it in the tests.
var NewFlagSet = func(cmd string) *pflag.FlagSet {
return pflag.NewFlagSet(cmd, pflag.ContinueOnError)
}
func ParseOptions(argv []string, helpRequested func()) (Options, error) {
if len(argv) < 2 {
helpRequested()
return Options{}, ErrHelp
}
attach, err := arguments.Bool("--attach")
if err != nil {
return Options{}, err
cmd := argv[0]
project := argv[1]
flags := NewFlagSet(cmd)
windows := flags.StringArrayP("windows", "w", []string{}, WindowsUsage)
attach := flags.BoolP("attach", "a", false, AttachUsage)
debug := flags.BoolP("debug", "d", false, DebugUsage)
err := flags.Parse(argv)
if err == pflag.ErrHelp {
return Options{}, ErrHelp
}
debug, err := arguments.Bool("--debug")
if err != nil {
return Options{}, err
}
var windows []string
if strings.Contains(project, ":") {
parts := strings.Split(project, ":")
project = parts[0]
windows = strings.Split(parts[1], ",")
} else {
windows = arguments["-w"].([]string)
wl := strings.Split(parts[1], ",")
windows = &wl
}
return Options{cmd, project, windows, attach, debug}, nil
return Options{cmd, project, *windows, *attach, *debug}, nil
}

@ -4,42 +4,86 @@ import (
"reflect"
"testing"
"github.com/docopt/docopt-go"
"github.com/spf13/pflag"
)
var usageTestTable = []struct {
argv []string
opts Options
argv []string
opts Options
err error
helpCalls int
}{
{
[]string{"start", "smug"},
Options{"start", "smug", []string{}, false, false},
nil,
0,
},
{
[]string{"start", "smug", "-wfoo"},
[]string{"start", "smug", "-w", "foo"},
Options{"start", "smug", []string{"foo"}, false, false},
nil,
0,
},
{
[]string{"start", "smug:foo,bar"},
Options{"start", "smug", []string{"foo", "bar"}, false, false},
nil,
0,
},
{
[]string{"start", "smug", "--attach", "--debug"},
Options{"start", "smug", []string{}, true, true},
nil,
0,
},
{
[]string{"start", "smug", "-ad"},
Options{"start", "smug", []string{}, true, true},
nil,
0,
},
{
[]string{"start"},
Options{},
ErrHelp,
1,
},
{
[]string{"start", "--help"},
Options{},
ErrHelp,
1,
},
}
func TestParseOptions(t *testing.T) {
parser := docopt.Parser{}
for _, v := range usageTestTable {
opts, err := ParseOptions(parser, v.argv)
helpCalls := 0
helpRequested := func() {
helpCalls++
}
if err != nil {
t.Fail()
}
NewFlagSet = func(cmd string) *pflag.FlagSet {
flagSet := pflag.NewFlagSet(cmd, pflag.ContinueOnError)
flagSet.Usage = helpRequested
return flagSet
}
for _, v := range usageTestTable {
opts, err := ParseOptions(v.argv, helpRequested)
if !reflect.DeepEqual(v.opts, opts) {
t.Errorf("expected struct %v, got %v", v.opts, opts)
}
if helpCalls != v.helpCalls {
t.Errorf("expected to get %d help calls, got %d", v.helpCalls, helpCalls)
}
if err != v.err {
t.Errorf("expected to get error %v, got %v", v.err, err)
}
helpCalls = 0
}
}

Loading…
Cancel
Save