Share flag consumption between parsing and completion

This commit is contained in:
2026-11-07 15:53:32 +00:00
parent 51a147a6e5
commit 02cd49d6b6
6 changed files with 153 additions and 114 deletions

View File

@@ -53,44 +53,26 @@ func walkCompletionFlags(tokens []string, lookup commandmeta.FlagLookup) complet
state.ended = true
case commandmeta.OperandToken:
state.operands = append(state.operands, token)
case commandmeta.LongFlagToken:
spelling, _, attached := commandmeta.SplitLongFlag(token)
flag, ok := lookup.Find(spelling)
if !ok {
state.invalid = true
return state
}
state.supplied[flag.Name] = true
if !flag.Boolean && !attached {
if index+1 == len(tokens) {
state.pending = &flag
return state
}
index++
}
case commandmeta.ShortFlagToken:
for offset := 1; offset < len(token); offset++ {
flag, ok := lookup.Find("-" + token[offset:offset+1])
if !ok {
case commandmeta.LongFlagToken, commandmeta.ShortFlagToken:
for offset := 1; ; {
fact := commandmeta.ConsumeFlag(lookup, token, offset)
if !fact.Found {
state.invalid = true
return state
}
state.supplied[flag.Name] = true
suffix := token[offset+1:]
if flag.Boolean {
if strings.HasPrefix(suffix, "=") {
break
}
continue
}
if suffix == "" {
state.supplied[fact.Flag.Name] = true
if fact.NeedsNext {
if index+1 == len(tokens) {
flag := fact.Flag
state.pending = &flag
return state
}
index++
}
break
if fact.NextOffset == 0 {
break
}
offset = fact.NextOffset
}
}
}
@@ -132,10 +114,10 @@ func completionOptionTarget(current string, flags []commandmeta.Flag, lookup com
return completionTarget{kind: completionTargetFlags, choices: completionFlagNames(flags, supplied, current)}
}
if strings.HasPrefix(current, "--") {
spelling, value, attached := commandmeta.SplitLongFlag(current)
if attached {
if flag, ok := lookup.Find(spelling); ok {
return completionTarget{kind: completionTargetValue, hint: flag.Completion, prefix: spelling + "=", valuePrefix: value}
fact := commandmeta.ConsumeFlag(lookup, current, 1)
if fact.Attached {
if fact.Found {
return completionTarget{kind: completionTargetValue, hint: fact.Flag.Completion, prefix: fact.Spelling + "=", valuePrefix: fact.Value}
}
return completionTarget{}
}
@@ -145,25 +127,26 @@ func completionOptionTarget(current string, flags []commandmeta.Flag, lookup com
for name, value := range supplied {
used[name] = value
}
for offset := 1; offset < len(current); offset++ {
flag, ok := lookup.Find("-" + current[offset:offset+1])
if !ok {
for offset := 1; offset < len(current); {
fact := commandmeta.ConsumeFlag(lookup, current, offset)
if !fact.Found {
return completionTarget{}
}
used[flag.Name] = true
suffix := current[offset+1:]
if flag.Boolean {
if strings.HasPrefix(suffix, "=") {
return completionTarget{kind: completionTargetValue, hint: flag.Completion, prefix: current[:offset+2], valuePrefix: suffix[1:]}
used[fact.Flag.Name] = true
if fact.Flag.Boolean && fact.Attached {
return completionTarget{kind: completionTargetValue, hint: fact.Flag.Completion, prefix: current[:offset+2], valuePrefix: fact.Value}
}
if !fact.Flag.Boolean {
prefix := current[:offset+1]
if strings.HasPrefix(current[offset+1:], "=") {
prefix += "="
}
continue
return completionTarget{kind: completionTargetValue, hint: fact.Flag.Completion, prefix: prefix, valuePrefix: fact.Value}
}
prefix := current[:offset+1]
if strings.HasPrefix(suffix, "=") {
prefix += "="
suffix = suffix[1:]
if fact.NextOffset == 0 {
break
}
return completionTarget{kind: completionTargetValue, hint: flag.Completion, prefix: prefix, valuePrefix: suffix}
offset = fact.NextOffset
}
var choices []commandmeta.CompletionChoice
for _, flag := range flags {