| Index: go/src/infra/tools/cr/lib/subcommand/subcommand.go
|
| diff --git a/go/src/infra/tools/cr/lib/subcommand/subcommand.go b/go/src/infra/tools/cr/lib/subcommand/subcommand.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f36c8472a693a917412444cc81c46e66939e6b17
|
| --- /dev/null
|
| +++ b/go/src/infra/tools/cr/lib/subcommand/subcommand.go
|
| @@ -0,0 +1,107 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/*
|
| +Library for defining subcommands in a structured way.
|
| +*/
|
| +
|
| +// Package subcommand provides a simple framework for defining subcommands.
|
| +package subcommand
|
| +
|
| +import (
|
| + "flag"
|
| + "fmt"
|
| + "os"
|
| + "sort"
|
| + "text/tabwriter"
|
| +)
|
| +
|
| +// Subcommand represents a single subcommand, with short and long versions of
|
| +// its help (usage) text, a function which adds command-line flags to a
|
| +// pre-existing flag.FlagSet, and a function which will be called to actually
|
| +// execute the subcommand.
|
| +type Subcommand struct {
|
| + shortHelp string
|
| + longHelp string
|
| + flagFn func(*flag.FlagSet)
|
| + runFn func(*flag.FlagSet) error
|
| +}
|
| +
|
| +// Help prints the short and long help messages, as well as the autogenerated
|
| +// flags documentation.
|
| +func (c *Subcommand) Help(flags *flag.FlagSet) {
|
| + fmt.Printf("%s\n\n%s\n\n", c.shortHelp, c.longHelp)
|
| + flags.PrintDefaults()
|
| +}
|
| +
|
| +// InitFlags adds the subcommand's flags to a FlagSet, if flagFn is defined.
|
| +func (c *Subcommand) InitFlags(flags *flag.FlagSet) {
|
| + if c.flagFn != nil {
|
| + c.flagFn(flags)
|
| + }
|
| +}
|
| +
|
| +// Run executes the subcommand's runFn, if it is defined.
|
| +func (c *Subcommand) Run(flags *flag.FlagSet) error {
|
| + if c.runFn != nil {
|
| + return c.runFn(flags)
|
| + }
|
| + return nil
|
| +}
|
| +
|
| +// Private registry holding a map of subcommands. Users of this library only
|
| +// have access to a default instance of the registry via the New and Tabulate
|
| +// functions, but tests can instantiate one directly.
|
| +type registry struct {
|
| + subcommands map[string]*Subcommand
|
| +}
|
| +
|
| +func (r *registry) new(name string, shortHelp string, longHelp string, flagFn func(*flag.FlagSet), runFn func(*flag.FlagSet) error) *Subcommand {
|
| + if _, ok := r.subcommands[name]; ok {
|
| + panic(fmt.Errorf("attempted to double-register subcommand %q", name))
|
| + }
|
| + ret := &Subcommand{shortHelp, longHelp, flagFn, runFn}
|
| + r.subcommands[name] = ret
|
| + return ret
|
| +}
|
| +
|
| +func (r *registry) get(name string) *Subcommand {
|
| + s, ok := r.subcommands[name]
|
| + if !ok {
|
| + return nil
|
| + }
|
| + return s
|
| +}
|
| +
|
| +func (r *registry) tabulate() {
|
| + colwriter := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
| + keys := make([]string, 0, len(r.subcommands))
|
| + for key := range r.subcommands {
|
| + keys = append(keys, key)
|
| + }
|
| + sort.Strings(keys)
|
| + for _, key := range keys {
|
| + fmt.Fprintf(colwriter, "\t%v\t%v\n", key, r.subcommands[key].shortHelp)
|
| + }
|
| + colwriter.Flush()
|
| +}
|
| +
|
| +var defaultRegistry = ®istry{make(map[string]*Subcommand)}
|
| +
|
| +// New creates, registers, and returns a new Subcommand struct.
|
| +// Panics if you attempt to register a second command with the same name.
|
| +func New(name string, shortHelp string, longHelp string, flagFn func(*flag.FlagSet), runFn func(*flag.FlagSet) error) *Subcommand {
|
| + return defaultRegistry.new(name, shortHelp, longHelp, flagFn, runFn)
|
| +}
|
| +
|
| +// Get returns a Subcommand struct which has been previously registered.
|
| +func Get(name string) *Subcommand {
|
| + return defaultRegistry.get(name)
|
| +}
|
| +
|
| +// Tabulate prints out all registered Subcommand names and their
|
| +// short help strings.
|
| +func Tabulate() {
|
| + defaultRegistry.tabulate()
|
| +}
|
|
|