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, route) 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(snapshot *routingSnapshot, route routeResult) []commandmeta.CommandAlias { bySource := make(map[string]commandmeta.CommandAlias) for _, prefix := range []commandpath.Path{route.enteredPath, route.discoveryPath} { for _, alias := range snapshot.commandAliases { source := commandpath.FromTokens(alias.Source) if len(source) <= len(prefix) || !source.HasPrefix(prefix) { continue } suffix := source[len(prefix):] entered := append(route.enteredPath.Clone(), suffix...) target := snapshot.aliases.Resolve(entered) if traceCanonicalPath(snapshot.canonical, target).exact == nil { continue } bySource[suffix.Key()] = commandmeta.CommandAlias{Source: clonePath(suffix), Target: clonePath(target)} } } 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 } 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 }