-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
142 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package configstruct | ||
|
||
import ( | ||
"flag" | ||
"strings" | ||
) | ||
|
||
// Command defines a command that consists of a name (empty for root command), a struct that models all | ||
// flags, a function that is executed if the command matches and that gets the config struct as argument | ||
// several sub-commands can be added | ||
type Command struct { | ||
fs *flag.FlagSet | ||
config interface{} | ||
f func(cfg interface{}) error | ||
subCommands []*Command | ||
} | ||
|
||
// NewCommand creates a command that is triggered by the given name in the command line | ||
// all flags are defined by a struct that is parsed and filled with real values | ||
// this struct is then set as argument for the function that is executed if the name matches | ||
func NewCommand(name string, config interface{}, f func(cfg interface{}) error, subCommands ...*Command) *Command { | ||
fs := flag.NewFlagSet(name, flag.ExitOnError) | ||
|
||
return &Command{ | ||
fs: fs, | ||
config: config, | ||
f: f, | ||
subCommands: subCommands, | ||
} | ||
} | ||
|
||
// ParseAndRun parses the given arguments and executes command functions | ||
func (c *Command) ParseAndRun(args []string, opts ...Option) error { | ||
err := ParseWithFlagSet(c.fs, args, c.config, opts...) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if c.fs.Name() == "" || strings.EqualFold(c.fs.Name(), args[0]) { | ||
err := c.f(c.config) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
args = c.fs.Args() | ||
if len(args) > 0 { | ||
for i := range c.subCommands { | ||
if strings.EqualFold(c.subCommands[i].fs.Name(), args[0]) { | ||
c.subCommands[i].ParseAndRun(args) | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package configstruct | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
type rootCmdConfig struct { | ||
Hostname string `env:"CONFIGSTRUCT_HOSTNAME" cli:"hostname" usage:"hostname value"` | ||
Port int `env:"CONFIGSTRUCT_PORT" cli:"port" usage:"listen port"` | ||
Debug bool `env:"CONFIGSTRUCT_DEBUG" cli:"debug" usage:"debug mode"` | ||
FloatValue float64 `env:"CONFIGSTRUCT_FLOAT" cli:"floatValue" usage:"float value"` | ||
} | ||
|
||
type subCmdConfig struct { | ||
Number int `cli:"number" usage:"number to count"` | ||
} | ||
|
||
func TestCommand_ParseAndRun(t *testing.T) { | ||
args := []string{"cliName", "-hostname", "localhost", "count", "-number", "2"} | ||
|
||
var rootConfig rootCmdConfig | ||
var subConfig subCmdConfig | ||
|
||
subCmd := NewCommand("count", &subConfig, func(cfg interface{}) error { | ||
cfgValues := cfg.(*subCmdConfig) | ||
t.Log("sub command", cfgValues.Number) | ||
return nil | ||
}) | ||
|
||
cmd := NewCommand("", &rootConfig, func(cfg interface{}) error { | ||
cfgValues := cfg.(*rootCmdConfig) | ||
t.Log("root command", cfgValues.Hostname) | ||
return nil | ||
}, subCmd) | ||
|
||
err := cmd.ParseAndRun(args) | ||
if err != nil { | ||
t.Errorf("error should be nil but is %v", err) | ||
} | ||
} |