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	Usage     string
18	EnvVar    string
19	FilePath  string
20	Required  bool
21	Hidden    bool
22	TakesFile bool
23	Value     Generic
24}
25
26// String returns a readable representation of this value
27// (for usage defaults)
28func (f GenericFlag) String() string {
29	return FlagStringer(f)
30}
31
32// GetName returns the name of the flag
33func (f GenericFlag) GetName() string {
34	return f.Name
35}
36
37// IsRequired returns whether or not the flag is required
38func (f GenericFlag) IsRequired() bool {
39	return f.Required
40}
41
42// TakesValue returns true of the flag takes a value, otherwise false
43func (f GenericFlag) TakesValue() bool {
44	return true
45}
46
47// GetUsage returns the usage string for the flag
48func (f GenericFlag) GetUsage() string {
49	return f.Usage
50}
51
52// GetValue returns the flags value as string representation and an empty
53// string if the flag takes no value at all.
54func (f GenericFlag) GetValue() string {
55	if f.Value != nil {
56		return f.Value.String()
57	}
58	return ""
59}
60
61// Apply takes the flagset and calls Set on the generic flag with the value
62// provided by the user for parsing by the flag
63// Ignores parsing errors
64func (f GenericFlag) Apply(set *flag.FlagSet) {
65	_ = f.ApplyWithError(set)
66}
67
68// ApplyWithError takes the flagset and calls Set on the generic flag with the value
69// provided by the user for parsing by the flag
70func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
71	val := f.Value
72	if fileEnvVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
73		if err := val.Set(fileEnvVal); err != nil {
74			return fmt.Errorf("could not parse %s as value for flag %s: %s", fileEnvVal, f.Name, err)
75		}
76	}
77
78	eachName(f.Name, func(name string) {
79		set.Var(f.Value, name, f.Usage)
80	})
81
82	return nil
83}
84
85// Generic looks up the value of a local GenericFlag, returns
86// nil if not found
87func (c *Context) Generic(name string) interface{} {
88	return lookupGeneric(name, c.flagSet)
89}
90
91// GlobalGeneric looks up the value of a global GenericFlag, returns
92// nil if not found
93func (c *Context) GlobalGeneric(name string) interface{} {
94	if fs := lookupGlobalFlagSet(name, c); fs != nil {
95		return lookupGeneric(name, fs)
96	}
97	return nil
98}
99
100func lookupGeneric(name string, set *flag.FlagSet) interface{} {
101	f := set.Lookup(name)
102	if f != nil {
103		parsed, err := f.Value, error(nil)
104		if err != nil {
105			return nil
106		}
107		return parsed
108	}
109	return nil
110}
111