Resolve command context for completion
This commit is contained in:
80
completion_context.go
Normal file
80
completion_context.go
Normal file
@@ -0,0 +1,80 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user