Skip to content

Commit 83a8f3e

Browse files
committed
update!: made overall changes to align the API with cliargs-rust
1 parent c0e293c commit 83a8f3e

29 files changed

+4935
-3147
lines changed

README.md

-80
This file was deleted.

cmd.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (C) 2023-2024 Takayuki Sato. All Rights Reserved.
2+
// This program is free software under MIT License.
3+
// See the file LICENSE in this distribution for more details.
4+
5+
package cliargs
6+
7+
import (
8+
"fmt"
9+
"os"
10+
"path"
11+
)
12+
13+
// Cmd is the structure that parses command line arguments and stores them.
14+
// The results of parsing are stored by separating into command name, command arguments, options,
15+
// and option arguments.
16+
// And this provides methods to check if they are specified and to retrieve them.
17+
type Cmd struct {
18+
Name string
19+
Args []string
20+
OptCfgs []OptCfg
21+
22+
opts map[string][]string
23+
24+
_args []string
25+
}
26+
27+
// NewCmd is the function that creates a Cmd instance iwth command line arguments obtained from
28+
// os.Args.
29+
func NewCmd() Cmd {
30+
var name string
31+
if len(os.Args) > 0 {
32+
name = path.Base(os.Args[0])
33+
}
34+
35+
var args []string
36+
if len(os.Args) > 1 {
37+
args = os.Args[1:]
38+
}
39+
40+
return Cmd{Name: name, Args: []string{}, opts: make(map[string][]string), _args: args}
41+
}
42+
43+
func (cmd Cmd) subCmd(fromIndex int) Cmd {
44+
var name string
45+
if len(cmd._args) > fromIndex {
46+
name = cmd._args[fromIndex]
47+
}
48+
49+
var args []string
50+
if len(cmd._args) > fromIndex+1 {
51+
args = cmd._args[fromIndex+1:]
52+
}
53+
54+
return Cmd{Name: name, Args: []string{}, opts: make(map[string][]string), _args: args}
55+
}
56+
57+
// HasOpt is the method that checks whether an option with the specified name exists.
58+
func (cmd Cmd) HasOpt(name string) bool {
59+
_, exists := cmd.opts[name]
60+
return exists
61+
}
62+
63+
// OptArg is the method that returns the option argument with the specified name.
64+
// If the option has multiple arguments, this method returns the first argument.
65+
// If the option is a boolean flag, the method returns an empty string.
66+
// If the option is not specified in the command line arguments, the return value
67+
// of this method is an empty string.
68+
func (cmd Cmd) OptArg(name string) string {
69+
arr := cmd.opts[name]
70+
// If no entry, map returns a nil slice.
71+
// len() methods of both a nil slice and a empty slice return zero in common.
72+
if len(arr) == 0 {
73+
return ""
74+
} else {
75+
return arr[0]
76+
}
77+
}
78+
79+
// OptArgs is the method that returns the option arguments with the specified name.
80+
// If the option has one or multiple arguments, this method returns an array of the arguments.
81+
// If the option is a boolean flag, the method returns an empty slice.
82+
// If the option is not specified in the command line arguments, the return value
83+
// of this method is a nil slice.
84+
func (cmd Cmd) OptArgs(name string) []string {
85+
return cmd.opts[name]
86+
}
87+
88+
// String is the method that returns the string which represents the content of this instance.
89+
func (cmd Cmd) String() string {
90+
return fmt.Sprintf("Cmd { Name: %s, Args: %v, Opts: %v }", cmd.Name, cmd.Args, cmd.opts)
91+
}

cmd_test.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package cliargs
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
var origOsArgs = os.Args
12+
13+
func reset() {
14+
os.Args = origOsArgs
15+
}
16+
17+
func TestCmd_NewCmd_withOsArgs(t *testing.T) {
18+
defer reset()
19+
os.Args = []string{"/path/to/app", "--foo", "bar"}
20+
21+
cmd := NewCmd()
22+
assert.Equal(t, cmd.Name, "app")
23+
assert.Equal(t, cmd.Args, []string{})
24+
assert.Equal(t, cmd.String(), "Cmd { Name: app, Args: [], Opts: map[] }")
25+
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: app, Args: [], Opts: map[] }")
26+
27+
assert.Equal(t, cmd._args, []string{"--foo", "bar"})
28+
29+
assert.Equal(t, cmd.HasOpt("foo"), false)
30+
assert.Equal(t, cmd.OptArg("foo"), "")
31+
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
32+
}
33+
34+
func TestCmd_NewCmd_withNoArgs(t *testing.T) {
35+
defer reset()
36+
os.Args = []string{"/path/to/app"}
37+
38+
cmd := NewCmd()
39+
assert.Equal(t, cmd.Name, "app")
40+
assert.Equal(t, cmd.Args, []string{})
41+
assert.Equal(t, cmd.String(), "Cmd { Name: app, Args: [], Opts: map[] }")
42+
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: app, Args: [], Opts: map[] }")
43+
44+
assert.Equal(t, cmd._args, []string(nil))
45+
46+
assert.Equal(t, cmd.HasOpt("foo"), false)
47+
assert.Equal(t, cmd.OptArg("foo"), "")
48+
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
49+
}
50+
51+
func TestCmd_NewCmd_empty(t *testing.T) {
52+
defer reset()
53+
os.Args = []string{}
54+
55+
cmd := NewCmd()
56+
assert.Equal(t, cmd.Name, "")
57+
assert.Equal(t, cmd.Args, []string{})
58+
assert.Equal(t, cmd.String(), "Cmd { Name: , Args: [], Opts: map[] }")
59+
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: , Args: [], Opts: map[] }")
60+
61+
assert.Equal(t, cmd._args, []string(nil))
62+
63+
assert.Equal(t, cmd.HasOpt("foo"), false)
64+
assert.Equal(t, cmd.OptArg("foo"), "")
65+
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
66+
}
67+
68+
func TestCmd_subCmd(t *testing.T) {
69+
cmd := NewCmd()
70+
cmd._args = []string{"--foo", "-b", "qux", "--corge"}
71+
72+
subCmd := cmd.subCmd(2)
73+
assert.Equal(t, subCmd.Name, "qux")
74+
assert.Equal(t, subCmd._args, []string{"--corge"})
75+
}
76+
77+
func TestCmd_subCmd_withNoArg(t *testing.T) {
78+
cmd := NewCmd()
79+
cmd._args = []string{"--foo", "-b", "qux"}
80+
81+
subCmd := cmd.subCmd(2)
82+
assert.Equal(t, subCmd.Name, "qux")
83+
assert.Equal(t, subCmd._args, []string(nil))
84+
}
85+
86+
func TestCmd_subCmd_empty(t *testing.T) {
87+
cmd := NewCmd()
88+
cmd._args = []string{"--foo", "-b"}
89+
90+
subCmd := cmd.subCmd(2)
91+
assert.Equal(t, subCmd.Name, "")
92+
assert.Equal(t, subCmd._args, []string(nil))
93+
}
94+
95+
func TestCmd_NewCmd_HasOpt(t *testing.T) {
96+
defer reset()
97+
98+
cmd := NewCmd()
99+
cmd.opts["foo-bar"] = []string(nil)
100+
cmd.opts["baz"] = []string{"123"}
101+
cmd.opts["qux"] = []string{"A", "B"}
102+
103+
assert.Equal(t, cmd.HasOpt("foo-bar"), true)
104+
assert.Equal(t, cmd.HasOpt("baz"), true)
105+
assert.Equal(t, cmd.HasOpt("qux"), true)
106+
assert.Equal(t, cmd.HasOpt("quux"), false)
107+
}
108+
109+
func TestCmd_NewCmd_OptArg(t *testing.T) {
110+
defer reset()
111+
112+
cmd := NewCmd()
113+
cmd.opts["foo-bar"] = []string{}
114+
cmd.opts["baz"] = []string{"123"}
115+
cmd.opts["qux"] = []string{"A", "B"}
116+
117+
assert.Equal(t, cmd.OptArg("foo-bar"), "")
118+
assert.Equal(t, cmd.OptArg("baz"), "123")
119+
assert.Equal(t, cmd.OptArg("qux"), "A")
120+
assert.Equal(t, cmd.OptArg("quux"), "")
121+
}
122+
123+
func TestCmd_NewCmd_OptArgs(t *testing.T) {
124+
defer reset()
125+
126+
cmd := NewCmd()
127+
cmd.opts["foo-bar"] = []string{}
128+
cmd.opts["baz"] = []string{"123"}
129+
cmd.opts["qux"] = []string{"A", "B"}
130+
131+
assert.Equal(t, cmd.OptArgs("foo-bar"), []string{})
132+
assert.Equal(t, cmd.OptArgs("baz"), []string{"123"})
133+
assert.Equal(t, cmd.OptArgs("qux"), []string{"A", "B"})
134+
assert.Equal(t, cmd.OptArgs("quux"), []string(nil))
135+
}

0 commit comments

Comments
 (0)