Merge pull request #830 from saschagrunert/docs-gen

Add markdown and man page docs generation methods
main
Audrius Butkevicius 5 years ago committed by GitHub
commit 2c477e720e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -978,7 +978,7 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "error_case_empty_input_with_required_flag_on_command",
appRunInput: []string{"myCLI", "myCommand"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -987,9 +987,9 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "error_case_empty_input_with_required_flag_on_subcommand",
appRunInput: []string{"myCLI", "myCommand", "mySubCommand"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Subcommands: []Command{Command{
Subcommands: []Command{{
Name: "mySubCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -1005,7 +1005,7 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "valid_case_help_input_with_required_flag_on_command",
appRunInput: []string{"myCLI", "myCommand", "--help"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -1013,9 +1013,9 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "valid_case_help_input_with_required_flag_on_subcommand",
appRunInput: []string{"myCLI", "myCommand", "mySubCommand", "--help"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Subcommands: []Command{Command{
Subcommands: []Command{{
Name: "mySubCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -1031,7 +1031,7 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "error_case_optional_input_with_required_flag_on_command",
appRunInput: []string{"myCLI", "myCommand", "--optional", "cats"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}, StringFlag{Name: "optional"}},
}},
@ -1040,9 +1040,9 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "error_case_optional_input_with_required_flag_on_subcommand",
appRunInput: []string{"myCLI", "myCommand", "mySubCommand", "--optional", "cats"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Subcommands: []Command{Command{
Subcommands: []Command{{
Name: "mySubCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}, StringFlag{Name: "optional"}},
}},
@ -1058,7 +1058,7 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "valid_case_required_flag_input_on_command",
appRunInput: []string{"myCLI", "myCommand", "--requiredFlag", "cats"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -1066,9 +1066,9 @@ func TestRequiredFlagAppRunBehavior(t *testing.T) {
{
testCase: "valid_case_required_flag_input_on_subcommand",
appRunInput: []string{"myCLI", "myCommand", "mySubCommand", "--requiredFlag", "cats"},
appCommands: []Command{Command{
appCommands: []Command{{
Name: "myCommand",
Subcommands: []Command{Command{
Subcommands: []Command{{
Name: "mySubCommand",
Flags: []Flag{StringFlag{Name: "requiredFlag", Required: true}},
}},
@ -1825,6 +1825,18 @@ func (c *customBoolFlag) GetName() string {
return c.Nombre
}
func (c *customBoolFlag) TakesValue() bool {
return false
}
func (c *customBoolFlag) GetValue() string {
return "value"
}
func (c *customBoolFlag) GetUsage() string {
return "usage"
}
func (c *customBoolFlag) Apply(set *flag.FlagSet) {
set.String(c.Nombre, c.Nombre, "")
}

@ -0,0 +1,146 @@
package cli
import (
"bytes"
"fmt"
"io"
"sort"
"strings"
"text/template"
"github.com/cpuguy83/go-md2man/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
Date string
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.Flags),
SynopsisArgs: prepareArgsSynopsis(a.Flags),
})
}
func prepareCommands(commands []Command, level int) []string {
coms := []string{}
for i := range commands {
command := &commands[i]
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 strings.Split(flag.GetName(), ",") {
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
}

@ -0,0 +1,115 @@
package cli
import (
"io/ioutil"
"testing"
)
func testApp() *App {
app := NewApp()
app.Name = "greet"
app.Flags = []Flag{
StringFlag{
Name: "socket, s",
Usage: "some usage text",
Value: "value",
},
StringFlag{Name: "flag, fl, f"},
BoolFlag{
Name: "another-flag, b",
Usage: "another usage text",
},
}
app.Commands = []Command{{
Aliases: []string{"c"},
Flags: []Flag{
StringFlag{Name: "flag, fl, f"},
BoolFlag{
Name: "another-flag, b",
Usage: "another usage text",
},
},
Name: "config",
Usage: "another usage test",
Subcommands: []Command{{
Aliases: []string{"s", "ss"},
Flags: []Flag{
StringFlag{Name: "sub-flag, sub-fl, s"},
BoolFlag{
Name: "sub-command-flag, s",
Usage: "some usage text",
},
},
Name: "sub-config",
Usage: "another usage test",
}},
}, {
Aliases: []string{"i", "in"},
Name: "info",
Usage: "retrieve generic information",
}, {
Name: "some-command",
}}
app.UsageText = "app [first_arg] [second_arg]"
app.Usage = "Some app"
app.Author = "Harrison"
app.Email = "harrison@lolwut.com"
app.Authors = []Author{{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
return app
}
func expectFileContent(t *testing.T, file, expected string) {
data, err := ioutil.ReadFile(file)
expect(t, err, nil)
expect(t, string(data), expected)
}
func TestToMarkdownFull(t *testing.T) {
// Given
app := testApp()
// When
res, err := app.ToMarkdown()
// Then
expect(t, err, nil)
expectFileContent(t, "testdata/expected-doc-full.md", res)
}
func TestToMarkdownNoFlags(t *testing.T) {
// Given
app := testApp()
app.Flags = nil
// When
res, err := app.ToMarkdown()
// Then
expect(t, err, nil)
expectFileContent(t, "testdata/expected-doc-no-flags.md", res)
}
func TestToMarkdownNoCommands(t *testing.T) {
// Given
app := testApp()
app.Commands = nil
// When
res, err := app.ToMarkdown()
// Then
expect(t, err, nil)
expectFileContent(t, "testdata/expected-doc-no-commands.md", res)
}
func TestToMan(t *testing.T) {
// Given
app := testApp()
// When
res, err := app.ToMan()
// Then
expect(t, err, nil)
expectFileContent(t, "testdata/expected-doc-full.man", res)
}

@ -28,9 +28,9 @@ var assets = func() http.FileSystem {
"/source/flag-types.json": &vfsgen۰CompressedFileInfo{
name: "flag-types.json",
modTime: time.Time{},
uncompressedSize: 2559,
uncompressedSize: 3364,
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\xc1\x6e\x9c\x30\x10\x86\xef\x3c\xc5\xc8\xbd\x40\xb5\x82\x1c\x56\x7b\xd8\x63\x55\xb5\xda\x5b\xa5\x34\xbd\x24\x51\xe4\x80\x21\x56\x1d\x1b\xd9\x43\xd4\x28\xca\xbb\x57\xf6\x2e\xbb\x60\x0c\x62\x5b\x2d\xb9\xfe\x23\x98\xef\x9b\xb1\xe6\x36\x02\x78\x8b\x00\x00\x88\xa4\xcf\x8c\x6c\x81\x7c\x51\x4a\x90\xd5\x3e\xc3\xd7\xda\x65\x8f\x9d\xec\x85\x8a\xc6\x86\x25\x15\x86\x1d\xb2\x82\x19\x24\x5b\x40\xdd\xb4\x49\xae\x24\xb2\x3f\xf8\x50\xb0\x92\x36\xc2\x16\x89\xfb\xa0\xfd\x4b\x4d\xb5\x61\xda\xc6\x06\x75\xae\xe4\x4b\xfa\xc3\x26\xb6\x79\x5c\xa6\xbf\x6c\x8f\xf4\x1a\x35\x97\x55\x9c\x24\x24\x02\x78\x5f\x85\x51\x7f\xfe\x3f\x6b\xa1\x72\xa4\x5c\xd8\x8f\x01\x9f\x28\x02\x37\xae\x0c\x8f\xaf\xd0\xf2\x2f\xa9\xf5\xb5\xd1\x14\xb9\x92\xbe\x19\xf2\x67\x96\xfa\xc5\x56\xb1\xeb\x33\x69\x18\x1b\xc6\xe0\x09\xb1\x36\xdb\x2c\xab\x94\xa0\xb2\x4a\x95\xae\xb2\xfa\x77\x95\xd9\x0e\xd9\x27\x87\xdc\xf6\x49\x26\xd4\xaf\x86\xda\x8e\xb1\xf7\x83\xf9\xde\xdf\x84\xa2\xb8\x59\xfb\xda\x65\x3f\x9e\x25\x3c\x0f\xb6\xb7\x23\xd7\x7d\x00\xbb\x82\xcd\x7a\x14\xf8\x3b\x93\x4c\xf3\xdc\x07\xf6\xe2\x71\xe0\xee\xb3\x0c\x10\x4b\x2e\xfc\xe1\xb7\x2d\xb8\x44\xa6\x4b\x9a\xb3\xb7\xf7\x31\xb8\x9d\x0c\xcc\x92\xcb\x05\x26\xb9\x93\xa1\x39\x5e\x4d\x8e\x72\x27\x31\xc0\xfa\xa1\xa4\xbd\x4f\x1f\x72\xea\xfa\x59\xaa\xd8\x45\xc5\x94\xcb\xb5\xe0\x39\xf3\x85\x3e\xfb\x85\x4b\xbc\x8c\xdb\xfb\xce\xdc\x4e\xda\x47\xcd\xf8\x48\x91\x24\xfb\xc8\x2a\x33\xad\x95\x8e\x25\x17\x53\x52\x9b\xf5\xa8\x96\x57\xba\x98\xd8\xe9\xf1\x8e\xa9\x1d\x48\xce\x93\xdb\xef\xde\x17\x33\xbd\xf4\x5f\xdf\xe0\x1d\xb9\x23\x43\xe8\xe1\xab\x9b\x4b\x19\xde\x41\xa0\x76\x99\x25\xf4\x87\x12\xdc\x42\x87\xe5\xbc\x35\xdc\xf0\xd0\xcd\x6a\x16\x39\x5a\xb6\xf7\xd9\x57\xeb\x86\x0f\xcf\x56\xb3\xc0\xdd\x9a\x86\x0d\x1f\xae\xc6\xbf\x5c\xd1\x7d\xf4\x37\x00\x00\xff\xff\x66\x52\x85\x44\xff\x09\x00\x00"),
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x95\x41\x6f\x9b\x40\x10\x85\xef\xfc\x8a\xe9\x56\x95\xa0\xb2\x20\x87\x28\x07\x4b\xbd\x54\x55\x2b\xdf\x2a\xb9\xe9\x25\x44\xd1\x06\x16\xb2\xea\x7a\x16\x2d\x43\xd4\xc8\xf2\x7f\xaf\x16\x9b\x04\x16\x70\x48\x5b\x2c\x5f\x7c\x78\xe3\xe5\xed\xfb\x66\x47\x73\xe3\x01\x6c\x3d\x00\x00\x86\x7c\x23\xd8\x12\xd8\x67\xad\x15\x5b\xec\x35\x7a\x2a\x6a\xed\xbe\xa5\x3d\x72\x55\x59\x31\xe3\xaa\x14\x07\x2d\x15\x25\xb1\x25\x90\xa9\x1a\x25\xd1\x48\xe2\x37\xdd\xa5\x22\xe3\x95\xb2\x45\x56\x1f\x68\xbe\x52\x70\x53\x0a\x63\xe5\x92\x4c\xa2\xf1\x31\xfc\x6e\x15\x6b\xee\x67\xe1\x4f\xeb\x11\xae\xc9\x48\xcc\xfd\x20\xe8\x58\xef\x55\x7b\xd2\x08\xaa\x0c\x42\xcc\x62\xc6\x3c\x80\xdd\x62\x38\xcc\x8f\x7f\x4f\x93\xea\x84\xb8\x54\xf6\x30\xd0\x03\x27\x90\x65\x5d\x86\xfb\x27\x68\x12\x9e\x57\xf0\x2f\x95\xe1\x24\x35\xba\xd9\x49\x6e\x44\xe8\x16\x1b\x08\xed\xc4\x47\x19\xf8\xa5\x10\xf0\x40\x54\x94\xcb\x28\xca\xb5\xe2\x98\x87\xda\xe4\x51\xf1\x2b\x8f\xac\x43\xf4\xbe\x0e\xd5\xf8\x04\x47\xe0\x5c\xf4\xc1\xd4\x77\xec\x7c\xe0\xad\x64\xdc\xbf\x8f\x51\xfa\xaa\x34\xa7\xab\x4b\x17\x52\xd6\x95\x27\xe1\x99\x16\xad\xd3\xf3\xda\xbd\x17\x6d\x01\x57\x97\xaf\xc5\xdb\x50\xb8\x2e\x8c\x44\xca\xfc\x98\x7d\xc8\x62\xb6\x68\x22\x8f\x46\xfd\x26\x50\x18\x99\xb8\x51\x1d\x79\x3c\x6a\x7b\x40\x06\xb2\xa2\x54\x6e\x93\x1b\x0b\x89\x24\x4c\xc6\x13\xb1\xdd\x8d\xc4\x92\x59\x73\x7d\x78\xf7\x09\x50\x2a\xd8\xc6\x18\x53\x4c\x23\xed\xb4\xc5\x9d\xfd\x99\x30\x08\x2b\x1c\x68\xb0\xc4\x13\xb4\x77\x85\x43\xcd\xbd\x78\x7b\x7f\xd3\x29\xfd\x5d\x21\x0d\xa4\x3c\x87\x8c\xfb\xa3\x77\x09\xaf\xfd\xec\xad\xfc\x5a\x4a\xe7\xa1\xb0\x56\x32\x11\x2e\x8a\x8f\x6e\x61\x8e\x87\x7e\x73\xdb\x22\xfe\x02\xec\x19\x90\xff\x7c\x8b\x20\xd8\x4b\x16\x96\x30\x46\x1b\x1f\xa5\x1a\xc3\x31\xfb\x74\x8c\x12\x73\x4a\xb3\x31\x7b\x99\xc5\x31\x6a\x87\x9b\x9c\x0d\xb7\x83\x8b\xc3\xac\xec\xa8\x7f\x3b\x73\xb5\x6f\x8f\x47\x7f\xca\x5e\x05\xd0\xcd\x79\x3c\xca\xf0\x1b\x18\xa8\xcd\xf3\x08\xba\xe4\x06\x5f\x41\xeb\x2e\x67\xf3\x0c\xae\xe5\xd0\x76\xa9\x4e\xb2\x5e\xac\xf7\x09\xf7\xcb\xb5\xec\x2f\x98\xea\x04\x1b\x66\x52\x4c\x67\xc5\x54\xff\x6f\xc7\x78\xb7\xde\x9f\x00\x00\x00\xff\xff\x61\x79\x63\x47\x24\x0d\x00\x00"),
},
"/templates": &vfsgen۰DirInfo{
name: "templates",
@ -46,9 +46,9 @@ var assets = func() http.FileSystem {
"/templates/cli_flags_generated.gotpl": &vfsgen۰CompressedFileInfo{
name: "cli_flags_generated.gotpl",
modTime: time.Time{},
uncompressedSize: 2102,
uncompressedSize: 2575,
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x54\xc1\x52\xdb\x30\x10\x3d\xdb\x5f\xb1\xcd\x70\xb0\x99\x34\xb9\x97\xe1\x44\xa0\x65\xa6\x03\x4c\xa1\xdc\x15\x7b\xe5\x68\x10\x52\x90\xd6\x50\x26\x93\x7f\xef\xac\x24\x3b\x4e\x48\x21\x17\x7a\xd3\x6a\x9f\xde\x7b\x7a\x5a\x7b\x3a\x85\x33\x5b\x23\x34\x68\xd0\x09\xc2\x1a\xe6\xaf\x20\x9b\x13\x98\x5d\xc3\xd5\xf5\x1d\x9c\xcf\x2e\xef\x26\x79\xbe\x14\xd5\x83\x68\x10\x56\x2b\x98\xdc\xc4\xf5\x95\x78\x44\x58\xaf\xf3\x5c\x3d\x2e\xad\x23\x28\xf2\x6c\x24\xb5\x68\x46\x79\x36\xf2\xe4\x2a\x6b\x9e\x79\x49\xea\x11\x47\x79\x99\xaf\x56\xe0\x84\x69\x10\x8e\xd4\x18\x8e\x18\x08\xdf\x4e\x61\x72\xa1\x45\xe3\x99\x66\x3a\x65\xf2\xd0\x98\x24\x6a\xee\x81\xf2\x20\x20\xc0\x5f\x14\x2d\x80\x5e\x97\xb8\x01\xde\x71\xb5\x5e\xf7\xf5\xcc\x56\x24\x94\x66\xbe\x6d\xe0\x90\xd1\x93\x6b\x2b\x82\x55\x9e\xf1\x6e\x96\x79\x72\xca\x34\x79\xf6\xdb\x8b\x66\x50\x9e\x9b\xe7\x7b\xe1\x36\xf5\x85\xd2\x78\x23\x68\xd1\x6f\xfc\xc2\xa7\x56\x39\xac\xb3\xb9\xb5\x3a\xcf\x7e\xa8\xba\x46\x93\xa5\x6a\xb5\xfa\x0a\x4a\x02\x3e\x25\x03\xf7\x42\xb7\x08\xe4\xda\x90\x59\x16\xca\x6c\xf7\x1e\xf1\x18\x9a\xba\x5f\x0f\x29\x66\xe8\x49\x19\x41\xca\x9a\x0d\xd1\x60\x33\x3b\x7e\x97\x6f\x9d\x73\xc6\xb7\xc1\x3c\x38\xa4\xd6\x19\x8e\xd6\xa1\xa8\xc5\x5c\x23\x38\x5c\x3a\xf4\x68\x28\x2a\x58\x09\xb4\x50\x1e\x9e\xd9\x29\x9f\x2c\xa4\x75\xd0\x72\x46\x50\xa3\x14\xad\x26\x5f\xe6\xb2\x35\x15\x14\x72\x6f\xd0\x65\x12\x2b\x4a\x88\x91\x71\xe4\x51\x18\xb8\x1f\xbb\xe8\x0a\x59\x26\x73\xdf\x91\xc2\xf9\xce\x1d\x2d\x10\x0c\x6f\x04\x33\x18\xc6\xe0\x03\xc9\x44\xb1\x4f\x53\x06\x64\x92\xba\xf4\xdd\xf3\xf5\x6a\x2f\x0b\xa4\x05\x3a\xb0\x0e\x8c\xa5\x5e\x90\x27\xd0\x25\xec\x07\xe2\x1b\xd2\xa2\x04\x9e\x83\x2d\xf5\xae\x97\x1c\xec\x52\x80\xb6\xf6\xc1\x43\xbb\x0c\xca\x21\x76\xbe\xb7\x00\x6d\x2b\xa1\xf7\x2a\x8e\x3b\xef\x5b\x7c\x67\xd6\x10\xfe\xa1\x59\x7c\x24\x66\x56\x32\xdc\x48\xda\xd6\x74\x57\xa8\xe0\x38\xe1\xca\x37\xd4\x45\xc8\x3c\xe6\x17\xba\x7c\x1e\xa1\x23\x0e\xc3\x35\x1a\x0d\xbf\xbb\x61\x27\x6c\xa3\xf6\x5b\x1f\x66\xdf\xe9\xc6\x71\x90\x0c\xdf\xbb\x5d\xee\x35\x31\x86\x6a\xc2\x9b\xb7\x48\xfd\x8c\x68\x3b\x17\xfa\xe0\xf0\x9a\x00\xff\xcc\xf4\xf6\x1b\xfa\x5f\x19\x2a\x09\xd2\xf3\x9f\x34\xa6\x18\xcd\x5c\xc4\xc8\xba\x08\xcb\x13\xc6\x7c\x39\x05\xa3\xc2\x44\x1e\x14\xbc\xf4\x65\x9e\xad\xfb\x47\xfa\x77\x3e\xfc\x2e\x21\x95\x77\xe8\x52\x10\x63\xf0\x48\x70\x1c\xda\xc9\xe3\x67\x66\x23\x39\x17\x8f\x34\xf9\x19\x9c\x05\x27\x65\x8c\x6c\x98\xc6\xc6\xc0\x8d\x70\x1e\x5d\xd4\x5e\xf2\xba\x1e\x03\x3a\xc7\x34\xbd\x52\xc2\x0c\x5d\xec\x40\x65\xfc\xd9\x87\xda\xba\xc2\x28\x5d\x32\x36\xfd\xd5\x59\x9e\x81\x03\x03\x07\x64\x9c\xf1\x53\xbc\x71\x7a\x26\x3c\x45\xb7\xbb\x0c\x83\xfe\xd0\x69\x82\x45\xc3\x03\x53\x07\xbe\x73\x7f\xe2\x6f\x00\x00\x00\xff\xff\x9b\xde\x9c\x04\x36\x08\x00\x00"),
compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x55\x4d\x8f\xdb\x36\x10\x3d\x4b\xbf\x62\x6a\xe4\x20\x2d\x5c\xfb\xde\x20\xa7\x75\x36\x0d\x50\x24\x8b\xc6\xcd\x9d\x96\x86\x32\xb1\x34\xa9\x90\xa3\xdd\x2e\x0c\xff\xf7\x62\x48\xea\xc3\x1f\x58\xfb\xb2\x3d\x89\xe4\x0c\xdf\x7b\x7c\x33\xa4\x96\x4b\xb8\xb7\x35\x42\x83\x06\x9d\x20\xac\x61\xf3\x0a\xb2\xf9\x08\xab\xef\xf0\xed\xfb\x1a\x3e\xaf\xbe\xae\x17\x79\xde\x8a\xea\x49\x34\x08\xfb\x3d\x2c\x1e\xe3\xf8\x9b\xd8\x21\x1c\x0e\x79\xae\x76\xad\x75\x04\x45\x9e\xcd\xa4\x16\xcd\x8c\xbf\x3b\xe2\x8f\x27\x57\x59\xf3\xcc\x43\x52\x3b\x9c\xe5\x65\xbe\xdf\x83\x13\xa6\x41\xf8\xa0\xe6\xf0\x81\xf3\xe1\x8f\x4f\xb0\x78\xd0\xa2\xf1\x8c\xb6\x5c\x32\x47\x08\x2c\x12\x03\xc7\x40\x79\x10\x10\xd2\x5f\x14\x6d\x81\x5e\x5b\x1c\x13\xd7\x3c\x3b\x1c\x86\xf9\xca\x56\x24\x94\x66\xbc\xe3\xc4\x29\xa2\x27\xd7\x55\x04\xfb\x3c\xe3\xd5\x2c\xf3\xe4\x94\x69\xf2\xec\x1f\x2f\x9a\xc9\xf4\xb3\x79\xfe\x29\xdc\x38\x7f\x50\x1a\x1f\x05\x6d\x87\x85\xbf\xf1\x57\xa7\x1c\xd6\xd9\xc6\x5a\x9d\x67\x7f\xaa\xba\x46\x93\xa5\xd9\x7e\xff\x3b\x28\x09\xf8\x2b\x09\xf8\x29\x74\x87\x40\xae\x0b\xd6\x65\x61\x9a\x9d\x9e\x23\x6e\x43\x53\x0f\xe3\x29\xc4\x0a\x3d\x29\x23\x48\x59\x33\x02\x4d\x16\xb3\xbb\x37\xf1\x0e\x39\x7b\xfc\x23\x88\x07\x87\xd4\x39\xc3\xd6\x3a\x14\xb5\xd8\x68\x04\x87\xad\x43\x8f\x86\x22\x83\x95\x40\x5b\xe5\xe1\x99\x95\xf2\xce\x42\x5a\x07\x1d\x7b\x04\x35\x4a\xd1\x69\xf2\x65\x2e\x3b\x53\x41\x21\x2f\x1a\x5d\x26\xb2\xa2\x84\x68\x19\x5b\x1e\x89\x81\xe3\x31\x8a\xae\x90\x65\x12\xf7\x05\x29\xec\xef\xd5\xd1\x16\xc1\xf0\x42\x10\x83\xa1\x0d\xae\x50\x26\x88\x4b\x9c\x32\x64\x26\xaa\xaf\xbe\x2f\xdf\xc0\xf6\xb2\x45\xda\xa2\x03\xeb\xc0\x58\x1a\x08\xb9\x03\x5d\xca\xbd\x42\x3e\x82\x16\x25\x70\x1f\x1c\xb1\xf7\xb1\xa4\x60\x2d\x9e\xd0\xc7\xb6\x18\xce\xcb\x55\x9d\x9c\x15\x88\x73\x40\xc4\x22\xcc\xc1\xb2\xbe\x17\xe5\x11\xa4\xd0\x1e\xaf\xa8\x19\x09\xce\xd5\x0c\x3b\xa2\x80\xa1\x3d\xbe\x20\x85\x6b\x70\x54\x82\x58\xf4\xe4\x27\x77\xc1\xed\xb5\x08\x60\x97\x8b\x11\x42\x23\xed\x89\x13\x89\x21\xf5\x1f\x08\xdf\x43\x9c\xb4\xa9\x30\x35\x08\x03\xb8\x6b\xe9\x95\x91\x52\x96\x3a\x33\xd1\xd8\x1e\x8a\x40\x68\xbd\xb8\xae\xbd\xb7\x6e\xd4\x7e\xec\x5a\xba\x4a\x83\x77\xa7\x40\xa0\xad\x7d\xf2\xd0\xb5\x41\x4a\x24\xb7\x12\x04\x68\x5b\x09\x7d\x91\x77\xde\x1b\x70\x84\x77\x6f\x0d\xe1\xbf\xb4\x8a\xb7\x8e\x91\x95\x0c\x2d\x2a\x6d\x67\xfa\x9e\xac\xe0\x2e\xe5\x95\x67\xd0\x45\xb8\x44\xf1\x1c\x21\xca\xfb\x11\x7a\xe0\xf0\x5a\xcc\x66\xd3\x87\x74\x1a\x09\xcb\xa8\xfd\xd1\x4b\x3b\x44\xfa\xf7\x65\x52\x5b\x3e\x77\xd7\x5e\x14\x31\x87\x6a\xc1\x8b\x3f\x90\x86\x4b\xaf\xed\x46\xe8\x9b\xcd\x6b\x42\xfa\x7b\xba\x77\x59\xd0\xff\xe5\xa1\x92\x20\x3d\xff\x1a\xa3\x8b\x51\xcc\x43\xb4\xac\xb7\xb0\xfc\xc8\x39\xbf\x7d\x02\xa3\xc2\xa5\xbe\xc9\x78\xe9\xcb\x3c\x3b\x9c\xbf\x00\x67\xfe\x70\x5d\x82\x2b\x6f\xc0\x25\x23\xe6\xe0\x91\xe0\x2e\x84\x93\xc6\xf7\xf4\x46\xb2\x2f\x1e\x69\xf1\x57\x50\x16\x94\x94\xd1\xb2\xa9\x1b\xa3\x80\x47\xe1\x3c\xba\xc8\xdd\xf2\xb8\x9e\x03\x3a\xc7\x30\x03\x53\xca\x99\xaa\x38\x49\x95\xf1\xbe\x87\xb9\x75\x85\x51\xba\xe4\xdc\xf4\x9b\x66\x7a\x4e\x9c\x08\xb8\xc1\xe3\x8c\x4b\x71\xa6\xf4\x5e\x78\x8a\x6a\x4f\x11\x26\xf1\xa9\xd2\x94\x16\x05\x4f\x44\xdd\x58\xe7\x71\xc7\x7f\x01\x00\x00\xff\xff\xa4\x4d\x6e\xce\x0f\x0a\x00\x00"),
},
}
fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{

@ -27,6 +27,7 @@ type FlagType struct {
ContextType string `json:"context_type"`
Parser string `json:"parser"`
ParserCast string `json:"parser_cast"`
ValueString string `json:"valueString"`
}
func main() {

@ -5,7 +5,8 @@
"value": false,
"dest": true,
"context_default": "false",
"parser": "strconv.ParseBool(f.Value.String())"
"parser": "strconv.ParseBool(f.Value.String())",
"valueString": "return \"\""
},
{
"name": "BoolT",
@ -14,7 +15,8 @@
"dest": true,
"doctail": " that is true by default",
"context_default": "false",
"parser": "strconv.ParseBool(f.Value.String())"
"parser": "strconv.ParseBool(f.Value.String())",
"valueString": "return \"\""
},
{
"name": "Duration",
@ -23,7 +25,8 @@
"dest": true,
"doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
"context_default": "0",
"parser": "time.ParseDuration(f.Value.String())"
"parser": "time.ParseDuration(f.Value.String())",
"valueString": "return f.Value.String()"
},
{
"name": "Float64",
@ -31,7 +34,8 @@
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseFloat(f.Value.String(), 64)"
"parser": "strconv.ParseFloat(f.Value.String(), 64)",
"valueString": "return fmt.Sprintf(\"%f\", f.Value)"
},
{
"name": "Generic",
@ -39,7 +43,8 @@
"value": true,
"dest": false,
"context_default": "nil",
"context_type": "interface{}"
"context_type": "interface{}",
"valueString": "if f.Value != nil {\n\t\treturn f.Value.String()\n\t}\n\treturn \"\""
},
{
"name": "Int64",
@ -47,7 +52,8 @@
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
"valueString": "return fmt.Sprintf(\"%d\", f.Value)"
},
{
"name": "Int",
@ -56,7 +62,8 @@
"dest": true,
"context_default": "0",
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
"parser_cast": "int(parsed)"
"parser_cast": "int(parsed)",
"valueString": "return fmt.Sprintf(\"%d\", f.Value)"
},
{
"name": "IntSlice",
@ -65,7 +72,8 @@
"dest": false,
"context_default": "nil",
"context_type": "[]int",
"parser": "(f.Value.(*IntSlice)).Value(), error(nil)"
"parser": "(f.Value.(*IntSlice)).Value(), error(nil)",
"valueString": "if f.Value != nil {\n\t\treturn f.Value.String()\n\t}\n\treturn \"\""
},
{
"name": "Int64Slice",
@ -74,7 +82,8 @@
"dest": false,
"context_default": "nil",
"context_type": "[]int64",
"parser": "(f.Value.(*Int64Slice)).Value(), error(nil)"
"parser": "(f.Value.(*Int64Slice)).Value(), error(nil)",
"valueString": "if f.Value != nil {\n\t\treturn f.Value.String()\n\t}\n\treturn \"\""
},
{
"name": "String",
@ -82,7 +91,8 @@
"value": true,
"dest": true,
"context_default": "\"\"",
"parser": "f.Value.String(), error(nil)"
"parser": "f.Value.String(), error(nil)",
"valueString": "return f.Value"
},
{
"name": "StringSlice",
@ -91,7 +101,8 @@
"dest": false,
"context_default": "nil",
"context_type": "[]string",
"parser": "(f.Value.(*StringSlice)).Value(), error(nil)"
"parser": "(f.Value.(*StringSlice)).Value(), error(nil)",
"valueString": "if f.Value != nil {\n\t\treturn f.Value.String()\n\t}\n\treturn \"\""
},
{
"name": "Uint64",
@ -99,7 +110,8 @@
"value": true,
"dest": true,
"context_default": "0",
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
"valueString": "return fmt.Sprintf(\"%d\", f.Value)"
},
{
"name": "Uint",
@ -108,6 +120,7 @@
"dest": true,
"context_default": "0",
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
"parser_cast": "uint(parsed)"
"parser_cast": "uint(parsed)",
"valueString": "return fmt.Sprintf(\"%d\", f.Value)"
}
]

@ -4,6 +4,7 @@ package {{ .PackageName }}
import (
"flag"
"fmt"
"strconv"
"time"
)
@ -40,6 +41,22 @@ func (f {{ $flag.Name }}Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f {{ $flag.Name }}Flag) TakesValue() bool {
return {{ $flag.Value }}
}
// GetUsage returns the usage string for the flag
func (f {{ $flag.Name }}Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f {{ $flag.Name }}Flag) GetValue() string {
{{ $flag.ValueString }}
}
// {{ $flag.Name }} looks up the value of a local {{ $flag.Name }}Flag, returns
// {{ $flag.ContextDefault }} if not found
func (c *Context) {{ $flag.Name }}(name string) {{ if ne .ContextType "" }}{{ $flag.ContextType }}{{ else }}{{ $flag.Type }}{{- end }} {
@ -66,4 +83,4 @@ func lookup{{ $flag.Name }}(name string, set *flag.FlagSet) {{ if ne .ContextTyp
}
return {{ $flag.ContextDefault }}
}
{{ end }}
{{ end }}

@ -83,6 +83,21 @@ type RequiredFlag interface {
IsRequired() bool
}
// DocGenerationFlag is an interface that allows documentation generation for the flag
type DocGenerationFlag interface {
Flag
// TakesValue returns true of the flag takes a value, otherwise false
TakesValue() bool
// GetUsage returns the usage string for the flag
GetUsage() string
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
GetValue() string
}
// errorableFlag is an interface that allows us to return errors during apply
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors

@ -4,6 +4,7 @@ package cli
import (
"flag"
"fmt"
"strconv"
"time"
)
@ -35,6 +36,22 @@ func (f BoolFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f BoolFlag) TakesValue() bool {
return false
}
// GetUsage returns the usage string for the flag
func (f BoolFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f BoolFlag) GetValue() string {
return ""
}
// Bool looks up the value of a local BoolFlag, returns
// false if not found
func (c *Context) Bool(name string) bool {
@ -89,6 +106,22 @@ func (f BoolTFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f BoolTFlag) TakesValue() bool {
return false
}
// GetUsage returns the usage string for the flag
func (f BoolTFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f BoolTFlag) GetValue() string {
return ""
}
// BoolT looks up the value of a local BoolTFlag, returns
// false if not found
func (c *Context) BoolT(name string) bool {
@ -144,6 +177,22 @@ func (f DurationFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f DurationFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f DurationFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f DurationFlag) GetValue() string {
return f.Value.String()
}
// Duration looks up the value of a local DurationFlag, returns
// 0 if not found
func (c *Context) Duration(name string) time.Duration {
@ -199,6 +248,22 @@ func (f Float64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Float64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Float64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Float64Flag) GetValue() string {
return fmt.Sprintf("%f", f.Value)
}
// Float64 looks up the value of a local Float64Flag, returns
// 0 if not found
func (c *Context) Float64(name string) float64 {
@ -253,6 +318,25 @@ func (f GenericFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f GenericFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f GenericFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f GenericFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Generic looks up the value of a local GenericFlag, returns
// nil if not found
func (c *Context) Generic(name string) interface{} {
@ -308,6 +392,22 @@ func (f Int64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Int64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Int64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Int64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Int64 looks up the value of a local Int64Flag, returns
// 0 if not found
func (c *Context) Int64(name string) int64 {
@ -363,6 +463,22 @@ func (f IntFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f IntFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f IntFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f IntFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Int looks up the value of a local IntFlag, returns
// 0 if not found
func (c *Context) Int(name string) int {
@ -417,6 +533,25 @@ func (f IntSliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f IntSliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f IntSliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f IntSliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// IntSlice looks up the value of a local IntSliceFlag, returns
// nil if not found
func (c *Context) IntSlice(name string) []int {
@ -471,6 +606,25 @@ func (f Int64SliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Int64SliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Int64SliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Int64SliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Int64Slice looks up the value of a local Int64SliceFlag, returns
// nil if not found
func (c *Context) Int64Slice(name string) []int64 {
@ -526,6 +680,22 @@ func (f StringFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f StringFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f StringFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f StringFlag) GetValue() string {
return f.Value
}
// String looks up the value of a local StringFlag, returns
// "" if not found
func (c *Context) String(name string) string {
@ -580,6 +750,25 @@ func (f StringSliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f StringSliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f StringSliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f StringSliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// StringSlice looks up the value of a local StringSliceFlag, returns
// nil if not found
func (c *Context) StringSlice(name string) []string {
@ -635,6 +824,22 @@ func (f Uint64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Uint64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Uint64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Uint64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Uint64 looks up the value of a local Uint64Flag, returns
// 0 if not found
func (c *Context) Uint64(name string) uint64 {
@ -690,6 +895,22 @@ func (f UintFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f UintFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f UintFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f UintFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Uint looks up the value of a local UintFlag, returns
// 0 if not found
func (c *Context) Uint(name string) uint {
@ -716,3 +937,4 @@ func lookupUint(name string, set *flag.FlagSet) uint {
}
return 0
}

@ -4,6 +4,7 @@ go 1.10
require (
github.com/BurntSushi/toml v0.3.1
github.com/cpuguy83/go-md2man v1.0.10
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd // indirect
gopkg.in/yaml.v2 v2.2.2

@ -1,5 +1,9 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=

@ -10,79 +10,6 @@ import (
"unicode/utf8"
)
// AppHelpTemplate is the text template for the Default help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var AppHelpTemplate = `NAME:
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
`
// CommandHelpTemplate is the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var CommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
CATEGORY:
{{.Category}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
`
// SubcommandHelpTemplate is the text template for the subcommand help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var SubcommandHelpTemplate = `NAME:
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
`
var helpCommand = Command{
Name: "help",
Aliases: []string{"h"},

@ -0,0 +1,107 @@
package cli
// AppHelpTemplate is the text template for the Default help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var AppHelpTemplate = `NAME:
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
`
// CommandHelpTemplate is the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var CommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
CATEGORY:
{{.Category}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
`
// SubcommandHelpTemplate is the text template for the subcommand help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
var SubcommandHelpTemplate = `NAME:
{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
`
var MarkdownDocTemplate = `% {{ .App.Name }}(8) {{ .App.Description }}
% {{ .App.Author }}
# NAME
{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }}
# SYNOPSIS
{{ .App.Name }}
{{ if .SynopsisArgs }}
` + "```" + `
{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + `
{{ end }}{{ if .App.UsageText }}
# DESCRIPTION
{{ .App.UsageText }}
{{ end }}
**Usage**:
` + "```" + `
{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
` + "```" + `
{{ if .GlobalArgs }}
# GLOBAL OPTIONS
{{ range $v := .GlobalArgs }}
{{ $v }}{{ end }}
{{ end }}{{ if .Commands }}
# COMMANDS
{{ range $v := .Commands }}
{{ $v }}{{ end }}{{ end }}`

@ -0,0 +1,80 @@
.nh
.TH greet(8)
.SH Harrison
.SH NAME
.PP
greet \- Some app
.SH SYNOPSIS
.PP
greet
.PP
.RS
.nf
[\-\-another\-flag|\-b]
[\-\-flag|\-\-fl|\-f]=[value]
[\-\-socket|\-s]=[value]
.fi
.RE
.SH DESCRIPTION
.PP
app [first\_arg] [second\_arg]
.PP
\fBUsage\fP:
.PP
.RS
.nf
greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
.fi
.RE
.SH GLOBAL OPTIONS
.PP
\fB\-\-another\-flag, \-b\fP: another usage text
.PP
\fB\-\-flag, \-\-fl, \-f\fP="":
.PP
\fB\-\-socket, \-s\fP="": some usage text (default: value)
.SH COMMANDS
.SH config, c
.PP
another usage test
.PP
\fB\-\-another\-flag, \-b\fP: another usage text
.PP
\fB\-\-flag, \-\-fl, \-f\fP="":
.SS sub\-config, s, ss
.PP
another usage test
.PP
\fB\-\-sub\-command\-flag, \-s\fP: some usage text
.PP
\fB\-\-sub\-flag, \-\-sub\-fl, \-s\fP="":
.SH info, i, in
.PP
retrieve generic information
.SH some\-command

@ -0,0 +1,62 @@
% greet(8)
% Harrison
# NAME
greet - Some app
# SYNOPSIS
greet
```
[--another-flag|-b]
[--flag|--fl|-f]=[value]
[--socket|-s]=[value]
```
# DESCRIPTION
app [first_arg] [second_arg]
**Usage**:
```
greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
```
# GLOBAL OPTIONS
**--another-flag, -b**: another usage text
**--flag, --fl, -f**="":
**--socket, -s**="": some usage text (default: value)
# COMMANDS
## config, c
another usage test
**--another-flag, -b**: another usage text
**--flag, --fl, -f**="":
### sub-config, s, ss
another usage test
**--sub-command-flag, -s**: some usage text
**--sub-flag, --sub-fl, -s**="":
## info, i, in
retrieve generic information
## some-command

@ -0,0 +1,36 @@
% greet(8)
% Harrison
# NAME
greet - Some app
# SYNOPSIS
greet
```
[--another-flag|-b]
[--flag|--fl|-f]=[value]
[--socket|-s]=[value]
```
# DESCRIPTION
app [first_arg] [second_arg]
**Usage**:
```
greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
```
# GLOBAL OPTIONS
**--another-flag, -b**: another usage text
**--flag, --fl, -f**="":
**--socket, -s**="": some usage text (default: value)

@ -0,0 +1,47 @@
% greet(8)
% Harrison
# NAME
greet - Some app
# SYNOPSIS
greet
# DESCRIPTION
app [first_arg] [second_arg]
**Usage**:
```
greet [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
```
# COMMANDS
## config, c
another usage test
**--another-flag, -b**: another usage text
**--flag, --fl, -f**="":
### sub-config, s, ss
another usage test
**--sub-command-flag, -s**: some usage text
**--sub-flag, --sub-fl, -s**="":
## info, i, in
retrieve generic information
## some-command
Loading…
Cancel
Save