Skip to content

Commit

Permalink
refactor: improve flag values, types and helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
joseluisq committed Mar 25, 2021
1 parent 1a366ec commit 8c2065b
Show file tree
Hide file tree
Showing 4 changed files with 898 additions and 140 deletions.
108 changes: 54 additions & 54 deletions app_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,119 +5,119 @@ import (
"strings"
)

// validateCommands checks if a command is valid and initialize it
func validateCommands(commands []Cmd) ([]Cmd, error) {
var cmds []Cmd
// It checks if a list of commands and initialize them if they are valid.
func validateCommands(commands []Cmd) (cmds []Cmd, err error) {
for _, c := range commands {
name := strings.TrimSpace(c.Name)
if name == "" {
return nil, fmt.Errorf("command name has empty value")
err = fmt.Errorf("one command name has empty value")
return
}
vflags, err := validateFlagsAndInit(c.Flags)
if err != nil {
return nil, err
flags, errf := validateFlagsAndInit(c.Flags)
if errf != nil {
err = errf
return
}
c.Flags = vflags
c.Flags = flags
cmds = append(cmds, c)
}
return cmds, nil
return
}

// validateFlagsAndInit validates flags and initialize them
func validateFlagsAndInit(flags []Flag) ([]Flag, error) {
var vFlags []Flag
// It checks a list of flags and initialize them if they are valid.
func validateFlagsAndInit(flags []Flag) (vflags []Flag, err error) {
for _, v := range flags {
switch f := v.(type) {
case FlagBool:
name := strings.ToLower(strings.TrimSpace(f.Name))
if name == "" {
return nil, fmt.Errorf("flag name has empty value")
if name := strings.ToLower(strings.TrimSpace(f.Name)); name == "" {
err = fmt.Errorf("bool flag name has an empty value")
return
}
f.initialize()
vFlags = append(vFlags, f)
vflags = append(vflags, f)

case FlagInt:
name := strings.ToLower(strings.TrimSpace(f.Name))
if name == "" {
return nil, fmt.Errorf("flag name has empty value")
if name := strings.ToLower(strings.TrimSpace(f.Name)); name == "" {
err = fmt.Errorf("int flag name has an empty value")
return
}
f.initialize()
vFlags = append(vFlags, f)
vflags = append(vflags, f)

case FlagString:
name := strings.ToLower(strings.TrimSpace(f.Name))
if name == "" {
return nil, fmt.Errorf("flag name has empty value")
if name := strings.ToLower(strings.TrimSpace(f.Name)); name == "" {
err = fmt.Errorf("string flag name has an empty value")
return
}
f.initialize()
vFlags = append(vFlags, f)
vflags = append(vflags, f)

case FlagStringSlice:
name := strings.ToLower(strings.TrimSpace(f.Name))
if name == "" {
return nil, fmt.Errorf("flag name has empty value")
if name := strings.ToLower(strings.TrimSpace(f.Name)); name == "" {
err = fmt.Errorf("string slice flag name has an empty value")
return
}
f.initialize()
vFlags = append(vFlags, f)
vflags = append(vflags, f)

default:
return nil, fmt.Errorf("flag has invalid data type value. Use bool, int, string, []string or nil")
err = fmt.Errorf("one flag has invalid data type value. Use a bool, int, string, []string or nil value")
return
}
}
return vFlags, nil
return
}

// findFlagByKey finds a flag item with its index in a flag's array by key.
// It also checks if was a short flag or not.
// It finds a flag item with its index in a given flags array by key
// then checks if every flag is a short flag or not.
func findFlagByKey(key string, flags []Flag) (int, Flag, bool) {
var short bool = false
for i, v := range flags {
switch f := v.(type) {
case FlagBool:
// Check for long named flags
if key == f.Name {
return i, f, short
if f.Name == key {
return i, f, false
}
// Check for short named flags
for _, s := range f.Aliases {
if key == s {
short = true
return i, f, short
if s == key {
return i, f, true
}
}
case FlagInt:
// Check for long named flags
if key == f.Name {
return i, f, short
if f.Name == key {
return i, f, false
}
// Check for short named flags
for _, s := range f.Aliases {
if key == s {
short = true
return i, f, short
if s == key {
return i, f, true
}
}
case FlagString:
// Check for long named flags
if key == f.Name {
return i, f, short
if f.Name == key {
return i, f, false
}
// Check for short named flags
for _, s := range f.Aliases {
if key == s {
short = true
return i, f, short
if s == key {
return i, f, true
}
}
case FlagStringSlice:
// Check for long named flags
if key == f.Name {
return i, f, short
if f.Name == key {
return i, f, false
}
// Check for short named flags
for _, s := range f.Aliases {
if key == s {
short = true
return i, f, short
if s == key {
return i, f, true
}
}
}
}
return -1, nil, short
return -1, nil, false
}
96 changes: 68 additions & 28 deletions flag_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,30 @@ import (
"syscall"
)

// FlagInt defines a flag with `Int` type.
// FlagInt defines an `Int` type flag.
type FlagInt struct {
Name string
Summary string
Value int
Aliases []string
EnvVar string
// Name of the flag containing alphanumeric characters and dashes
// but without leading dashes, spaces or any kind of special chars.
Name string
// An optional summary for the flag.
Summary string
// An optional default value for the flag.
Value int
// An optional list of flag aliases containing single alphanumeric characters
// but without dashes, spaces or any special chars.
Aliases []string
// An optional environment variable containing uppercase alphanumeric characters
// and underscores but without dashes, spaces or any kind of special chars.
EnvVar string

flagValue AnyValue
flagAssigned bool
flagProvided bool
flagProvidedAsAlias bool
}

// initialize sets a default flag value via associated `Value` prop or an environment variable (`EnvVar`).
// It sets a default flag value via its associated `Value` prop
// or its environment variable (`EnvVar`) if so.
func (fi *FlagInt) initialize() {
val := AnyValue(strconv.Itoa(fi.Value))
ev, ok := syscall.Getenv(fi.EnvVar)
Expand All @@ -32,20 +42,30 @@ func (fi *FlagInt) initialize() {
fi.flagValue = val
}

// FlagBool defines a flag with `bool` type.
// FlagBool defines a `bool` type flag.
type FlagBool struct {
Name string
Summary string
Value bool
Aliases []string
EnvVar string
// Name of the flag containing alphanumeric characters and dashes
// but without leading dashes, spaces or any kind of special chars.
Name string
// An optional summary for the flag.
Summary string
// An optional default value for the flag.
Value bool
// An optional list of flag aliases containing single alphanumeric characters
// but without dashes, spaces or any special chars.
Aliases []string
// An optional environment variable containing uppercase alphanumeric characters
// and underscores but without dashes, spaces or any kind of special chars.
EnvVar string

flagValue AnyValue
flagAssigned bool
flagProvided bool
flagProvidedAsAlias bool
}

// initialize sets a default flag value via associated `Value` prop or an environment variable (`EnvVar`).
// It sets a default flag value via its associated `Value` prop
// or its environment variable (`EnvVar`) if so.
func (fb *FlagBool) initialize() {
val := AnyValue(strconv.FormatBool(fb.Value))
ev, ok := syscall.Getenv(fb.EnvVar)
Expand All @@ -57,20 +77,30 @@ func (fb *FlagBool) initialize() {
fb.flagValue = val
}

// FlagString defines a flag with `String` type.
// FlagString defines a `String` type flag.
type FlagString struct {
Name string
Summary string
Value string
Aliases []string
EnvVar string
// Name of the flag containing alphanumeric characters and dashes
// but without leading dashes, spaces or any kind of special chars.
Name string
// An optional summary for the flag.
Summary string
// An optional default value for the flag.
Value string
// An optional list of flag aliases containing single alphanumeric characters
// but without dashes, spaces or any special chars.
Aliases []string
// An optional environment variable containing uppercase alphanumeric characters
// and underscores but without dashes, spaces or any kind of special chars.
EnvVar string

flagValue AnyValue
flagAssigned bool
flagProvided bool
flagProvidedAsAlias bool
}

// initialize sets a default flag value via associated `Value` prop or an environment variable (`EnvVar`).
// It sets a default flag value via its associated `Value` prop
// or its environment variable (`EnvVar`) if so.
func (fs *FlagString) initialize() {
val := AnyValue(fs.Value)
ev, ok := syscall.Getenv(fs.EnvVar)
Expand All @@ -80,20 +110,30 @@ func (fs *FlagString) initialize() {
fs.flagValue = val
}

// FlagStringSlice defines a flag with string slice type.
// FlagStringSlice defines a string slice type flag.
type FlagStringSlice struct {
Name string
Summary string
Value []string
Aliases []string
EnvVar string
// Name of the flag containing alphanumeric characters and dashes
// but without leading dashes, spaces or any kind of special chars.
Name string
// An optional default value for the flag.
Summary string
// An optional default value for the flag.
Value []string
// An optional list of flag aliases containing single alphanumeric characters
// but without dashes, spaces or any special chars.
Aliases []string
// An optional environment variable containing uppercase alphanumeric characters
// and underscores but without dashes, spaces or any kind of special chars.
EnvVar string

flagValue AnyValue
flagAssigned bool
flagProvided bool
flagProvidedAsAlias bool
}

// initialize sets a default flag value via associated `Value` prop or an environment variable (`EnvVar`).
// It sets a default flag value via its associated `Value` prop
// or its environment variable (`EnvVar`) if so.
func (fs *FlagStringSlice) initialize() {
val := AnyValue(strings.Join(fs.Value, ","))
ev, ok := syscall.Getenv(fs.EnvVar)
Expand Down
Loading

0 comments on commit 8c2065b

Please sign in to comment.