- appendList: one home for the List newline-join rule (was duplicated across accumulate and set) - fold the redundant Int64 getter into Int; drop the truthy helper for the shared boolWord vocabulary - add Opt.Metavar so help derives the value placeholder from data instead of branching on the option name (seed-time) No behavior change; --help output is byte-identical.
120 lines
2.9 KiB
Go
120 lines
2.9 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// Version is the program version, overridable at build time via -ldflags.
|
|
var Version = "0.1.0"
|
|
|
|
// PrintVersion writes the version banner.
|
|
func PrintVersion(w io.Writer) {
|
|
fmt.Fprintf(w, "got %s — a Rob-Pike-style command-line downloader in Go\n", Version)
|
|
}
|
|
|
|
// PrintHelp writes usage. A bare -h/--help (empty tag) shows only the Basic
|
|
// group, keeping the default terse; --help=all shows every group and
|
|
// --help=<group> (basic/http/bittorrent/advanced) filters to one.
|
|
func PrintHelp(w io.Writer, tag string) {
|
|
all := tag == "all"
|
|
// Empty tag means a bare -h/--help: default to the Basic group only.
|
|
bare := tag == ""
|
|
want, filtered := tagByName(tag)
|
|
if bare {
|
|
want, filtered = Basic, true
|
|
}
|
|
if !all && !bare && !filtered {
|
|
fmt.Fprintf(w, "got: unknown help tag %q (use all|basic|http|bittorrent|advanced)\n\n", tag)
|
|
}
|
|
fmt.Fprint(w, `Usage: got [OPTIONS] URI | magnet:... | file.torrent ...
|
|
|
|
A multi-protocol download tool: segmented HTTP(S) and BitTorrent.
|
|
|
|
`)
|
|
for _, group := range []Tag{Basic, HTTP, BitTorrent, Advanced} {
|
|
if filtered && !all && group != want {
|
|
continue
|
|
}
|
|
fmt.Fprintf(w, "%s options:\n", title(group.String()))
|
|
for i := range options {
|
|
o := &options[i]
|
|
if o.Tag != group {
|
|
continue
|
|
}
|
|
fmt.Fprintf(w, " %s %s\n", flagLabel(o), o.Help)
|
|
}
|
|
fmt.Fprintln(w)
|
|
}
|
|
// Only the full listing (all groups) repeats the meta flags.
|
|
if all || !filtered {
|
|
fmt.Fprint(w, " -h, --help[=TAG] show help (TAG: all|basic|http|bittorrent|advanced)\n")
|
|
fmt.Fprint(w, " -v, --version show version\n\n")
|
|
}
|
|
if bare {
|
|
fmt.Fprint(w, "Showing basic options. Use --help=all for every option, or --help=advanced for advanced ones.\n")
|
|
}
|
|
}
|
|
|
|
// title upper-cases the first letter of a single word.
|
|
func title(s string) string {
|
|
if s == "" {
|
|
return s
|
|
}
|
|
return strings.ToUpper(s[:1]) + s[1:]
|
|
}
|
|
|
|
func tagByName(name string) (Tag, bool) {
|
|
switch name {
|
|
case "basic":
|
|
return Basic, true
|
|
case "http":
|
|
return HTTP, true
|
|
case "bittorrent", "bt":
|
|
return BitTorrent, true
|
|
case "advanced":
|
|
return Advanced, true
|
|
default:
|
|
return Basic, false
|
|
}
|
|
}
|
|
|
|
// flagLabel renders the "-x, --long=ARG" column for one option.
|
|
func flagLabel(o *Opt) string {
|
|
var b strings.Builder
|
|
if o.Short != 0 {
|
|
fmt.Fprintf(&b, "-%c, ", o.Short)
|
|
} else {
|
|
b.WriteString(" ")
|
|
}
|
|
b.WriteString("--" + o.Long)
|
|
if m := metavar(o); m != "" {
|
|
b.WriteString("=" + m)
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
// metavar is the placeholder shown after a value-taking flag, e.g. the "N" in
|
|
// "--split=N". An explicit Opt.Metavar wins; otherwise it derives from the Kind.
|
|
// Bool takes no value, so its metavar is empty and no "=ARG" is printed.
|
|
func metavar(o *Opt) string {
|
|
if o.Metavar != "" {
|
|
return o.Metavar
|
|
}
|
|
switch o.Kind {
|
|
case Bool:
|
|
return ""
|
|
case Size:
|
|
return "SIZE"
|
|
case Int:
|
|
return "N"
|
|
case Float:
|
|
return "RATIO"
|
|
case Enum:
|
|
return strings.Join(o.Enum, "|")
|
|
default:
|
|
return "VAL"
|
|
}
|
|
}
|