-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
117 lines (105 loc) · 2.65 KB
/
main.go
File metadata and controls
117 lines (105 loc) · 2.65 KB
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"context"
"fmt"
"strings"
"github.com/scott-cotton/cli"
)
func main() {
cli.MainContext(context.Background(), MainCommand())
}
type MainConfig struct {
Debug bool `cli:"name=debug desc='turn on debugging'"`
}
func MainCommand() *cli.Command {
cfg := &MainConfig{}
opts, err := cli.StructOpts(cfg)
if err != nil {
// yes it should panic for development
// but nothing would reasonably be shipped with
// this possibility
panic(err)
}
return cli.NewCommand("example").
WithSynopsis("example run me and see").
WithDescription("example is a demo use of github.com/scott-cotton/cli").
WithOpts(opts...).
WithSubs(
ACommand(),
BCommand(),
)
}
// The a command
type AConfig struct {
*cli.Command
Name string `cli:"name=n aliases=name,na desc=name default=sam"`
Level int `cli:"name=level aliases=l desc='A\\'s level'"`
}
func ACommand() *cli.Command {
cfg := &AConfig{}
opts, err := cli.StructOpts(cfg)
if err != nil {
// yes it should panic for development
// but nothing would reasonably be shipped with
// this possibility
panic(err)
}
return cli.NewCommandAt(&cfg.Command, "a").
WithSynopsis("a the a command exits code equal to the number of args").
WithOpts(opts...).
WithRun(cfg.run)
}
func (cfg *AConfig) run(cc *cli.Context, args []string) error {
args, err := cfg.Parse(cc, args)
if err != nil {
return err
}
fmt.Fprintf(cc.Out, "should exit %d\n", len(args))
return cli.ExitCodeErr(len(args))
}
// The b command
type BConfig struct {
*cli.Command
env map[string]any
// cli.FuncOpt must be bound to field with type any
E any `cli:"name=e type=env desc='-e key=val sets key to val'"`
}
func (bCfg *BConfig) parseEnv(cc *cli.Context, a string) (any, error) {
key, val, ok := strings.Cut(a, "=")
if !ok {
return nil, fmt.Errorf("%w: -e expected key=value", cli.ErrUsage)
}
bCfg.env[key] = val
return nil, nil
}
func BCommand() *cli.Command {
cfg := &BConfig{
env: map[string]any{},
}
opts, err := cli.StructOptsWithTypes(cfg, map[string]cli.OptType{
"env": cli.FuncOpt(cfg.parseEnv),
})
if err != nil {
panic(err)
}
return cli.NewCommandAt(&cfg.Command, "b").
WithAliases("bb", "bbb").
WithSynopsis("b cool and use cli").
WithDescription("b is a subcommand").
WithOpts(opts...).
WithRun(cfg.run)
}
func (b *BConfig) run(cc *cli.Context, args []string) error {
args, err := b.Parse(cc, args)
if err != nil {
return err
}
if len(b.env) == 0 && len(args) == 0 {
return fmt.Errorf("%w: please supply some -e flags or args", cli.ErrUsage)
}
fmt.Fprintf(cc.Out, "args: %v\nenv:\n", args)
for k, v := range b.env {
fmt.Fprintf(cc.Out, "\t%s: %v\n", k, v)
}
return nil
}