Resolve entered command routes to canonical paths
This commit is contained in:
28
internal/alias/provenance_test.go
Normal file
28
internal/alias/provenance_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package alias
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
|
||||
)
|
||||
|
||||
func TestResolveWithProvenanceCarriesInputOriginsThroughChains(t *testing.T) {
|
||||
resolver, err := NewResolver([]Mapping{
|
||||
{Source: commandpath.Path{"collections"}, Target: commandpath.Path{"list", "collections"}},
|
||||
{Source: commandpath.Path{"list", "collections"}, Target: commandpath.Path{"promptkit", "list", "collections"}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
path := commandpath.Path{"collections", "--format", "yaml"}
|
||||
gotPath, gotOrigins := resolver.ResolveWithProvenance(path)
|
||||
if want := (commandpath.Path{"promptkit", "list", "collections", "--format", "yaml"}); !reflect.DeepEqual(gotPath, want) {
|
||||
t.Fatalf("resolved path = %v, want %v", gotPath, want)
|
||||
}
|
||||
wantOrigins := [][]int{{0}, {0}, {0}, {1}, {2}}
|
||||
if !reflect.DeepEqual(gotOrigins, wantOrigins) {
|
||||
t.Fatalf("origins = %v, want %v", gotOrigins, wantOrigins)
|
||||
}
|
||||
}
|
||||
@@ -132,3 +132,39 @@ func (resolver *Resolver) Resolve(path commandpath.Path) commandpath.Path {
|
||||
current = next
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveWithProvenance resolves a command path and carries the input token
|
||||
// indexes that contributed to each output component. Rewritten target
|
||||
// components inherit the origins of the matched source prefix.
|
||||
func (resolver *Resolver) ResolveWithProvenance(path commandpath.Path) (commandpath.Path, [][]int) {
|
||||
current := path.Clone()
|
||||
origins := make([][]int, len(path))
|
||||
for index := range path {
|
||||
origins[index] = []int{index}
|
||||
}
|
||||
for {
|
||||
next, mapping, matched := resolver.ResolveOnce(current)
|
||||
if !matched {
|
||||
return current, origins
|
||||
}
|
||||
|
||||
matchedOrigins := make([]int, 0)
|
||||
seen := make(map[int]struct{})
|
||||
for _, componentOrigins := range origins[:len(mapping.Source)] {
|
||||
for _, origin := range componentOrigins {
|
||||
if _, exists := seen[origin]; exists {
|
||||
continue
|
||||
}
|
||||
seen[origin] = struct{}{}
|
||||
matchedOrigins = append(matchedOrigins, origin)
|
||||
}
|
||||
}
|
||||
nextOrigins := make([][]int, 0, len(mapping.Target)+len(origins)-len(mapping.Source))
|
||||
for range mapping.Target {
|
||||
nextOrigins = append(nextOrigins, append([]int(nil), matchedOrigins...))
|
||||
}
|
||||
nextOrigins = append(nextOrigins, origins[len(mapping.Source):]...)
|
||||
current = next
|
||||
origins = nextOrigins
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user