Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1. (+)Add:Multiple chars shorthand supported. #174

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 83 additions & 33 deletions flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ type FlagSet struct {
// help/usage messages.
SortFlags bool

// Allow multiple characters shorthand
AllowMultCharsShorthand bool

// ParseErrorsWhitelist is used to configure a whitelist of errors
ParseErrorsWhitelist ParseErrorsWhitelist

Expand All @@ -156,7 +159,7 @@ type FlagSet struct {
formal map[NormalizedName]*Flag
orderedFormal []*Flag
sortedFormal []*Flag
shorthands map[byte]*Flag
shorthands map[string]*Flag
args []string // arguments after flags
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
errorHandling ErrorHandling
Expand Down Expand Up @@ -344,12 +347,17 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
if name == "" {
return nil
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.out(), msg)
panic(msg)
c := ""
if f.AllowMultCharsShorthand {
c = name
} else {
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.out(), msg)
panic(msg)
}
c = string(name[0])
}
c := name[0]
return f.shorthands[c]
}

Expand Down Expand Up @@ -846,15 +854,20 @@ func (f *FlagSet) AddFlag(flag *Flag) {
if flag.Shorthand == "" {
return
}
if len(flag.Shorthand) > 1 {
if !f.AllowMultCharsShorthand && len(flag.Shorthand) > 1 {
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
fmt.Fprintf(f.out(), msg)
panic(msg)
}
if f.shorthands == nil {
f.shorthands = make(map[byte]*Flag)
f.shorthands = make(map[string]*Flag)
}
c := ""
if f.AllowMultCharsShorthand {
c = flag.Shorthand
} else {
c = string(flag.Shorthand[0])
}
c := flag.Shorthand[0]
used, alreadyThere := f.shorthands[c]
if alreadyThere {
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
Expand Down Expand Up @@ -996,22 +1009,41 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
return
}

outShorts = shorthands[1:]
c := shorthands[0]
c := ""
eqVal := ""
if f.AllowMultCharsShorthand {
// When in multiple-chars-shorhand-enabled mode, only "-ff=arg" or "-ff arg" is allowed.
eqPos := strings.Index(shorthands, "=")
if eqPos > 0 {
shorthands = shorthands[0:eqPos]
eqVal = shorthands[eqPos+1 : 0]
}
outShorts = ""
c = shorthands
} else {
outShorts = shorthands[1:]
c = string(shorthands[0])
}

flag, exists := f.shorthands[c]
if !exists {
switch {
case c == 'h':
case c == "h":
f.usage()
err = ErrHelp
return
case f.ParseErrorsWhitelist.UnknownFlags:
// '-f=arg arg ...'
// we do not want to lose arg in this case
if len(shorthands) > 2 && shorthands[1] == '=' {
outShorts = ""
return
if f.AllowMultCharsShorthand {
if len(eqVal) > 0 {
return
}
} else {
if len(shorthands) > 2 && shorthands[1] == '=' {
outShorts = ""
return
}
}

outArgs = stripUnknownFlagValue(outArgs)
Expand All @@ -1023,25 +1055,43 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
}

var value string
if len(shorthands) > 2 && shorthands[1] == '=' {
// '-f=arg'
value = shorthands[2:]
outShorts = ""
} else if flag.NoOptDefVal != "" {
// '-f' (arg was optional)
value = flag.NoOptDefVal
} else if len(shorthands) > 1 {
// '-farg'
value = shorthands[1:]
outShorts = ""
} else if len(args) > 0 {
// '-f arg'
value = args[0]
outArgs = args[1:]
if f.AllowMultCharsShorthand {
if len(eqVal) > 0 {
value = eqVal
outShorts = ""
} else if flag.NoOptDefVal != "" {
// '-f' (arg was optional)
value = flag.NoOptDefVal
} else if len(args) > 0 {
// '-f arg'
value = args[0]
outArgs = args[1:]
} else {
// '-f' (arg was required)
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
return
}
} else {
// '-f' (arg was required)
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
return
if len(shorthands) > 2 && shorthands[1] == '=' {
// '-f=arg'
value = shorthands[2:]
outShorts = ""
} else if flag.NoOptDefVal != "" {
// '-f' (arg was optional)
value = flag.NoOptDefVal
} else if len(shorthands) > 1 {
// '-farg'
value = shorthands[1:]
outShorts = ""
} else if len(args) > 0 {
// '-f arg'
value = args[0]
outArgs = args[1:]
} else {
// '-f' (arg was required)
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
return
}
}

if flag.ShorthandDeprecated != "" {
Expand Down