2
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
8
http://www.apache.org/licenses/LICENSE-2.0
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
29
type HasFlags interface {
30
// Register may be called more than once and should be idempotent.
31
Register(f *flag.FlagSet)
33
// Process may be called more than once and should be idempotent.
37
type Command interface {
40
Run(f *flag.FlagSet) error
43
var hasFlagsType = reflect.TypeOf((*HasFlags)(nil)).Elem()
45
func RegisterCommand(h HasFlags, f *flag.FlagSet) {
46
visited := make(map[interface{}]struct{})
47
Walk(h, hasFlagsType, func(v interface{}) error {
48
if _, ok := visited[v]; ok {
51
visited[v] = struct{}{}
52
v.(HasFlags).Register(f)
57
func ProcessCommand(h HasFlags) error {
58
visited := make(map[interface{}]struct{})
59
err := Walk(h, hasFlagsType, func(v interface{}) error {
60
if _, ok := visited[v]; ok {
63
visited[v] = struct{}{}
64
err := v.(HasFlags).Process()
71
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
74
for name := range commands {
75
cmds = append(cmds, name)
80
for _, name := range cmds {
81
fmt.Fprintf(os.Stderr, " %s\n", name)
85
func commandHelp(name string, cmd Command, f *flag.FlagSet) {
86
type HasUsage interface {
90
fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS]", os.Args[0], name)
91
if u, ok := cmd.(HasUsage); ok {
92
fmt.Fprintf(os.Stderr, " %s", u.Usage())
94
fmt.Fprintf(os.Stderr, "\n")
96
type HasDescription interface {
100
if u, ok := cmd.(HasDescription); ok {
101
fmt.Fprintf(os.Stderr, "%s\n", u.Description())
105
f.VisitAll(func(_ *flag.Flag) {
110
fmt.Fprintf(os.Stderr, "\nOptions:\n")
111
tw := tabwriter.NewWriter(os.Stderr, 2, 0, 2, ' ', 0)
112
f.VisitAll(func(f *flag.Flag) {
113
fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage)
119
func Run(args []string) int {
125
// Look up real command name in aliases table.
126
name, ok := aliases[args[0]]
131
cmd, ok := commands[name]
137
f := flag.NewFlagSet("", flag.ContinueOnError)
138
f.SetOutput(ioutil.Discard)
140
RegisterCommand(cmd, f)
142
if err := f.Parse(args[1:]); err != nil {
143
if err == flag.ErrHelp {
144
commandHelp(args[0], cmd, f)
146
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
151
if err := ProcessCommand(cmd); err != nil {
152
if err == flag.ErrHelp {
153
commandHelp(args[0], cmd, f)
155
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
160
if err := cmd.Run(f); err != nil {
161
if err == flag.ErrHelp {
162
commandHelp(args[0], cmd, f)
164
fmt.Fprintf(os.Stderr, "Error: %s\n", err)