Split examples and fix tree
Signed-off-by: jolheiser <john.olheiser@gmail.com>main v0.0.1
parent
34293148d7
commit
2b03d73292
|
@ -0,0 +1,8 @@
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Each directory contains a sample flagset/command setup and the resulting
|
||||||
|
generated docs.
|
||||||
|
|
||||||
|
- [flagset](flagset) - Using only stdlib `flag.FlagSet`
|
||||||
|
- [single](single) - Using a single `ffcli.Command`
|
||||||
|
- [multiple](multiple) - Using `ffcli.Command` with multiple sub-commands
|
|
@ -1,55 +0,0 @@
|
||||||
# myapp
|
|
||||||
|
|
||||||
myapp
|
|
||||||
|
|
||||||
```
|
|
||||||
myapp
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
[--help]
|
|
||||||
[--myapp-bool-flag-f]
|
|
||||||
[--myapp-bool-flag-t]
|
|
||||||
[--myapp-duration-flag]=[value]
|
|
||||||
[--myapp-duration-flag-default]=[value]
|
|
||||||
[--myapp-int-flag]=[value]
|
|
||||||
[--myapp-int-flag-default]=[value]
|
|
||||||
[--myapp-string-flag]=[value]
|
|
||||||
[--myapp-string-flag-default]=[value]
|
|
||||||
```
|
|
||||||
**Usage**:
|
|
||||||
|
|
||||||
```
|
|
||||||
myapp [FLAGS] [ARGS...]
|
|
||||||
```
|
|
||||||
|
|
||||||
**--help**: Show help
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-bool-flag-f**: Bool flag false
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-bool-flag-t**: Bool flag true (default: `true`)
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-duration-flag**="": Duration flag with no default
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-duration-flag-default**="": Duration flag with default (default: `5m0s`)
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-int-flag**="": Int flag with no default
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-int-flag-default**="": Int flag with default (default: `100`)
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-string-flag**="": String flag with no default
|
|
||||||
|
|
||||||
|
|
||||||
**--myapp-string-flag-default**="": String flag with default (default: `string default`)
|
|
||||||
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
//go:build generate
|
||||||
|
// +build generate
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.jolheiser.com/ffmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run main.go
|
||||||
|
func main() {
|
||||||
|
fs := flag.NewFlagSet("myapp", flag.ExitOnError)
|
||||||
|
fs.String("string-flag", "", "String flag with no default")
|
||||||
|
fs.String("string-flag-default", "string default", "String flag with default")
|
||||||
|
fs.Int("int-flag", 0, "Int flag with no default")
|
||||||
|
fs.Int("int-flag-default", 100, "Int flag with default")
|
||||||
|
fs.Bool("bool-flag-f", false, "Bool flag false")
|
||||||
|
fs.Bool("bool-flag-t", true, "Bool flag true")
|
||||||
|
fs.Duration("duration-flag", 0, "Duration flag with no default")
|
||||||
|
fs.Duration("duration-flag-default", time.Minute*5, "Duration flag with default")
|
||||||
|
|
||||||
|
md, err := ffmd.FromFlagSet(fs)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
write("flagset.md", md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(path, content string) {
|
||||||
|
fi, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
if _, err := fi.WriteString(content); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,59 +14,8 @@ import (
|
||||||
"go.jolheiser.com/ffmd"
|
"go.jolheiser.com/ffmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run examples.go
|
//go:generate go run main.go
|
||||||
func main() {
|
func main() {
|
||||||
fs := flagSet("")
|
|
||||||
md, err := ffmd.FromFlagSet(fs)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
write("flagset.md", md)
|
|
||||||
|
|
||||||
command()
|
|
||||||
commandSub()
|
|
||||||
}
|
|
||||||
|
|
||||||
func write(path, content string) {
|
|
||||||
fi, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer fi.Close()
|
|
||||||
if _, err := fi.WriteString(content); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func flagSet(name string) *flag.FlagSet {
|
|
||||||
fs := flag.NewFlagSet("myapp", flag.ExitOnError)
|
|
||||||
fs.String(fmt.Sprintf("%sstring-flag", name), "", "String flag with no default")
|
|
||||||
fs.String(fmt.Sprintf("%sstring-flag-default", name), "string default", "String flag with default")
|
|
||||||
fs.Int(fmt.Sprintf("%sint-flag", name), 0, "Int flag with no default")
|
|
||||||
fs.Int(fmt.Sprintf("%sint-flag-default", name), 100, "Int flag with default")
|
|
||||||
fs.Bool(fmt.Sprintf("%sbool-flag-f", name), false, "Bool flag false")
|
|
||||||
fs.Bool(fmt.Sprintf("%sbool-flag-t", name), true, "Bool flag true")
|
|
||||||
fs.Duration(fmt.Sprintf("%sduration-flag", name), 0, "Duration flag with no default")
|
|
||||||
fs.Duration(fmt.Sprintf("%sduration-flag-default", name), time.Minute*5, "Duration flag with default")
|
|
||||||
return fs
|
|
||||||
}
|
|
||||||
|
|
||||||
func command() {
|
|
||||||
fs1 := flagSet("myapp-")
|
|
||||||
cmd1 := &ffcli.Command{
|
|
||||||
Name: "myapp",
|
|
||||||
FlagSet: fs1,
|
|
||||||
Subcommands: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
md, err := ffmd.FromCommand(cmd1)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
write("command.md", md)
|
|
||||||
}
|
|
||||||
|
|
||||||
func commandSub() {
|
|
||||||
fs := flagSet("myapp-")
|
fs := flagSet("myapp-")
|
||||||
cmd := &ffcli.Command{
|
cmd := &ffcli.Command{
|
||||||
Name: "myapp",
|
Name: "myapp",
|
||||||
|
@ -95,18 +44,18 @@ func commandSub() {
|
||||||
}
|
}
|
||||||
fs4 := flagSet("sub4-")
|
fs4 := flagSet("sub4-")
|
||||||
cmd4 := &ffcli.Command{
|
cmd4 := &ffcli.Command{
|
||||||
Name: "sub4",
|
Name: "sub4",
|
||||||
FlagSet: fs4,
|
FlagSet: fs4,
|
||||||
}
|
}
|
||||||
fs5 := flagSet("sub5-")
|
fs5 := flagSet("sub5-")
|
||||||
cmd5 := &ffcli.Command{
|
cmd5 := &ffcli.Command{
|
||||||
Name: "sub5",
|
Name: "sub5",
|
||||||
FlagSet: fs5,
|
FlagSet: fs5,
|
||||||
}
|
}
|
||||||
fs6 := flagSet("sub6-")
|
fs6 := flagSet("sub6-")
|
||||||
cmd6 := &ffcli.Command{
|
cmd6 := &ffcli.Command{
|
||||||
Name: "sub6",
|
Name: "sub6",
|
||||||
FlagSet: fs6,
|
FlagSet: fs6,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Subcommands = []*ffcli.Command{cmd1, cmd2, cmd6}
|
cmd.Subcommands = []*ffcli.Command{cmd1, cmd2, cmd6}
|
||||||
|
@ -119,3 +68,27 @@ func commandSub() {
|
||||||
}
|
}
|
||||||
write("command-sub.md", md)
|
write("command-sub.md", md)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func write(path, content string) {
|
||||||
|
fi, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
if _, err := fi.WriteString(content); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagSet(name string) *flag.FlagSet {
|
||||||
|
fs := flag.NewFlagSet("myapp", flag.ExitOnError)
|
||||||
|
fs.String(fmt.Sprintf("%sstring-flag", name), "", "String flag with no default")
|
||||||
|
fs.String(fmt.Sprintf("%sstring-flag-default", name), "string default", "String flag with default")
|
||||||
|
fs.Int(fmt.Sprintf("%sint-flag", name), 0, "Int flag with no default")
|
||||||
|
fs.Int(fmt.Sprintf("%sint-flag-default", name), 100, "Int flag with default")
|
||||||
|
fs.Bool(fmt.Sprintf("%sbool-flag-f", name), false, "Bool flag false")
|
||||||
|
fs.Bool(fmt.Sprintf("%sbool-flag-t", name), true, "Bool flag true")
|
||||||
|
fs.Duration(fmt.Sprintf("%sduration-flag", name), 0, "Duration flag with no default")
|
||||||
|
fs.Duration(fmt.Sprintf("%sduration-flag-default", name), time.Minute*5, "Duration flag with default")
|
||||||
|
return fs
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
//go:build generate
|
||||||
|
// +build generate
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/peterbourgon/ff/v3/ffcli"
|
||||||
|
|
||||||
|
"go.jolheiser.com/ffmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run main.go
|
||||||
|
func main() {
|
||||||
|
fs := flag.NewFlagSet("myapp", flag.ExitOnError)
|
||||||
|
fs.String("string-flag", "", "String flag with no default")
|
||||||
|
fs.String("string-flag-default", "string default", "String flag with default")
|
||||||
|
fs.Int("int-flag", 0, "Int flag with no default")
|
||||||
|
fs.Int("int-flag-default", 100, "Int flag with default")
|
||||||
|
fs.Bool("bool-flag-f", false, "Bool flag false")
|
||||||
|
fs.Bool("bool-flag-t", true, "Bool flag true")
|
||||||
|
fs.Duration("duration-flag", 0, "Duration flag with no default")
|
||||||
|
fs.Duration("duration-flag-default", time.Minute*5, "Duration flag with default")
|
||||||
|
|
||||||
|
cmd := &ffcli.Command{
|
||||||
|
Name: "myapp",
|
||||||
|
FlagSet: fs,
|
||||||
|
Subcommands: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
md, err := ffmd.FromCommand(cmd)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
write("single.md", md)
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(path, content string) {
|
||||||
|
fi, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer fi.Close()
|
||||||
|
if _, err := fi.WriteString(content); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
# myapp
|
||||||
|
|
||||||
|
myapp
|
||||||
|
|
||||||
|
```
|
||||||
|
myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
[--bool-flag-f]
|
||||||
|
[--bool-flag-t]
|
||||||
|
[--duration-flag]=[value]
|
||||||
|
[--duration-flag-default]=[value]
|
||||||
|
[--help]
|
||||||
|
[--int-flag]=[value]
|
||||||
|
[--int-flag-default]=[value]
|
||||||
|
[--string-flag]=[value]
|
||||||
|
[--string-flag-default]=[value]
|
||||||
|
```
|
||||||
|
**Usage**:
|
||||||
|
|
||||||
|
```
|
||||||
|
myapp [FLAGS] [ARGS...]
|
||||||
|
```
|
||||||
|
|
||||||
|
**--bool-flag-f**: Bool flag false
|
||||||
|
|
||||||
|
|
||||||
|
**--bool-flag-t**: Bool flag true (default: `true`)
|
||||||
|
|
||||||
|
|
||||||
|
**--duration-flag**="": Duration flag with no default
|
||||||
|
|
||||||
|
|
||||||
|
**--duration-flag-default**="": Duration flag with default (default: `5m0s`)
|
||||||
|
|
||||||
|
|
||||||
|
**--help**: Show help
|
||||||
|
|
||||||
|
|
||||||
|
**--int-flag**="": Int flag with no default
|
||||||
|
|
||||||
|
|
||||||
|
**--int-flag-default**="": Int flag with default (default: `100`)
|
||||||
|
|
||||||
|
|
||||||
|
**--string-flag**="": String flag with no default
|
||||||
|
|
||||||
|
|
||||||
|
**--string-flag-default**="": String flag with default (default: `string default`)
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package ffmd
|
|
48
tree.go
48
tree.go
|
@ -2,49 +2,27 @@ package ffmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/peterbourgon/ff/v3/ffcli"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/peterbourgon/ff/v3/ffcli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tree returns a tree-representation of a ffcli.Command
|
// Tree returns a tree-representation of a ffcli.Command
|
||||||
func Tree(cmd *ffcli.Command) string {
|
func Tree(cmd *ffcli.Command) string {
|
||||||
t := tree{}
|
t := tree{cmd.Name: commandTree(cmd)}
|
||||||
for _, path := range commandPaths(cmd, "") {
|
|
||||||
t.add(path)
|
|
||||||
}
|
|
||||||
s := t.String(true, "")
|
s := t.String(true, "")
|
||||||
return strings.TrimSpace(s)
|
return strings.TrimSpace(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commandPaths(cmd *ffcli.Command, path string) []string {
|
|
||||||
root := fmt.Sprintf("%s%s", path, cmd.Name)
|
|
||||||
s := []string{root}
|
|
||||||
for _, sub := range cmd.Subcommands {
|
|
||||||
s = append(s, commandPaths(sub, root+"/")...)
|
|
||||||
}
|
|
||||||
sort.SliceStable(s, func(i, j int) bool {
|
|
||||||
return s[i] < s[j]
|
|
||||||
})
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
type tree map[string]tree
|
type tree map[string]tree
|
||||||
|
|
||||||
func (t tree) add(path string) {
|
func commandTree(cmd *ffcli.Command) tree {
|
||||||
t.addParts(strings.Split(path, "/"))
|
t := tree{}
|
||||||
}
|
for _, sub := range cmd.Subcommands {
|
||||||
|
t[sub.Name] = commandTree(sub)
|
||||||
func (t tree) addParts(parts []string) {
|
|
||||||
if len(parts) == 0 {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
next, ok := t[parts[0]]
|
return t
|
||||||
if !ok {
|
|
||||||
next = tree{}
|
|
||||||
t[parts[0]] = next
|
|
||||||
}
|
|
||||||
next.addParts(parts[1:])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t tree) keys() []string {
|
func (t tree) keys() []string {
|
||||||
|
@ -61,8 +39,10 @@ func (t tree) String(root bool, padding string) string {
|
||||||
index := 0
|
index := 0
|
||||||
for _, k := range t.keys() {
|
for _, k := range t.keys() {
|
||||||
v := t[k]
|
v := t[k]
|
||||||
s.WriteString(fmt.Sprintf("%s%s\n", padding+pipePad(root, pipe(index, len(t))), k))
|
p := pipe(index, len(t))
|
||||||
s.WriteString(v.String(false, padding+pipePad(root, outerPipe(index, len(t)))))
|
s.WriteString(fmt.Sprintf("%s%s\n", padding+pipePad(root, p), k))
|
||||||
|
op := outerPipe(index, len(t))
|
||||||
|
s.WriteString(v.String(false, padding+pipePad(root, op)))
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
return s.String()
|
return s.String()
|
||||||
|
@ -70,10 +50,10 @@ func (t tree) String(root bool, padding string) string {
|
||||||
|
|
||||||
func pipe(index int, len int) string {
|
func pipe(index int, len int) string {
|
||||||
switch {
|
switch {
|
||||||
case index+1 == len:
|
|
||||||
return "└─"
|
|
||||||
case index+1 > len:
|
case index+1 > len:
|
||||||
return " "
|
return " "
|
||||||
|
case index+1 == len:
|
||||||
|
return "└─"
|
||||||
default:
|
default:
|
||||||
return "├─"
|
return "├─"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue