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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions