81 lines
2.8 KiB
Go
81 lines
2.8 KiB
Go
|
|
package commandkit
|
||
|
|
|
||
|
|
import (
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
internalcobra "gitea.maximumdirect.net/eric/CommandKit/internal/cobra"
|
||
|
|
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
|
||
|
|
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
|
||
|
|
)
|
||
|
|
|
||
|
|
type completionContext struct {
|
||
|
|
route routeResult
|
||
|
|
command *commandmeta.Command
|
||
|
|
aliases []commandmeta.FlagAlias
|
||
|
|
completed []string
|
||
|
|
tail []string
|
||
|
|
current string
|
||
|
|
commandPosition bool
|
||
|
|
}
|
||
|
|
|
||
|
|
func resolveCompletionContext(snapshot *routingSnapshot, completed []string, current string) completionContext {
|
||
|
|
context := completionContext{completed: append([]string(nil), completed...), current: current}
|
||
|
|
if snapshot == nil {
|
||
|
|
return context
|
||
|
|
}
|
||
|
|
context.route = resolveEnteredRoute(completed, snapshot)
|
||
|
|
switch context.route.kind {
|
||
|
|
case routeCanonical:
|
||
|
|
context.command = completionCommand(snapshot.metadata, context.route.canonicalPath)
|
||
|
|
if context.command == nil || len(context.route.args) < len(context.route.canonicalPath) {
|
||
|
|
context.command = nil
|
||
|
|
return context
|
||
|
|
}
|
||
|
|
context.tail = append([]string(nil), context.route.args[len(context.route.canonicalPath):]...)
|
||
|
|
context.aliases = snapshot.flagAliases[context.route.canonicalPath.Key()].neutralRecords()
|
||
|
|
context.commandPosition = len(context.tail) == 0
|
||
|
|
case routeDiscovery:
|
||
|
|
context.command = &commandmeta.Command{CoreFlags: commandmeta.ReportingFlags()}
|
||
|
|
context.tail = append([]string(nil), context.route.args...)
|
||
|
|
context.aliases = snapshot.discoveryFlags[context.route.discoveryPath.Key()].neutralRecords()
|
||
|
|
}
|
||
|
|
return context
|
||
|
|
}
|
||
|
|
|
||
|
|
func completionCommand(root *commandmeta.Command, path commandpath.Path) *commandmeta.Command {
|
||
|
|
current := root
|
||
|
|
for _, name := range path {
|
||
|
|
if current == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
var next *commandmeta.Command
|
||
|
|
for _, child := range current.Children {
|
||
|
|
if child.Name == name {
|
||
|
|
next = child
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
current = next
|
||
|
|
}
|
||
|
|
return current
|
||
|
|
}
|
||
|
|
|
||
|
|
func completionChildren(snapshot *routingSnapshot, context completionContext) []commandmeta.CompletionChoice {
|
||
|
|
if snapshot == nil || context.command == nil || !context.commandPosition {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
var choices []commandmeta.CompletionChoice
|
||
|
|
for _, child := range context.command.Children {
|
||
|
|
if !strings.HasPrefix(child.Name, context.current) || (len(context.route.canonicalPath) == 0 && child.Name == internalcobra.CompletionQueryToken) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
entered := append(append([]string(nil), context.completed...), child.Name)
|
||
|
|
route := resolveEnteredRoute(entered, snapshot)
|
||
|
|
intended := append(context.route.canonicalPath.Clone(), child.Name)
|
||
|
|
if route.kind == routeCanonical && route.canonicalPath.Equal(intended) {
|
||
|
|
choices = append(choices, commandmeta.CompletionChoice{Value: child.Name, Description: child.Summary})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return choices
|
||
|
|
}
|