Skip to content

Support for custom help sections or hooks to extend help output #82

@phikai

Description

@phikai

Description

Problem

Applications using Fang may need to display additional custom sections in their help output beyond the standard sections (usage, commands, flags, examples). Currently, there's no way to extend Fang's help rendering to include custom content.

Use Case

CLI applications often need to display additional information in their help output, such as:

  • Environment Variables - Documentation for environment variables that affect the CLI
  • Learn More - Additional resources or tips
  • Feedback/Support - How to report bugs or request features
  • Configuration - Where config files are located
  • License/Legal - License or attribution information

Many applications use Cobra's Annotations map to store this custom content:

rootCmd := &cobra.Command{
    // ...
    Annotations: map[string]string{
        "help:environment": heredoc.Doc(`
            MYAPP_HOST: Specify the URL of the server
            MYAPP_TOKEN: Authentication token for API requests
            // ... more env vars
        `),
        "help:feedback": `
            Encountered a bug? Open an issue at github.com/org/repo
        `,
    },
}

With a custom help function, these annotations can be rendered as additional sections. However, Fang's Execute() function sets its own help function internally, making it impossible to extend the help output without copying and modifying Fang's internal rendering logic.

Current Limitations

  1. fang.Execute() sets root.SetHelpFunc() internally and then calls ExecuteContext(), which blocks
  2. The helpFn function in help.go is not exported, so it can't be wrapped or extended
  3. No hooks or callbacks are provided to inject custom content before/after standard help rendering
  4. Copying Fang's entire help rendering logic (~481 lines) creates maintenance burden

Proposed Solutions

Option 1: Help Section Hook (Preferred)

Add an option to provide a callback that runs after Fang's standard help rendering:

fang.Execute(ctx, root,
    fang.WithHelpAppender(func(w io.Writer, cmd *cobra.Command, styles Styles) {
        // Custom rendering logic here
        if envHelp, ok := cmd.Annotations["help:environment"]; ok {
            fmt.Fprintln(w, styles.Title.Render("ENVIRONMENT VARIABLES"))
            fmt.Fprintln(w, envHelp)
        }
    }),
)

Option 2: Annotation Support

Built-in support for rendering custom annotation sections:

fang.Execute(ctx, root,
    fang.WithCustomSections(map[string]string{
        "help:environment": "ENVIRONMENT VARIABLES",
        "help:feedback":    "FEEDBACK",
    }),
)

Option 3: Export helpFn and makeStyles

Export the help rendering function so downstream users can wrap it:

// In fang package
func RenderHelp(c *cobra.Command, w io.Writer, styles Styles) {
    // existing helpFn logic
}

// In user code
root.SetHelpFunc(func(c *cobra.Command, args []string) {
    w := colorprofile.NewWriter(c.OutOrStdout(), os.Environ())
    fang.RenderHelp(c, w, styles)
    appendCustomSections(w, c, styles)
})

// Then call root.ExecuteContext() directly instead of fang.Execute()

Benefits

  • Allows applications to maintain existing help customizations when migrating to Fang
  • Provides flexibility for application-specific help content
  • Avoids need to fork or copy Fang's rendering logic
  • Maintains Fang's excellent styling while adding custom sections

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions