2026-11-03 03:51:26 +00:00
|
|
|
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:
|
2026-11-03 13:13:20 +00:00
|
|
|
context.command = completionCommand(snapshot, context.route.canonicalPath)
|
2026-11-03 03:51:26 +00:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2026-11-03 13:13:20 +00:00
|
|
|
func completionCommand(snapshot *routingSnapshot, path commandpath.Path) *commandmeta.Command {
|
|
|
|
|
if len(path) == 0 {
|
|
|
|
|
return snapshot.metadata
|
|
|
|
|
}
|
|
|
|
|
children := snapshot.canonical
|
|
|
|
|
var node *canonicalNode
|
2026-11-03 03:51:26 +00:00
|
|
|
for _, name := range path {
|
2026-11-03 13:13:20 +00:00
|
|
|
node = children[name]
|
|
|
|
|
if node == nil {
|
2026-11-03 03:51:26 +00:00
|
|
|
return nil
|
|
|
|
|
}
|
2026-11-03 13:13:20 +00:00
|
|
|
children = node.children
|
2026-11-03 03:51:26 +00:00
|
|
|
}
|
2026-11-03 13:13:20 +00:00
|
|
|
return node.metadata
|
2026-11-03 03:51:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|