Index completion metadata by canonical node
This commit is contained in:
@@ -26,7 +26,7 @@ func resolveCompletionContext(snapshot *routingSnapshot, completed []string, cur
|
||||
context.route = resolveEnteredRoute(completed, snapshot)
|
||||
switch context.route.kind {
|
||||
case routeCanonical:
|
||||
context.command = completionCommand(snapshot.metadata, context.route.canonicalPath)
|
||||
context.command = completionCommand(snapshot, context.route.canonicalPath)
|
||||
if context.command == nil || len(context.route.args) < len(context.route.canonicalPath) {
|
||||
context.command = nil
|
||||
return context
|
||||
@@ -42,22 +42,20 @@ func resolveCompletionContext(snapshot *routingSnapshot, completed []string, cur
|
||||
return context
|
||||
}
|
||||
|
||||
func completionCommand(root *commandmeta.Command, path commandpath.Path) *commandmeta.Command {
|
||||
current := root
|
||||
func completionCommand(snapshot *routingSnapshot, path commandpath.Path) *commandmeta.Command {
|
||||
if len(path) == 0 {
|
||||
return snapshot.metadata
|
||||
}
|
||||
children := snapshot.canonical
|
||||
var node *canonicalNode
|
||||
for _, name := range path {
|
||||
if current == nil {
|
||||
node = children[name]
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
var next *commandmeta.Command
|
||||
for _, child := range current.Children {
|
||||
if child.Name == name {
|
||||
next = child
|
||||
break
|
||||
}
|
||||
}
|
||||
current = next
|
||||
children = node.children
|
||||
}
|
||||
return current
|
||||
return node.metadata
|
||||
}
|
||||
|
||||
func completionChildren(snapshot *routingSnapshot, context completionContext) []commandmeta.CompletionChoice {
|
||||
|
||||
@@ -73,6 +73,10 @@ func TestCompletionQueryDispatch(t *testing.T) {
|
||||
if outcome := app.Execute(context.Background(), []string{"__complete", "lat"}, Streams{Out: &output}); outcome.Status != 0 || !strings.Contains(output.String(), "later") {
|
||||
t.Fatalf("later command outcome=%#v reply=%q", outcome, output.String())
|
||||
}
|
||||
output.Reset()
|
||||
if outcome := app.Execute(context.Background(), []string{"__complete", "later", "--qui"}, Streams{Out: &output}); outcome.Status != 0 || !strings.Contains(output.String(), "--quiet") {
|
||||
t.Fatalf("later command flag outcome=%#v reply=%q", outcome, output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompletionQueryErrorsAndDelivery(t *testing.T) {
|
||||
|
||||
@@ -169,7 +169,9 @@ the remaining scope. The six existing findings remain open.
|
||||
|
||||
### 7. Look up canonical completion metadata without scanning siblings
|
||||
|
||||
Priority: P3. Status: for consideration.
|
||||
Priority: P3. Status: complete.
|
||||
|
||||
- [x] Completed: Canonical snapshot nodes now hold their neutral metadata. Completion uses one map lookup per path component; root, nested and alias context checks and a late-registration leaf query pass.
|
||||
|
||||
[completionCommand](../../completion_context.go) searches the metadata child
|
||||
slice at every component of an already resolved canonical path. For depth
|
||||
|
||||
@@ -99,13 +99,13 @@ func (a *App) buildRoutingSnapshot() *routingSnapshot {
|
||||
sort.Strings(names)
|
||||
var key commandmeta.Key
|
||||
for _, name := range names {
|
||||
root.Children = append(root.Children, bridgeCommand(a.commands[name].command, snapshot, &key))
|
||||
root.Children = append(root.Children, bridgeCommand(snapshot.canonical[name], snapshot, &key))
|
||||
}
|
||||
return snapshot
|
||||
}
|
||||
|
||||
func bridgeCommand(command Command, snapshot *routingSnapshot, next *commandmeta.Key) *commandmeta.Command {
|
||||
record := command.record
|
||||
func bridgeCommand(node *canonicalNode, snapshot *routingSnapshot, next *commandmeta.Key) *commandmeta.Command {
|
||||
record := node.command.record
|
||||
*next = *next + 1
|
||||
declaration := &commandmeta.Command{
|
||||
Key: *next,
|
||||
@@ -114,6 +114,7 @@ func bridgeCommand(command Command, snapshot *routingSnapshot, next *commandmeta
|
||||
Description: record.description,
|
||||
CoreFlags: commandmeta.ReportingFlags(),
|
||||
}
|
||||
node.metadata = declaration
|
||||
if record.payload != nil {
|
||||
snapshot.runners[declaration.Key] = record.payload
|
||||
declaration.Runnable = record.payload.hasRun()
|
||||
@@ -126,7 +127,7 @@ func bridgeCommand(command Command, snapshot *routingSnapshot, next *commandmeta
|
||||
if child.record == nil || child.record.absent {
|
||||
continue
|
||||
}
|
||||
declaration.Children = append(declaration.Children, bridgeCommand(child, snapshot, next))
|
||||
declaration.Children = append(declaration.Children, bridgeCommand(node.children[child.record.name], snapshot, next))
|
||||
}
|
||||
return declaration
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
internalalias "gitea.maximumdirect.net/eric/CommandKit/internal/alias"
|
||||
internalcobra "gitea.maximumdirect.net/eric/CommandKit/internal/cobra"
|
||||
"gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
|
||||
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
|
||||
)
|
||||
|
||||
@@ -31,6 +32,7 @@ type installationCandidate struct {
|
||||
}
|
||||
|
||||
type canonicalNode struct {
|
||||
metadata *commandmeta.Command
|
||||
command Command
|
||||
path commandpath.Path
|
||||
children map[string]*canonicalNode
|
||||
|
||||
Reference in New Issue
Block a user