1package cli
2
3import (
4	"flag"
5	"fmt"
6)
7
8// Generic is a generic parseable type identified by a specific flag
9type Generic interface {
10	Set(value string) error
11	String() string
12}
13
14// GenericFlag is a flag with type Generic
15type GenericFlag struct {
16	Name        string
17	Aliases     []string
18	Usage       string
19	EnvVars     []string
20	FilePath    string
21	Required    bool
22	Hidden      bool
23	TakesFile   bool
24	Value       Generic
25	DefaultText string
26	HasBeenSet  bool
27}
28
29// IsSet returns whether or not the flag has been set through env or file
30func (f *GenericFlag) IsSet() bool {
31	return f.HasBeenSet
32}
33
34// String returns a readable representation of this value
35// (for usage defaults)
36func (f *GenericFlag) String() string {
37	return FlagStringer(f)
38}
39
40// Names returns the names of the flag
41func (f *GenericFlag) Names() []string {
42	return flagNames(f.Name, f.Aliases)
43}
44
45// IsRequired returns whether or not the flag is required
46func (f *GenericFlag) IsRequired() bool {
47	return f.Required
48}
49
50// TakesValue returns true of the flag takes a value, otherwise false
51func (f *GenericFlag) TakesValue() bool {
52	return true
53}
54
55// GetUsage returns the usage string for the flag
56func (f *GenericFlag) GetUsage() string {
57	return f.Usage
58}
59
60// GetValue returns the flags value as string representation and an empty
61// string if the flag takes no value at all.
62func (f *GenericFlag) GetValue() string {
63	if f.Value != nil {
64		return f.Value.String()
65	}
66	return ""
67}
68
69// Apply takes the flagset and calls Set on the generic flag with the value
70// provided by the user for parsing by the flag
71func (f GenericFlag) Apply(set *flag.FlagSet) error {
72	if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
73		if val != "" {
74			if err := f.Value.Set(val); err != nil {
75				return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err)
76			}
77
78			f.HasBeenSet = true
79		}
80	}
81
82	for _, name := range f.Names() {
83		set.Var(f.Value, name, f.Usage)
84	}
85
86	return nil
87}
88
89// Generic looks up the value of a local GenericFlag, returns
90// nil if not found
91func (c *Context) Generic(name string) interface{} {
92	if fs := lookupFlagSet(name, c); fs != nil {
93		return lookupGeneric(name, fs)
94	}
95	return nil
96}
97
98func lookupGeneric(name string, set *flag.FlagSet) interface{} {
99	f := set.Lookup(name)
100	if f != nil {
101		parsed, err := f.Value, error(nil)
102		if err != nil {
103			return nil
104		}
105		return parsed
106	}
107	return nil
108}
109