Skip to content

Commit ee0b971

Browse files
committed
fix: collapse the usage string to a single line
cobra's default advertised two usage modes for a runnable command with subcommands — "flagsmith [flags]" and "flagsmith [command]" — which reads oddly for a root whose bare run just prints help. Rewrite the Usage block so each command shows one context-appropriate line: "<path> [command] [flags]" for groups, or the command's own use line for leaves. Done as a string replace on cobra's own default template so it survives version bumps (no-op if the block changes, guarded by a test). beep boop
1 parent 19d4a1b commit ee0b971

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

internal/cmd/cmd_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,31 @@ func TestFlagDelete(t *testing.T) {
24232423
})
24242424
}
24252425

2426+
func TestUsageIsSingleLine(t *testing.T) {
2427+
// Given / When — root help
2428+
out, err := run("", "--help")
2429+
if err != nil {
2430+
t.Fatal(err)
2431+
}
2432+
2433+
// Then — one context-appropriate line, not cobra's default two-line form
2434+
if !strings.Contains(out, "flagsmith [command] [flags]") {
2435+
t.Errorf("root usage = %q, want the single-line form", out)
2436+
}
2437+
if strings.Contains(out, "flagsmith [flags]\n") {
2438+
t.Errorf("root usage still shows the two-line form:\n%s", out)
2439+
}
2440+
2441+
// Leaf commands render their own use line
2442+
leaf, err := run("", "flag", "list", "--help")
2443+
if err != nil {
2444+
t.Fatal(err)
2445+
}
2446+
if !strings.Contains(leaf, "flagsmith flag list [flags]") {
2447+
t.Errorf("leaf usage = %q, want its own use line", leaf)
2448+
}
2449+
}
2450+
24262451
func TestFlagIdentity(t *testing.T) {
24272452
// max_items is feature id 2 in defaultFeatures; user-1 is core identity 501.
24282453

internal/cmd/root.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"strings"
78

89
"github.com/spf13/cobra"
910
"github.com/spf13/pflag"
@@ -12,6 +13,18 @@ import (
1213
"github.com/Flagsmith/flagsmith-cli/internal/output"
1314
)
1415

16+
// singleLineUsage rewrites cobra's default two-line Usage block (one line for
17+
// running the command bare, another for a subcommand) into a single
18+
// context-appropriate line: "<path> [command] [flags]" for groups, or the
19+
// command's own use line for leaves. Applied as a string replace on cobra's
20+
// own template so it survives version bumps (a no-op if the block ever changes,
21+
// caught by TestUsageIsSingleLine).
22+
func singleLineUsage(template string) string {
23+
const defaultBlock = "Usage:{{if .Runnable}}\n {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}\n {{.CommandPath}} [command]{{end}}"
24+
const oneLine = "Usage:{{if .HasAvailableSubCommands}}\n {{.CommandPath}} [command] [flags]{{else}}\n {{.UseLine}}{{end}}"
25+
return strings.Replace(template, defaultBlock, oneLine, 1)
26+
}
27+
1528
// apiURL is the resolved instance URL for the current invocation, set by
1629
// applyContext. Flag values live in the *Flag variables below.
1730
var apiURL string
@@ -116,6 +129,8 @@ func init() {
116129
flags.StringVar(&jqFlag, "jq", "",
117130
"filter JSON output through a jq expression (implies --json)")
118131

132+
rootCmd.SetUsageTemplate(singleLineUsage(rootCmd.UsageTemplate()))
133+
119134
// Hidden aliases: --api for --api-url, --no-input for --yes.
120135
rootCmd.SetGlobalNormalizationFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
121136
switch name {

0 commit comments

Comments
 (0)