mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 16:30:55 +01:00
7f4fb34182
It is better developing vmctl tool in VictoriaMetrics repository, so it could be released together with the rest of vmutils tools such as vmalert, vmagent, vmbackup, vmrestore and vmauth.
149 lines
3.1 KiB
Go
149 lines
3.1 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"sort"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/cpuguy83/go-md2man/v2/md2man"
|
|
)
|
|
|
|
// ToMarkdown creates a markdown string for the `*App`
|
|
// The function errors if either parsing or writing of the string fails.
|
|
func (a *App) ToMarkdown() (string, error) {
|
|
var w bytes.Buffer
|
|
if err := a.writeDocTemplate(&w); err != nil {
|
|
return "", err
|
|
}
|
|
return w.String(), nil
|
|
}
|
|
|
|
// ToMan creates a man page string for the `*App`
|
|
// The function errors if either parsing or writing of the string fails.
|
|
func (a *App) ToMan() (string, error) {
|
|
var w bytes.Buffer
|
|
if err := a.writeDocTemplate(&w); err != nil {
|
|
return "", err
|
|
}
|
|
man := md2man.Render(w.Bytes())
|
|
return string(man), nil
|
|
}
|
|
|
|
type cliTemplate struct {
|
|
App *App
|
|
Commands []string
|
|
GlobalArgs []string
|
|
SynopsisArgs []string
|
|
}
|
|
|
|
func (a *App) writeDocTemplate(w io.Writer) error {
|
|
const name = "cli"
|
|
t, err := template.New(name).Parse(MarkdownDocTemplate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return t.ExecuteTemplate(w, name, &cliTemplate{
|
|
App: a,
|
|
Commands: prepareCommands(a.Commands, 0),
|
|
GlobalArgs: prepareArgsWithValues(a.VisibleFlags()),
|
|
SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()),
|
|
})
|
|
}
|
|
|
|
func prepareCommands(commands []*Command, level int) []string {
|
|
var coms []string
|
|
for _, command := range commands {
|
|
if command.Hidden {
|
|
continue
|
|
}
|
|
usage := ""
|
|
if command.Usage != "" {
|
|
usage = command.Usage
|
|
}
|
|
|
|
prepared := fmt.Sprintf("%s %s\n\n%s\n",
|
|
strings.Repeat("#", level+2),
|
|
strings.Join(command.Names(), ", "),
|
|
usage,
|
|
)
|
|
|
|
flags := prepareArgsWithValues(command.Flags)
|
|
if len(flags) > 0 {
|
|
prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n"))
|
|
}
|
|
|
|
coms = append(coms, prepared)
|
|
|
|
// recursevly iterate subcommands
|
|
if len(command.Subcommands) > 0 {
|
|
coms = append(
|
|
coms,
|
|
prepareCommands(command.Subcommands, level+1)...,
|
|
)
|
|
}
|
|
}
|
|
|
|
return coms
|
|
}
|
|
|
|
func prepareArgsWithValues(flags []Flag) []string {
|
|
return prepareFlags(flags, ", ", "**", "**", `""`, true)
|
|
}
|
|
|
|
func prepareArgsSynopsis(flags []Flag) []string {
|
|
return prepareFlags(flags, "|", "[", "]", "[value]", false)
|
|
}
|
|
|
|
func prepareFlags(
|
|
flags []Flag,
|
|
sep, opener, closer, value string,
|
|
addDetails bool,
|
|
) []string {
|
|
args := []string{}
|
|
for _, f := range flags {
|
|
flag, ok := f.(DocGenerationFlag)
|
|
if !ok {
|
|
continue
|
|
}
|
|
modifiedArg := opener
|
|
|
|
for _, s := range flag.Names() {
|
|
trimmed := strings.TrimSpace(s)
|
|
if len(modifiedArg) > len(opener) {
|
|
modifiedArg += sep
|
|
}
|
|
if len(trimmed) > 1 {
|
|
modifiedArg += fmt.Sprintf("--%s", trimmed)
|
|
} else {
|
|
modifiedArg += fmt.Sprintf("-%s", trimmed)
|
|
}
|
|
}
|
|
modifiedArg += closer
|
|
if flag.TakesValue() {
|
|
modifiedArg += fmt.Sprintf("=%s", value)
|
|
}
|
|
|
|
if addDetails {
|
|
modifiedArg += flagDetails(flag)
|
|
}
|
|
|
|
args = append(args, modifiedArg+"\n")
|
|
|
|
}
|
|
sort.Strings(args)
|
|
return args
|
|
}
|
|
|
|
// flagDetails returns a string containing the flags metadata
|
|
func flagDetails(flag DocGenerationFlag) string {
|
|
description := flag.GetUsage()
|
|
value := flag.GetValue()
|
|
if value != "" {
|
|
description += " (default: " + value + ")"
|
|
}
|
|
return ": " + description
|
|
}
|