Skip to content

Commit

Permalink
update!: made overall changes to align the API with cliargs-rust (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
sttk authored Aug 31, 2024
1 parent c0e293c commit 71930c9
Show file tree
Hide file tree
Showing 29 changed files with 4,935 additions and 3,147 deletions.
80 changes: 0 additions & 80 deletions README.md

This file was deleted.

91 changes: 91 additions & 0 deletions cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (C) 2023-2024 Takayuki Sato. All Rights Reserved.
// This program is free software under MIT License.
// See the file LICENSE in this distribution for more details.

package cliargs

import (
"fmt"
"os"
"path"
)

// Cmd is the structure that parses command line arguments and stores them.
// The results of parsing are stored by separating into command name, command arguments, options,
// and option arguments.
// And this provides methods to check if they are specified and to retrieve them.
type Cmd struct {
Name string
Args []string
OptCfgs []OptCfg

opts map[string][]string

_args []string
}

// NewCmd is the function that creates a Cmd instance iwth command line arguments obtained from
// os.Args.
func NewCmd() Cmd {
var name string
if len(os.Args) > 0 {
name = path.Base(os.Args[0])
}

var args []string
if len(os.Args) > 1 {
args = os.Args[1:]
}

return Cmd{Name: name, Args: []string{}, opts: make(map[string][]string), _args: args}
}

func (cmd Cmd) subCmd(fromIndex int) Cmd {
var name string
if len(cmd._args) > fromIndex {
name = cmd._args[fromIndex]
}

var args []string
if len(cmd._args) > fromIndex+1 {
args = cmd._args[fromIndex+1:]
}

return Cmd{Name: name, Args: []string{}, opts: make(map[string][]string), _args: args}
}

// HasOpt is the method that checks whether an option with the specified name exists.
func (cmd Cmd) HasOpt(name string) bool {
_, exists := cmd.opts[name]
return exists
}

// OptArg is the method that returns the option argument with the specified name.
// If the option has multiple arguments, this method returns the first argument.
// If the option is a boolean flag, the method returns an empty string.
// If the option is not specified in the command line arguments, the return value
// of this method is an empty string.
func (cmd Cmd) OptArg(name string) string {
arr := cmd.opts[name]
// If no entry, map returns a nil slice.
// len() methods of both a nil slice and a empty slice return zero in common.
if len(arr) == 0 {
return ""
} else {
return arr[0]
}
}

// OptArgs is the method that returns the option arguments with the specified name.
// If the option has one or multiple arguments, this method returns an array of the arguments.
// If the option is a boolean flag, the method returns an empty slice.
// If the option is not specified in the command line arguments, the return value
// of this method is a nil slice.
func (cmd Cmd) OptArgs(name string) []string {
return cmd.opts[name]
}

// String is the method that returns the string which represents the content of this instance.
func (cmd Cmd) String() string {
return fmt.Sprintf("Cmd { Name: %s, Args: %v, Opts: %v }", cmd.Name, cmd.Args, cmd.opts)
}
135 changes: 135 additions & 0 deletions cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package cliargs

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

var origOsArgs = os.Args

func reset() {
os.Args = origOsArgs
}

func TestCmd_NewCmd_withOsArgs(t *testing.T) {
defer reset()
os.Args = []string{"/path/to/app", "--foo", "bar"}

cmd := NewCmd()
assert.Equal(t, cmd.Name, "app")
assert.Equal(t, cmd.Args, []string{})
assert.Equal(t, cmd.String(), "Cmd { Name: app, Args: [], Opts: map[] }")
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: app, Args: [], Opts: map[] }")

assert.Equal(t, cmd._args, []string{"--foo", "bar"})

assert.Equal(t, cmd.HasOpt("foo"), false)
assert.Equal(t, cmd.OptArg("foo"), "")
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
}

