commandUsage adds the command usage info for the given commands to the given [strings.Builder]. It also takes the full name of our command as it appears in the terminal (cmdName), (eg: "core build"), and the name of the command we are running (eg: "build"). To be a command that is included in the u
(b *strings.Builder, cmdName string, cmd string, cmds ...*Cmd[T])
| 124 | // generate usage for "mod init", "mod tidy", and "mod edit". This ensures |
| 125 | // that only relevant commands are shown in the usage. |
| 126 | func commandUsage[T any](b *strings.Builder, cmdName string, cmd string, cmds ...*Cmd[T]) { |
| 127 | acmds := []*Cmd[T]{} // actual commands we care about |
| 128 | var rcmd *Cmd[T] // root command |
| 129 | cmdstrs := strings.Fields(cmd) // subcommand strings in passed command |
| 130 | |
| 131 | // need this label so that we can continue outer loop when we have non-matching cmdstr |
| 132 | outer: |
| 133 | for _, c := range cmds { |
| 134 | cstrs := strings.Fields(c.Name) // subcommand strings in command we are checking |
| 135 | if len(cstrs) != len(cmdstrs)+1 { // we must be one deeper |
| 136 | continue |
| 137 | } |
| 138 | for i, cmdstr := range cmdstrs { |
| 139 | if cmdstr != cstrs[i] { // every subcommand so far must match |
| 140 | continue outer |
| 141 | } |
| 142 | } |
| 143 | if c.Root { |
| 144 | rcmd = c |
| 145 | } else if c.Name != cmd { // if it is the same subcommand we are already on, we handle it above in main Usage |
| 146 | acmds = append(acmds, c) |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | if len(acmds) != 0 { |
| 151 | b.WriteString(indent + logx.CmdColor(cmdName+" <subcommand> ") + logx.SuccessColor("[flags]\n")) |
| 152 | } |
| 153 | |
| 154 | if rcmd != nil { |
| 155 | b.WriteString(logx.TitleColor("\nDefault command:\n")) |
| 156 | b.WriteString(indent + logx.CmdColor(rcmd.Name) + "\n" + indent + indent + strings.ReplaceAll(rcmd.Doc, "\n", "\n"+indent+indent) + "\n") // need to put two indents on every newline for formatting |
| 157 | } |
| 158 | |
| 159 | if len(acmds) == 0 && cmd != "" { // nothing to do |
| 160 | return |
| 161 | } |
| 162 | |
| 163 | b.WriteString(logx.TitleColor("\nSubcommands:\n")) |
| 164 | |
| 165 | // if we are in root, we also add help |
| 166 | if cmd == "" { |
| 167 | b.WriteString(indent + logx.CmdColor("help") + "\n" + indent + indent + "Help shows usage information for a command\n") |
| 168 | } |
| 169 | |
| 170 | for _, c := range acmds { |
| 171 | b.WriteString(indent + logx.CmdColor(c.Name)) |
| 172 | if c.Doc != "" { |
| 173 | // we only want the first paragraph of text for subcommand usage; after that is where more specific details can go |
| 174 | doc, _, _ := strings.Cut(c.Doc, "\n\n") |
| 175 | b.WriteString("\n" + indent + indent + strings.ReplaceAll(doc, "\n", "\n"+indent+indent)) // need to put two indents on every newline for formatting |
| 176 | } |
| 177 | b.WriteString("\n") |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | // flagUsage adds the flag usage info for the given fields |
| 182 | // to the given [strings.Builder]. |
no test coverage detected