Skip to content

feat: add command groups to help output for better organization#10

Merged
timkrebs merged 1 commit into
mainfrom
KAN-13-gocli-add-command-groups-to-help-output
Mar 31, 2026
Merged

feat: add command groups to help output for better organization#10
timkrebs merged 1 commit into
mainfrom
KAN-13-gocli-add-command-groups-to-help-output

Conversation

@timkrebs
Copy link
Copy Markdown
Owner

Summary

  • Added CommandGroup struct with Name string and Commands []string fields, with godoc and a usage example.
  • Extended BasicHelpFunc(app string, groups ...CommandGroup) HelpFunc with a variadic groups parameter — fully backward compatible, since all existing callers omit it.
  • No groups → original flat "Available commands are:" layout (unchanged behavior).
  • With groups → each group is rendered under its own heading ("Server Commands:", etc.); any command not assigned to a group appears under "Other Commands:" at the end; empty groups are silently skipped.
  • FilteredHelpFunc requires no changes — it wraps any HelpFunc, so it automatically works with the grouped variant.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Refactor (no functional change)
  • Documentation update
  • CI / tooling change

Checklist

  • Tests added or updated to cover the change
  • go test -race ./... passes locally
  • golangci-lint run ./... passes locally (or lint issues are intentional and explained)
  • Public API additions / changes have godoc comments
  • CHANGELOG.md updated under ## [Unreleased] (for features and bug fixes)
  • PR title follows Conventional Commits format
    (feat: ..., fix: ..., docs: ..., etc.)

Testing notes

  • Flat output (sorted, header present)
  • Grouped headings, ordering, ungrouped fallback, fully-assigned (no "Other"), unknown keys, empty groups
  • FilteredHelpFunc + grouped BasicHelpFunc
  • End-to-end CLI.Run with -h using groups

Breaking change migration guide

No breaking changes

Copilot AI review requested due to automatic review settings March 31, 2026 10:09
@timkrebs timkrebs merged commit 47bfabd into main Mar 31, 2026
8 of 9 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optional command grouping support to the CLI help output so large CLIs can present commands under labeled headings, while preserving the existing flat help layout when no groups are provided.

Changes:

  • Introduces CommandGroup and extends BasicHelpFunc(app string, groups ...CommandGroup) to render grouped help output.
  • Keeps the original flat help output when groups is omitted (backward-compatible call sites).
  • Adds a new help_test.go test suite covering flat vs grouped output and FilteredHelpFunc interoperability.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
help.go Adds CommandGroup and grouped rendering logic to BasicHelpFunc while keeping the original flat output when no groups are passed.
help_test.go Adds unit tests for flat/grouped help rendering plus an end-to-end CLI.Run -h grouped output test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread help.go
Comment on lines +59 to 83
// printSection writes a titled block of commands. Commands that are
// not present in the commands map are silently skipped.
printSection := func(title string, keys []string) {
var present []string
for _, k := range keys {
if _, ok := commands[k]; ok {
present = append(present, k)
}
}
if len(present) == 0 {
return
}
sort.Strings(present)
buf.WriteString(title + "\n")
for _, key := range present {
commandFunc := commands[key]
command, err := commandFunc()
if err != nil {
fmt.Fprintf(os.Stderr, "[ERR] cli: Command '%s' failed to load: %s\n", key, err)
continue
}
padded := key + strings.Repeat(" ", maxKeyLen-len(key))
buf.WriteString(fmt.Sprintf(" %s %s\n", padded, command.Synopsis()))
}
}
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the same command key appears more than once in a group's Commands list (or appears in multiple groups), it will be rendered multiple times and its CommandFactory will be invoked multiple times. Consider de-duplicating command keys (within a section and/or globally with a rendered set so “first group wins”) to avoid confusing help output and redundant command loading when groups are misconfigured.

Copilot uses AI. Check for mistakes.
Comment thread help.go
key = fmt.Sprintf("%s%s", key, strings.Repeat(" ", maxKeyLen-len(key)))
buf.WriteString(fmt.Sprintf(" %s %s\n", key, command.Synopsis()))
for _, g := range groups {
printSection(g.Name+":", g.Commands)
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Groups with an empty or whitespace-only Name currently render a bare ":" heading (since the code always appends ":"). It would be safer to skip such groups (e.g., trim and require non-empty) or provide a default heading to avoid odd output.

Suggested change
printSection(g.Name+":", g.Commands)
title := strings.TrimSpace(g.Name)
if title == "" {
// Skip groups with empty or whitespace-only names to avoid
// rendering a bare ":" heading.
continue
}
printSection(title+":", g.Commands)

Copilot uses AI. Check for mistakes.
Comment thread help_test.go
}

// ---------------------------------------------------------------------------
// Backward compatibility: CLI wired with no groups renders flat output
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section header says this test covers backward compatibility / "no groups renders flat output", but the test actually configures BasicHelpFunc with groups and asserts grouped headings. Please update the comment (or test name) so it matches what the test is validating.

Suggested change
// Backward compatibility: CLI wired with no groups renders flat output
// Backward compatibility: CLI wired with groups renders grouped output

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants