Skip to content

Commit

Permalink
Merge pull request #258 from ffromani/flagcodec-flag-compat-0.18
Browse files Browse the repository at this point in the history
pkg: flagcodec: enable flag normalization
  • Loading branch information
ffromani authored Nov 29, 2023
2 parents e80847b + 72b4af0 commit 5f9ae4f
Show file tree
Hide file tree
Showing 2 changed files with 394 additions and 34 deletions.
78 changes: 60 additions & 18 deletions pkg/flagcodec/flagcodec.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ type Val struct {
}

type Flags struct {
command string
args map[string]Val
keys []string
command string
args map[string]Val
keys []string
processFlagName func(string) string
}

// ParseArgvKeyValue parses a clean (trimmed) argv whose components
Expand All @@ -51,9 +52,24 @@ type Flags struct {
// "--opt=foo"
// AND NOT
// "--opt", "foo"
// The value of argv[0], whatever it is, is taken at command.
func ParseArgvKeyValue(args []string) *Flags {
return ParseArgvKeyValueWithCommand("", args)
func ParseArgvKeyValue(args []string, opts ...Option) *Flags {
ret := &Flags{
command: "",
args: make(map[string]Val),
processFlagName: func(v string) string { return v },
}
for _, opt := range opts {
opt(ret)
}
for _, arg := range args {
fields := strings.SplitN(arg, "=", 2)
if len(fields) == 1 {
ret.SetToggle(fields[0])
continue
}
ret.SetOption(fields[0], fields[1])
}
return ret
}

// ParseArgvKeyValueWithCommand parses a clean (trimmed) argv whose components
Expand All @@ -64,21 +80,43 @@ func ParseArgvKeyValue(args []string) *Flags {
// "--opt=foo"
// AND NOT
// "--opt", "foo"
// The command is supplied explicitely as parameter.
// The command is supplied explicitly as parameter.
// DEPRECATED: use ParseArgvValue and WithCommand option
func ParseArgvKeyValueWithCommand(command string, args []string) *Flags {
ret := &Flags{
command: command,
args: make(map[string]Val),
return ParseArgvKeyValue(args, WithCommand(command))
}

type Option func(*Flags) *Flags

func normalizeFlagName(v string) string {
if len(v) == 3 && v[0] == '-' && v[1] == '-' {
// single char, double dash flag (ugly?), fix it
return v[1:]
}
for _, arg := range args {
fields := strings.SplitN(arg, "=", 2)
if len(fields) == 1 {
ret.SetToggle(fields[0])
continue
}
ret.SetOption(fields[0], fields[1])
// everything else pass through silently
return v
}

// WithFlagNormalization optionally enables flag normalization.
// The canonical representation of flags in this package is:
// * single-dash for one-char flags (-v, -h)
// * double-dash for multi-char flags (--foo, --long-option)
// pflag allows one-char to have one or two dashes. For flagcodec
// these were different options. When normalization is enabled,
// though, all flag names are processed to adhere to the canonical
// representation, so flagcodec will treat `--v` and `-v` to
// be the same flag. Since this is possibly breaking change,
// this treatment is opt-in.
func WithFlagNormalization(fl *Flags) *Flags {
fl.processFlagName = normalizeFlagName
return fl
}

func WithCommand(command string) Option {
return func(fl *Flags) *Flags {
fl.command = command
return fl
}
return ret
}

func (fl *Flags) recordFlag(name string) {
Expand All @@ -99,13 +137,15 @@ func (fl *Flags) forgetFlag(name string) {
}

func (fl *Flags) SetToggle(name string) {
name = fl.processFlagName(name)
fl.recordFlag(name)
fl.args[name] = Val{
Kind: FlagToggle,
}
}

func (fl *Flags) SetOption(name, data string) {
name = fl.processFlagName(name)
fl.recordFlag(name)
fl.args[name] = Val{
Kind: FlagOption,
Expand All @@ -114,6 +154,7 @@ func (fl *Flags) SetOption(name, data string) {
}

func (fl *Flags) Delete(name string) {
name = fl.processFlagName(name)
fl.forgetFlag(name)
delete(fl.args, name)
}
Expand All @@ -139,6 +180,7 @@ func (fl *Flags) Argv() []string {
}

func (fl *Flags) GetFlag(name string) (Val, bool) {
name = fl.processFlagName(name)
if val, ok := fl.args[name]; ok {
return val, ok
}
Expand Down
Loading

0 comments on commit 5f9ae4f

Please sign in to comment.