Files
commandkit/help_view.go

99 lines
2.9 KiB
Go

package commandkit
import (
"sort"
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
)
func (a *App) helpView(route routeResult, snapshot *routingSnapshot) commandmeta.HelpView {
view := commandmeta.HelpView{
EnteredPath: clonePath(route.enteredPath),
CanonicalPath: clonePath(route.canonicalPath),
Discovery: route.kind == routeDiscovery,
}
if snapshot == nil {
return view
}
if view.Discovery {
view.CommandAliases = discoveryHelpAliases(snapshot.commandAliases, route.discoveryPath)
view.FlagAliases = snapshot.discoveryFlags[route.discoveryPath.Key()].neutralRecords()
return view
}
view.FlagAliases = snapshot.flagAliases[route.canonicalPath.Key()].neutralRecords()
view.CommandAliases = routeHelpAliases(snapshot, route)
return view
}
func clonePath(path commandpath.Path) []string {
return append([]string(nil), path...)
}
func discoveryHelpAliases(aliases []commandmeta.CommandAlias, prefix commandpath.Path) []commandmeta.CommandAlias {
var result []commandmeta.CommandAlias
for _, alias := range aliases {
source := commandpath.FromTokens(alias.Source)
if len(source) <= len(prefix) || !source.HasPrefix(prefix) {
continue
}
result = append(result, commandmeta.CommandAlias{
Source: clonePath(source[len(prefix):]),
Target: append([]string(nil), alias.Target...),
})
}
return result
}
func routeHelpAliases(snapshot *routingSnapshot, route routeResult) []commandmeta.CommandAlias {
if len(route.canonicalPath) == 0 {
return append([]commandmeta.CommandAlias(nil), snapshot.commandAliases...)
}
node := traceCanonicalPath(snapshot.canonical, route.canonicalPath).exact
if node == nil || len(node.children) == 0 {
return nil
}
entered := route.enteredPath
canonical := route.canonicalPath
bySource := make(map[string]commandmeta.CommandAlias)
add := func(base commandpath.Path, includeOnlyWhenReached bool) {
for _, alias := range snapshot.commandAliases {
source := commandpath.FromTokens(alias.Source)
if len(source) <= len(base) || !source.HasPrefix(base) {
continue
}
suffix := source[len(base):]
if includeOnlyWhenReached {
enteredSource := append(entered.Clone(), suffix...)
if !snapshot.aliases.Resolve(enteredSource).Equal(commandpath.FromTokens(alias.Target)) {
continue
}
}
key := commandpath.FromTokens(suffix).Key()
if _, exists := bySource[key]; exists {
continue
}
bySource[key] = commandmeta.CommandAlias{
Source: clonePath(suffix),
Target: append([]string(nil), alias.Target...),
}
}
}
add(entered, false)
if !entered.Equal(canonical) {
add(canonical, true)
}
keys := make([]string, 0, len(bySource))
for key := range bySource {
keys = append(keys, key)
}
sort.Strings(keys)
result := make([]commandmeta.CommandAlias, 0, len(keys))
for _, key := range keys {
result = append(result, bySource[key])
}
return result
}