Commit 54236b3f88
54236b3f88b1c12cca152c40b62ceecc823a22e7
parent: c2a6cbdbec
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-24 04:05 UTC
help: usage keeps required flags; owner/name as written
Ref #254
internal/control/help.go
+6 −9
| @@ -146,17 +146,14 @@ func (c *Ctx) helpVerb(w io.Writer, cmd Command, below []Command) { |
| 146 | 146 | fmt.Fprintln(w, cmd.Summary) |
| 147 | 147 | fmt.Fprintln(w) |
| 148 | 148 | c.heading(w, "USAGE") |
| 149 | // Cutting at the first optional flag drops the rest of the usage |
| 150 | // syntax behind "[flags]" — safe only for what is actually optional. |
| 151 | // A required flag (repo delete --yes) or an alternative |
| 152 | // (notifications read <id>... | --all) has no " [--" to cut at, so |
| 153 | // the usage prints whole. |
| 149 | 154 | shape := cmd.Usage |
| 150 | 155 | if i := strings.Index(shape, " [--"); i >= 0 { |
| 151 | | shape = shape[:i] |
| 152 | | } else if i := strings.Index(shape, " --"); i >= 0 { |
| 153 | | shape = shape[:i] |
| 154 | | } |
| 155 | | if c.Term.Cols > 0 { |
| 156 | | shape = strings.Replace(shape, "<owner/name>", "[<owner/name>]", 1) |
| 157 | | } |
| 158 | | if len(cmd.Flags) > 0 { |
| 159 | | shape += " [flags]" |
| 156 | shape = shape[:i] + " [flags]" |
| 160 | 157 | } |
| 161 | 158 | fmt.Fprintf(w, " %s %s\n", c.program(), shape) |
| 162 | 159 | fmt.Fprintln(w) |
internal/control/help_test.go
+23 −1
| @@ -25,7 +25,7 @@ func TestHelpVerb(t *testing.T) { |
| 25 | 25 | out := helpOut(t, Term{Cols: 100}, "issue", "list") |
| 26 | 26 | for _, want := range []string{ |
| 27 | 27 | "list issues\n", |
| 28 | | "USAGE\n gitbay issue list [<owner/name>] [flags]\n", |
| 28 | "USAGE\n gitbay issue list <owner/name> [flags]\n", |
| 29 | 29 | "FLAGS\n", |
| 30 | 30 | " --state open|closed|all", |
| 31 | 31 | "which issues (default open)\n", |
| @@ -45,6 +45,28 @@ func TestHelpVerb(t *testing.T) { |
| 45 | 45 | } |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | // TestHelpVerbUsageKeepsRequiredFlags covers a usage line with no |
| 49 | // optional flag to cut at: it prints whole, not truncated to "[flags]" |
| 50 | // as though --yes were optional. |
| 51 | func TestHelpVerbUsageKeepsRequiredFlags(t *testing.T) { |
| 52 | out := helpOut(t, Term{Cols: 100}, "repo", "delete") |
| 53 | if !strings.Contains(out, "USAGE\n gitbay repo delete <owner/name> --yes\n") { |
| 54 | t.Errorf("missing required --yes in usage:\n%s", out) |
| 55 | } |
| 56 | if strings.Contains(out, "[flags]") { |
| 57 | t.Errorf("repo delete has no optional flags; should not print [flags]:\n%s", out) |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | // TestHelpVerbUsageKeepsAlternative covers a usage line whose flag is |
| 62 | // one side of a "|" alternative, not an optional extra. |
| 63 | func TestHelpVerbUsageKeepsAlternative(t *testing.T) { |
| 64 | out := helpOut(t, Term{Cols: 100}, "notifications", "read") |
| 65 | if !strings.Contains(out, "USAGE\n gitbay notifications read <id>... | --all\n") { |
| 66 | t.Errorf("missing whole alternative in usage:\n%s", out) |
| 67 | } |
| 68 | } |
| 69 | |
| 48 | 70 | func TestHelpNoun(t *testing.T) { |
| 49 | 71 | out := helpOut(t, Term{Cols: 100}, "issue") |
| 50 | 72 | for _, want := range []string{"issues\n", "READ\n", "WRITE\n", " list ", " create ", "gitbay issue <verb> --help for flags.\n"} { |