Skip to content

DefaultUsage causes infinite recursion when called from UsageFunc #15

@mfridman

Description

@mfridman

DefaultUsage checks UsageFunc at the top and calls it if set:

func DefaultUsage(root *Command) string {
	// ...
	terminalCmd := root.terminal()
	if terminalCmd.UsageFunc != nil {
		return terminalCmd.UsageFunc(terminalCmd)
	}
	// ... build default output
}

This means you can't call DefaultUsage from within a UsageFunc to compose on top of it -- it recurses infinitely. The only workaround is temporarily nilling out UsageFunc before calling DefaultUsage:

UsageFunc: func(c *cli.Command) string {
    c.UsageFunc = nil
    s := cli.DefaultUsage(c)
    return s + "\n\nExamples:\n  ..."
},

The function name already implies "give me the default behavior," so the UsageFunc check is surprising. Removing those lines would make DefaultUsage composable without breaking any existing behavior -- commands without UsageFunc are unaffected, and the top-level dispatch in the library still calls UsageFunc directly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions