1
1
package main
2
2
3
3
import (
4
+ "errors"
4
5
"flag"
5
6
"fmt"
7
+ "io"
6
8
"os"
7
9
"runtime"
10
+ "strings"
8
11
"time"
9
12
10
13
"github.com/mutablelogic/go-client"
@@ -18,6 +21,9 @@ type Flags struct {
18
21
* flag.FlagSet
19
22
20
23
cmds []Cmd
24
+ cmd * Cmd
25
+ root string
26
+ args []string
21
27
names map [string ]* Value
22
28
}
23
29
@@ -32,7 +38,8 @@ type flagType uint
32
38
// GLOBALS
33
39
34
40
var (
35
- ErrHelp = flag .ErrHelp
41
+ ErrHelp = flag .ErrHelp
42
+ ErrInstall = errors .New ("install" )
36
43
)
37
44
38
45
const (
@@ -67,19 +74,48 @@ func (flags *Flags) Register(c Cmd) {
67
74
flags .cmds = append (flags .cmds , c )
68
75
}
69
76
70
- func (flags * Flags ) Parse (args []string ) error {
77
+ func (flags * Flags ) Parse (args []string ) ( * Fn , [] string , error ) {
71
78
// Parse command line
72
- if err := flags .FlagSet .Parse (args ); err != nil {
73
- if err == flag .ErrHelp {
79
+ err := flags .FlagSet .Parse (args )
80
+
81
+ // If there is a version argument, print the version and exit
82
+ if flags .NArg () == 1 {
83
+ switch flags .Arg (0 ) {
84
+ case "version" :
85
+ flags .PrintVersion ()
86
+ return nil , nil , ErrHelp
87
+ case "help" :
74
88
flags .PrintUsage ()
89
+ return nil , nil , ErrHelp
90
+ case ErrInstall .Error ():
91
+ return nil , nil , ErrInstall
75
92
}
76
- return err
77
93
}
78
94
79
- // If there is a version argument, print the version and exit
80
- if flags .NArg () == 1 && flags .Arg (0 ) == "version" {
81
- flags .PrintVersion ()
82
- return ErrHelp
95
+ // If the name of the command is the same as the name of the application
96
+ if cmd := flags .getCommandSet (flags .Name ()); cmd != nil {
97
+ flags .cmd = cmd
98
+ flags .root = cmd .Name
99
+ flags .args = flags .Args ()
100
+ } else if flags .NArg () > 0 {
101
+ if cmd := flags .getCommandSet (flags .Arg (0 )); cmd != nil {
102
+ flags .cmd = cmd
103
+ flags .root = strings .Join ([]string {flags .Name (), cmd .Name }, " " )
104
+ flags .args = flags .Args ()[1 :]
105
+ }
106
+ }
107
+
108
+ // Print usage
109
+ if err != nil {
110
+ if err != flag .ErrHelp {
111
+ fmt .Fprintf (os .Stderr , "%v: %v\n " , flags .cmd .Name , err )
112
+ } else {
113
+ flags .PrintUsage ()
114
+ }
115
+ return nil , nil , err
116
+ } else if flags .cmd == nil {
117
+ fmt .Fprintln (os .Stderr , "Unknown command, try -help" )
118
+ return nil , nil , ErrHelp
83
119
}
84
120
85
121
// Set client options
@@ -89,29 +125,27 @@ func (flags *Flags) Parse(args []string) error {
89
125
opts = append (opts , client .OptTrace (flags .Output (), flags .GetBool ("verbose" )))
90
126
}
91
127
92
- // Parse the commands
93
- if flags .NArg () > 0 {
94
- if cmd := flags .GetCommandSet (flags .Arg (0 )); cmd != nil {
95
- if err := cmd .Parse (flags , opts ... ); err != nil {
96
- fmt .Fprintf (os .Stderr , "%v: %v\n " , cmd .Name , err )
97
- return err
98
- }
99
- }
128
+ // If there is a help argument, print the help and exit
129
+ if flags .NArg () == 1 && flags .Arg (0 ) == "help" || flags .cmd == nil {
130
+ flags .PrintUsage ()
131
+ return nil , nil , ErrHelp
132
+ } else if err := flags .cmd .Parse (flags , opts ... ); err != nil {
133
+ fmt .Fprintf (os .Stderr , "%v: %v\n " , flags .cmd .Name , err )
134
+ return nil , nil , err
100
135
}
101
136
102
- // Return success
103
- return nil
104
- }
105
-
106
- // GetCommandSet returns a command set from a name, or nil if the command set does
107
- // not exist
108
- func (flags * Flags ) GetCommandSet (name string ) * Cmd {
109
- for _ , cmd := range flags .cmds {
110
- if cmd .Name == name {
111
- return & cmd
112
- }
137
+ // Set the function to call
138
+ fn , args , err := flags .cmd .Get (flags .args )
139
+ if err != nil {
140
+ fmt .Fprintf (os .Stderr , "%v: %v\n " , flags .cmd .Name , err )
141
+ return nil , nil , err
142
+ } else if fn == nil {
143
+ fmt .Fprintln (os .Stderr , "Unknown command, try -help" )
144
+ return nil , nil , ErrHelp
113
145
}
114
- return nil
146
+
147
+ // Return success
148
+ return fn , args , nil
115
149
}
116
150
117
151
// Get returns the value of a flag, and returns true if the flag exists
@@ -123,6 +157,11 @@ func (flags *Flags) Get(name string) (string, bool) {
123
157
}
124
158
}
125
159
160
+ // Get the current command set
161
+ func (flags * Flags ) Cmd () * Cmd {
162
+ return flags .cmd
163
+ }
164
+
126
165
///////////////////////////////////////////////////////////////////////////////
127
166
// PUBLIC METHODS
128
167
@@ -156,33 +195,33 @@ func (flags *Flags) PrintVersion() {
156
195
// PrintUsage prints the usage of the application
157
196
func (flags * Flags ) PrintUsage () {
158
197
w := flags .Output ()
159
- if flags .NArg () == 1 {
160
- cmd := flags .GetCommandSet (flags .Arg (0 ))
161
- if cmd != nil {
162
- flags .PrintCommandUsage (cmd )
163
- }
198
+ if flags .cmd != nil {
199
+ flags .PrintCommandUsage (flags .cmd )
164
200
} else {
165
- fmt .Fprintln (w , "Name:" , flags .Name () )
201
+ fmt .Fprintln (w , "Name:" , flags .root )
166
202
fmt .Fprintln (w , " General command-line interface to API clients" )
167
203
fmt .Fprintln (w , "" )
168
204
169
205
// Command Sets
170
206
fmt .Fprintln (w , "Command Sets:" )
171
207
for _ , cmd := range flags .cmds {
172
- fmt .Fprintln (w , " " , flags .Name () , cmd .Name )
208
+ fmt .Fprintln (w , " " , flags .root , cmd .Name )
173
209
fmt .Fprintln (w , " " , cmd .Description )
174
210
fmt .Fprintln (w , "" )
175
211
}
176
212
177
213
// Help
178
214
fmt .Fprintln (w , "Help:" )
179
- fmt .Fprintln (w , " " , flags .Name () , "version" )
215
+ fmt .Fprintln (w , " " , flags .root , "version" )
180
216
fmt .Fprintln (w , " " , "Return the version of the application" )
181
217
fmt .Fprintln (w , "" )
218
+ fmt .Fprintln (w , " " , flags .root , "install" )
219
+ fmt .Fprintln (w , " " , "Install symlinks for command calling" )
220
+ fmt .Fprintln (w , "" )
182
221
183
222
// Help for command sets
184
223
for _ , cmd := range flags .cmds {
185
- fmt .Fprintln (w , " " , flags .Name () , "-help" , cmd .Name )
224
+ fmt .Fprintln (w , " " , flags .root , "-help" , cmd .Name )
186
225
fmt .Fprintln (w , " " , "Display" , cmd .Name , "command syntax" )
187
226
fmt .Fprintln (w , "" )
188
227
}
@@ -200,14 +239,14 @@ func (flags *Flags) PrintGlobalFlags() {
200
239
// PrintCommandUsage prints the usage of a commandset
201
240
func (flags * Flags ) PrintCommandUsage (cmd * Cmd ) {
202
241
w := flags .Output ()
203
- fmt .Fprintln (w , "Name:" , flags .Name (), cmd . Name )
242
+ fmt .Fprintln (w , "Name:" , flags .root )
204
243
fmt .Fprintln (w , " " , cmd .Description )
205
244
fmt .Fprintln (w , "" )
206
245
207
246
// Help for command sets
208
247
fmt .Fprintln (w , "Commands:" )
209
248
for _ , fn := range cmd .Fn {
210
- fmt .Fprintln (w , " " , flags .Name (), cmd . Name , fn .Name )
249
+ fmt .Fprintln (w , " " , flags .root , fn .Name )
211
250
fmt .Fprintln (w , " " , fn .Description )
212
251
fmt .Fprintln (w , "" )
213
252
}
@@ -224,13 +263,21 @@ func (flags *Flags) PrintCommandFlags(cmd string) {
224
263
} else {
225
264
fmt .Fprintf (w , "Flags for %v:\n " , cmd )
226
265
}
227
- flags .VisitAll (func (f * flag.Flag ) {
228
- if flags .names [f .Name ].cmd == cmd {
229
- fmt . Fprintf (w , " -%v: %v \n " , f . Name , f . Usage )
266
+ flags .VisitAll (func (flag * flag.Flag ) {
267
+ if flags .names [flag .Name ].cmd == cmd {
268
+ printFlag (w , flag )
230
269
}
231
270
})
232
271
}
233
272
273
+ func printFlag (w io.Writer , f * flag.Flag ) {
274
+ fmt .Fprintf (w , " -%v" , f .Name )
275
+ if len (f .DefValue ) > 0 {
276
+ fmt .Fprintf (w , " (default %q)" , f .DefValue )
277
+ }
278
+ fmt .Fprintf (w , "\n %v\n \n " , f .Usage )
279
+ }
280
+
234
281
///////////////////////////////////////////////////////////////////////////////
235
282
// PUBLIC METHODS - SET FLAGS
236
283
@@ -315,3 +362,15 @@ func (flags *Flags) GetString(name string) string {
315
362
return os .ExpandEnv (value )
316
363
}
317
364
}
365
+
366
+ ///////////////////////////////////////////////////////////////////////////////
367
+ // PRIVATE METHODS
368
+
369
+ func (flags * Flags ) getCommandSet (name string ) * Cmd {
370
+ for _ , cmd := range flags .cmds {
371
+ if cmd .Name == name {
372
+ return & cmd
373
+ }
374
+ }
375
+ return nil
376
+ }
0 commit comments