205 lines
4.5 KiB
Go
205 lines
4.5 KiB
Go
package wand
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/iancoleman/strcase"
|
|
"io"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func formatManCommand(printf func(string, ...any), println func(...any), doc doc) {
|
|
println(".SH Synopsis")
|
|
printf(".B %s", escapeRoff(doc.synopsis.command))
|
|
if doc.synopsis.hasOptions {
|
|
printf(" [options...]")
|
|
}
|
|
|
|
for i := range doc.synopsis.arguments.names {
|
|
printf(
|
|
" [%s %s]",
|
|
doc.synopsis.arguments.names[i],
|
|
doc.synopsis.arguments.types[i],
|
|
)
|
|
}
|
|
|
|
min := doc.synopsis.arguments.minPositional
|
|
max := doc.synopsis.arguments.maxPositional
|
|
if doc.synopsis.arguments.variadic {
|
|
println("...")
|
|
if min > 0 || max > 0 {
|
|
println(".PP")
|
|
}
|
|
|
|
switch {
|
|
case min > 0 && max > 0:
|
|
printf("min %d and max %d total positional arguments\n", min, max)
|
|
case min > 0:
|
|
printf("min %d total positional arguments\n", min)
|
|
case max > 0:
|
|
printf("max %d total positional arguments\n", max)
|
|
}
|
|
}
|
|
|
|
if doc.synopsis.hasSubcommands {
|
|
if min > 0 || max > 0 {
|
|
println(".PP")
|
|
}
|
|
|
|
for i, sc := range doc.subcommands {
|
|
if i > 0 {
|
|
println(".br")
|
|
}
|
|
|
|
printf("%s %s\n", escapeRoff(doc.name), sc.name)
|
|
}
|
|
}
|
|
|
|
if doc.description != "" {
|
|
println(".SH Description")
|
|
println(manParagraphs(escapeRoff(doc.description)))
|
|
}
|
|
|
|
if len(doc.options) > 0 {
|
|
println(".SH Options")
|
|
if doc.hasBoolOptions || doc.hasListOptions {
|
|
println(".PP")
|
|
}
|
|
|
|
if doc.hasBoolOptions {
|
|
println(".B [b]:")
|
|
println("booelan flag, true or false, or no argument means true")
|
|
}
|
|
|
|
if doc.hasListOptions {
|
|
if doc.hasBoolOptions {
|
|
println(".br")
|
|
}
|
|
|
|
println(".B [*]:")
|
|
println("accepts multiple instances of the same option")
|
|
}
|
|
|
|
names, descriptions := prepareOptions(doc.options)
|
|
for _, n := range names {
|
|
println(".TP")
|
|
printf(".B %s\n", escapeRoff(n))
|
|
if descriptions[n] != "" {
|
|
println(manLines(escapeRoff(descriptions[n])))
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(doc.options) > 0 && commandNameExpression.MatchString(doc.appName) {
|
|
println(".SH Environment Variables")
|
|
println(manParagraphs(escapeRoff(envDocs)))
|
|
println(".PP Example environment variable:")
|
|
o := doc.options[0]
|
|
println(".TP")
|
|
printf(strcase.ToSnake(fmt.Sprintf("%s-%s", doc.appName, o.name)))
|
|
printf("=")
|
|
if o.isBool {
|
|
printf("true")
|
|
} else {
|
|
printf("42")
|
|
}
|
|
|
|
println()
|
|
}
|
|
|
|
if len(doc.options) > 0 && len(doc.configFiles) > 0 {
|
|
println(".SH Configuration Files")
|
|
println(manParagraphs(escapeRoff(configDocs)))
|
|
println(".PP Config files:")
|
|
for i, cf := range doc.configFiles {
|
|
if i > 0 {
|
|
println(".br")
|
|
}
|
|
|
|
if cf.fromOption {
|
|
println(escapeRoff("zero or more configuration files defined by the --config option"))
|
|
continue
|
|
}
|
|
|
|
if cf.fn != "" {
|
|
printf(escapeRoff(cf.fn))
|
|
if cf.optional {
|
|
printf(" (optional)")
|
|
}
|
|
|
|
println()
|
|
continue
|
|
}
|
|
}
|
|
|
|
println(".PP Example configuration entry:")
|
|
println(".PP")
|
|
o := doc.options[0]
|
|
printf(escapeRoff(fmt.Sprintf("# default for --%s:\n", o.name)))
|
|
println(".br")
|
|
printf(escapeRoff(strcase.ToSnake(o.name)))
|
|
printf(" = ")
|
|
if o.isBool {
|
|
printf("true")
|
|
} else {
|
|
printf("42")
|
|
}
|
|
|
|
println()
|
|
println(".PP Example for discarding an inherited entry:")
|
|
println(".PP")
|
|
println("# discarding an inherited entry:")
|
|
println(".br")
|
|
println(escapeRoff(strcase.ToSnake(o.name)))
|
|
}
|
|
}
|
|
|
|
func formatManMultiCommand(out io.Writer, doc doc) error {
|
|
printf, println, finish := printer(out)
|
|
printf(".TH %s 1 %s \"%s\"\n", escapeRoff(doc.appName), escapeRoff(doc.date.Format(time.DateOnly)), escapeRoff(doc.appName))
|
|
printf(".SH Name\n%s\n", escapeRoff(doc.appName))
|
|
println(".SH Provides several commands:")
|
|
println(".PP")
|
|
allCommands := allCommands(doc)
|
|
for i, c := range allCommands {
|
|
if i > 0 {
|
|
println(".br")
|
|
}
|
|
|
|
println(escapeRoff(c.fullCommand))
|
|
}
|
|
|
|
for _, c := range allCommands {
|
|
printf(".SH %s\n", escapeRoff(strings.ToUpper(c.fullCommand)))
|
|
formatManCommand(printf, println, c)
|
|
}
|
|
|
|
return finish()
|
|
}
|
|
|
|
func formatManSingleCommand(out io.Writer, doc doc) error {
|
|
printf, println, finish := printer(out)
|
|
printf(".TH %s 1 %s \"%s\"\n", escapeRoff(doc.appName), escapeRoff(doc.date.Format(time.DateOnly)), escapeRoff(doc.appName))
|
|
printf(".SH Name\n%s\n", escapeRoff(doc.appName))
|
|
formatManCommand(printf, println, doc)
|
|
return finish()
|
|
}
|
|
|
|
func formatMan(out io.Writer, doc doc) error {
|
|
var hasSubcommands bool
|
|
for _, sc := range doc.subcommands {
|
|
if !sc.isHelp && !sc.isVersion {
|
|
continue
|
|
}
|
|
|
|
hasSubcommands = true
|
|
break
|
|
}
|
|
|
|
if hasSubcommands {
|
|
return formatManMultiCommand(out, doc)
|
|
}
|
|
|
|
return formatManSingleCommand(out, doc)
|
|
}
|