aboutsummaryrefslogtreecommitdiffhomepage
path: root/command/flag.go
blob: d7eb6cb236320ab13aa682bedc6c5b959eac7786 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package command

import (
	"errors"
	"flag"
	"strings"
)

// FlagError wraps errors returned by [flag].
type FlagError struct{ error }

func (e FlagError) Success() bool { return errors.Is(e.error, flag.ErrHelp) }
func (e FlagError) Is(target error) bool {
	return (e.error == nil && target == nil) ||
		((e.error != nil && target != nil) && e.error.Error() == target.Error())
}

func (n *node) Flag(p any, name string, value FlagDefiner, usage string) Node {
	var buf strings.Builder
	value.Define(&buf, n.set, p, name, usage)
	s := buf.String()
	if len(s) > 0 && s[0] == ' ' {
		s = s[1:]
	}
	n.suffix = append(n.suffix, s)
	return n
}

// StringFlag is the default value of a string flag.
type StringFlag string

func (v StringFlag) Define(b *strings.Builder, set *flag.FlagSet, p any, name, usage string) {
	set.StringVar(p.(*string), name, string(v), usage)
	b.WriteString(" [" + prettyFlag(name) + " <value>]")
}

// IntFlag is the default value of an int flag.
type IntFlag int

func (v IntFlag) Define(b *strings.Builder, set *flag.FlagSet, p any, name, usage string) {
	set.IntVar(p.(*int), name, int(v), usage)
	b.WriteString(" [" + prettyFlag(name) + " <int>]")
}

// BoolFlag is the default value of a bool flag.
type BoolFlag bool

func (v BoolFlag) Define(b *strings.Builder, set *flag.FlagSet, p any, name, usage string) {
	set.BoolVar(p.(*bool), name, bool(v), usage)
	b.WriteString(" [" + prettyFlag(name) + "]")
}

// RepeatableFlag implements an ordered, repeatable string flag.
type RepeatableFlag []string

func (r *RepeatableFlag) String() string {
	if r == nil {
		return "<nil>"
	}
	return strings.Join(*r, " ")
}

func (r *RepeatableFlag) Set(v string) error {
	*r = append(*r, v)
	return nil
}

func (r *RepeatableFlag) Define(b *strings.Builder, set *flag.FlagSet, _ any, name, usage string) {
	set.Var(r, name, usage)
	b.WriteString(" [" + prettyFlag(name) + " <value>]")
}

// this has no effect on parse outcome
func prettyFlag(name string) string {
	switch len(name) {
	case 0:
		panic("zero length flag name")
	case 1:
		return "-" + name
	default:
		return "--" + name
	}
}