func TestCmd_NewCmd_withNoArgs(t *testing.T) {
defer reset()
os.Args = []string{"/path/to/app"}

cmd := NewCmd()
assert.Equal(t, cmd.Name, "app")
assert.Equal(t, cmd.Args, []string{})
assert.Equal(t, cmd.String(), "Cmd { Name: app, Args: [], Opts: map[] }")
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: app, Args: [], Opts: map[] }")

assert.Equal(t, cmd._args, []string(nil))

assert.Equal(t, cmd.HasOpt("foo"), false)
assert.Equal(t, cmd.OptArg("foo"), "")
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
}

func TestCmd_NewCmd_empty(t *testing.T) {
defer reset()
os.Args = []string{}

cmd := NewCmd()
assert.Equal(t, cmd.Name, "")
assert.Equal(t, cmd.Args, []string{})
assert.Equal(t, cmd.String(), "Cmd { Name: , Args: [], Opts: map[] }")
assert.Equal(t, fmt.Sprintf("%v", cmd), "Cmd { Name: , Args: [], Opts: map[] }")

assert.Equal(t, cmd._args, []string(nil))

assert.Equal(t, cmd.HasOpt("foo"), false)
assert.Equal(t, cmd.OptArg("foo"), "")
assert.Equal(t, cmd.OptArgs("foo"), []string(nil))
}

func TestCmd_subCmd(t *testing.T) {
cmd := NewCmd()
cmd._args = []string{"--foo", "-b", "qux", "--corge"}

subCmd := cmd.subCmd(2)
assert.Equal(t, subCmd.Name, "qux")
assert.Equal(t, subCmd._args, []string{"--corge"})
}

func TestCmd_subCmd_withNoArg(t *testing.T) {
cmd := NewCmd()
cmd._args = []string{"--foo", "-b", "qux"}

subCmd := cmd.subCmd(2)
assert.Equal(t, subCmd.Name, "qux")
assert.Equal(t, subCmd._args, []string(nil))
}

func TestCmd_subCmd_empty(t *testing.T) {
cmd := NewCmd()
cmd._args = []string{"--foo", "-b"}

subCmd := cmd.subCmd(2)
assert.Equal(t, subCmd.Name, "")
assert.Equal(t, subCmd._args, []string(nil))
}

func TestCmd_NewCmd_HasOpt(t *testing.T) {
defer reset()

cmd := NewCmd()
cmd.opts["foo-bar"] = []string(nil)
cmd.opts["baz"] = []string{"123"}
cmd.opts["qux"] = []string{"A", "B"}

assert.Equal(t, cmd.HasOpt("foo-bar"), true)
assert.Equal(t, cmd.HasOpt("baz"), true)
assert.Equal(t, cmd.HasOpt("qux"), true)
assert.Equal(t, cmd.HasOpt("quux"), false)
}

func TestCmd_NewCmd_OptArg(t *testing.T) {
defer reset()

cmd := NewCmd()
cmd.opts["foo-bar"] = []string{}
cmd.opts["baz"] = []string{"123"}
cmd.opts["qux"] = []string{"A", "B"}

assert.Equal(t, cmd.OptArg("foo-bar"), "")
assert.Equal(t, cmd.OptArg("baz"), "123")
assert.Equal(t, cmd.OptArg("qux"), "A")
assert.Equal(t, cmd.OptArg("quux"), "")
}

func TestCmd_NewCmd_OptArgs(t *testing.T) {
defer reset()

cmd := NewCmd()
cmd.opts["foo-bar"] = []string{}
cmd.opts["baz"] = []string{"123"}
cmd.opts["qux"] = []string{"A", "B"}

assert.Equal(t, cmd.OptArgs("foo-bar"), []string{})
assert.Equal(t, cmd.OptArgs("baz"), []string{"123"})
assert.Equal(t, cmd.OptArgs("qux"), []string{"A", "B"})
assert.Equal(t, cmd.OptArgs("quux"), []string(nil))
}
Loading

0 comments on commit 71930c9

Please sign in to comment.