Interpret command flag aliases in the parser

This commit is contained in:
2026-10-19 19:31:23 +00:00
parent 58b71c390f
commit 75fc45f072
8 changed files with 389 additions and 11 deletions

View File

@@ -22,6 +22,7 @@ type Session struct {
metadata *commandmeta.Command
root *spfcobra.Command
declarations map[*spfcobra.Command]*commandmeta.Command
flagAliases []commandmeta.FlagAlias
}
// Prepare constructs a fresh backend tree for one invocation.
@@ -31,6 +32,7 @@ func Prepare(root *commandmeta.Command, options commandmeta.ParseOptions) *Sessi
return session
}
session.metadata = root
session.flagAliases = append([]commandmeta.FlagAlias(nil), options.FlagAliases...)
options = normalizeOptions(options)
session.root, session.declarations = buildTree(root, options)
return session
@@ -75,16 +77,28 @@ func (session *Session) Parse(argv []string) commandmeta.Result {
}
remaining := append(commandpath.CloneTokens(unconsumed), tail...)
if err := selected.ParseFlags(remaining); err != nil {
interpreted, spellings := interpretFlagTokens(remaining, selectedNode.Flags, session.flagAliases)
for _, flag := range selectedNode.Flags {
if value := selected.Flags().Lookup(flag.Name); value != nil {
value.Value.(*rawValue).queueSpellings(spellings[flag.Name])
}
}
if helpFlag := selected.Flags().Lookup("help"); helpFlag != nil {
helpFlag.Value.(*rawValue).queueSpellings(spellings["help"])
}
if err := selected.ParseFlags(interpreted); err != nil {
return failure(result, err.Error())
}
operands := selected.Flags().Args()
result.Operands = append([]string(nil), operands...)
result.FlagValues = make([][]string, len(selectedNode.Flags))
result.FlagSpellings = make([][]string, len(selectedNode.Flags))
for index, flag := range selectedNode.Flags {
if value := selected.Flags().Lookup(flag.Name); value != nil {
result.FlagValues[index] = value.Value.(*rawValue).valuesCopy()
raw := value.Value.(*rawValue)
result.FlagValues[index] = raw.valuesCopy()
result.FlagSpellings[index] = raw.spellingsCopy()
}
}
if helpFlag := selected.Flags().Lookup("help"); helpFlag != nil {
@@ -337,15 +351,25 @@ func failure(result commandmeta.Result, message string) commandmeta.Result {
}
type rawValue struct {
values []string
boolean bool
values []string
spellings []string
pendingSpellings []string
boolean bool
}
func (v *rawValue) Set(value string) error {
v.values = append(v.values, value)
if len(v.pendingSpellings) > 0 {
v.spellings = append(v.spellings, v.pendingSpellings[0])
v.pendingSpellings = v.pendingSpellings[1:]
}
return nil
}
func (v *rawValue) queueSpellings(spellings []string) {
v.pendingSpellings = append(v.pendingSpellings, spellings...)
}
func (v *rawValue) String() string {
if len(v.values) > 0 {
return v.values[len(v.values)-1]
@@ -364,6 +388,8 @@ func (v *rawValue) IsBoolFlag() bool { return v.boolean }
func (v *rawValue) valuesCopy() []string { return append([]string(nil), v.values...) }
func (v *rawValue) spellingsCopy() []string { return append([]string(nil), v.spellings...) }
func (v *rawValue) lastBool() (bool, error) {
var value bool
for _, raw := range v.values {