Render help through command aliases

This commit is contained in:
2026-10-19 19:40:55 +00:00
parent 451a0c483f
commit a504efbad7
10 changed files with 391 additions and 11 deletions

View File

@@ -142,6 +142,87 @@ func (session *Session) RenderHelp(path []string) (string, *commandmeta.Failure)
return buffer.String(), nil
}
// RenderHelpView renders canonical command metadata with the selected entered
// path and its application-owned aliases.
func (session *Session) RenderHelpView(view commandmeta.HelpView) (string, *commandmeta.Failure) {
if session == nil || session.root == nil || session.metadata == nil {
return "", &commandmeta.Failure{Message: "command tree is nil"}
}
if view.Discovery {
return renderDiscoveryHelp(session.metadata.Name, view), nil
}
content, failure := session.RenderHelp(view.CanonicalPath)
if failure != nil {
return "", failure
}
if !commandpath.FromTokens(view.EnteredPath).Equal(commandpath.FromTokens(view.CanonicalPath)) {
if len(view.CanonicalPath) > 0 {
entered := displayCommandPath(session.metadata.Name, view.EnteredPath)
canonical := displayCommandPath(session.metadata.Name, view.CanonicalPath)
lines := strings.Split(content, "\n")
adjusted := make([]string, 0, len(lines)+1)
annotated := false
for _, line := range lines {
if strings.HasPrefix(line, " "+canonical) {
line = strings.Replace(line, canonical, entered, 1)
if !annotated {
adjusted = append(adjusted, line, "Alias for: "+displayCommandPath(session.metadata.Name, view.CanonicalPath))
annotated = true
continue
}
}
adjusted = append(adjusted, line)
}
content = strings.Join(adjusted, "\n")
}
}
return appendHelpAliases(content, view.CommandAliases, view.FlagAliases), nil
}
func appendHelpAliases(content string, commandAliases []commandmeta.CommandAlias, flagAliases []commandmeta.FlagAlias) string {
var sections []string
if len(commandAliases) > 0 {
lines := []string{"Command Aliases:"}
for _, alias := range commandAliases {
lines = append(lines, " "+strings.Join(alias.Source, " ")+" → "+strings.Join(alias.Target, " "))
}
sections = append(sections, strings.Join(lines, "\n"))
}
if len(flagAliases) > 0 {
lines := []string{"Flag Aliases:"}
for _, alias := range flagAliases {
lines = append(lines, " "+alias.Source+" → "+alias.Target)
}
sections = append(sections, strings.Join(lines, "\n"))
}
if len(sections) == 0 {
return content
}
return strings.TrimRight(content, "\n") + "\n\n" + strings.Join(sections, "\n\n") + "\n"
}
func renderDiscoveryHelp(rootName string, view commandmeta.HelpView) string {
lines := []string{"Usage:", " " + displayCommandPath(rootName, view.EnteredPath) + " [command]"}
if len(view.CommandAliases) > 0 {
lines = append(lines, "", "Available Aliases:")
for _, alias := range view.CommandAliases {
lines = append(lines, " "+strings.Join(alias.Source, " ")+" → "+strings.Join(alias.Target, " "))
}
}
if len(view.FlagAliases) > 0 {
lines = append(lines, "", "Flag Aliases:")
for _, alias := range view.FlagAliases {
lines = append(lines, " "+alias.Source+" → "+alias.Target)
}
}
return strings.Join(lines, "\n") + "\n"
}
func displayCommandPath(rootName string, path []string) string {
parts := append([]string{rootName}, path...)
return strings.Join(parts, " ")
}
// UsageLine returns Cobra's usage line for an exact path on this session.
func (session *Session) UsageLine(path []string) (string, *commandmeta.Failure) {
if session == nil || session.root == nil {

View File

@@ -47,6 +47,21 @@ type FlagAlias struct {
Target string
}
// CommandAlias describes one explicitly declared command route for help.
type CommandAlias struct {
Source []string
Target []string
}
// HelpView selects a canonical or alias-only command help presentation.
type HelpView struct {
EnteredPath []string
CanonicalPath []string
Discovery bool
CommandAliases []CommandAlias
FlagAliases []FlagAlias
}
// Failure is a neutral parsing or presentation failure.
type Failure struct {
Message string