Resolve entered command routes to canonical paths
This commit is contained in:
96
route.go
Normal file
96
route.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package commandkit
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
|
||||
)
|
||||
|
||||
type routeKind uint8
|
||||
|
||||
const (
|
||||
routeUnknown routeKind = iota
|
||||
routeCanonical
|
||||
routeDiscovery
|
||||
)
|
||||
|
||||
type routeResult struct {
|
||||
kind routeKind
|
||||
args []string
|
||||
enteredPath commandpath.Path
|
||||
canonicalPath commandpath.Path
|
||||
discoveryPath commandpath.Path
|
||||
}
|
||||
|
||||
func resolveEnteredRoute(args []string, snapshot *routingSnapshot) routeResult {
|
||||
path, trailing := commandPathTokens(args)
|
||||
result := routeResult{kind: routeUnknown}
|
||||
if snapshot == nil {
|
||||
result.args = append(append([]string(nil), path...), trailing...)
|
||||
result.enteredPath = path.Clone()
|
||||
return result
|
||||
}
|
||||
|
||||
resolved, origins := snapshot.aliases.ResolveWithProvenance(path)
|
||||
trace := traceCanonicalPath(snapshot.canonical, resolved)
|
||||
switch {
|
||||
case trace.exact != nil:
|
||||
result.kind = routeCanonical
|
||||
result.canonicalPath = trace.exact.path.Clone()
|
||||
case trace.operandOwner != nil:
|
||||
result.kind = routeCanonical
|
||||
result.canonicalPath = trace.operandOwner.path.Clone()
|
||||
}
|
||||
|
||||
if result.kind == routeCanonical {
|
||||
result.enteredPath = enteredEndpoint(path, origins, len(result.canonicalPath))
|
||||
} else if len(path) == 0 {
|
||||
result.kind = routeCanonical
|
||||
} else if discovery, ok := findDiscoveryPath(snapshot.discoveryFlags, path); ok {
|
||||
result.kind = routeDiscovery
|
||||
result.discoveryPath = discovery
|
||||
result.enteredPath = discovery.Clone()
|
||||
} else {
|
||||
result.enteredPath = path.Clone()
|
||||
}
|
||||
|
||||
result.args = make([]string, 0, len(resolved)+len(trailing))
|
||||
result.args = append(result.args, resolved...)
|
||||
result.args = append(result.args, trailing...)
|
||||
return result
|
||||
}
|
||||
|
||||
func commandPathTokens(args []string) (commandpath.Path, []string) {
|
||||
end := len(args)
|
||||
for index, token := range args {
|
||||
if token == "--" || (token != "-" && strings.HasPrefix(token, "-")) {
|
||||
end = index
|
||||
break
|
||||
}
|
||||
}
|
||||
path := make(commandpath.Path, end)
|
||||
copy(path, args[:end])
|
||||
return path, append([]string(nil), args[end:]...)
|
||||
}
|
||||
|
||||
func enteredEndpoint(path commandpath.Path, origins [][]int, canonicalLength int) commandpath.Path {
|
||||
inputLength := 0
|
||||
for _, componentOrigins := range origins[:canonicalLength] {
|
||||
for _, origin := range componentOrigins {
|
||||
if origin+1 > inputLength {
|
||||
inputLength = origin + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return path[:inputLength].Clone()
|
||||
}
|
||||
|
||||
func findDiscoveryPath(contexts map[string]resolvedFlagAliases, path commandpath.Path) (commandpath.Path, bool) {
|
||||
for length := len(path); length > 0; length-- {
|
||||
prefix := path[:length]
|
||||
if _, exists := contexts[prefix.Key()]; exists {
|
||||
return prefix.Clone(), true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
Reference in New Issue
Block a user