Ross Light avatar Ross Light committed 696c2ae

Start subcmd package

Comments (0)

Files changed (2)

+/*
+Package subcmd provides a means of managing CLI programs with subcommands.  This
+is commonly seen in version control systems or package managers.  subcmd uses
+the flag package to parse optional arguments.
+*/
+package subcmd
+package subcmd
+
+import (
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+)
+
+// A Set stores a list of subcommands.
+type Set struct {
+	Name        string
+	Commands    []Command
+	GlobalFlags func(*flag.FlagSet)
+
+	output io.Writer
+}
+
+// SetOutput sets the destination for usage and error messages. If output
+// is nil, os.Stderr is used.
+func (s *Set) SetOutput(output io.Writer) {
+	s.output = output
+}
+
+func (s *Set) outWriter() io.Writer {
+	if s.output == nil {
+		return os.Stderr
+	}
+	return s.output
+}
+
+// Find returns the command that matches a name or nil.
+func (s *Set) Find(name string) *Command {
+	for i := range s.Commands {
+		c := &s.Commands[i]
+		if c.Matches(name) {
+			return c
+		}
+	}
+	return nil
+}
+
+// Func is a function that runs a command.  The first element of args must
+// be the command's name as it was invoked.
+type Func func(set *Set, cmd *Command, args []string) error
+
+// A Command represents a single subcommand.
+type Command struct {
+	Name    string
+	Aliases []string
+
+	// A one-line demo of the subcommand. Should include the name.
+	Synopsis string
+
+	// The longer description of the command.  The first line is used as a summary.
+	Description string
+
+	// The function to call to execute the command.
+	Func Func
+}
+
+// Summary returns the one-line summary of the command.
+func (c *Command) Summary() string {
+	return summary(c.Description)
+}
+
+// Matches reports whether the string is one of the recognized forms of the command.
+func (c *Command) Matches(name string) bool {
+	if name == c.Name {
+		return true
+	}
+	for _, a := range c.Aliases {
+		if name == a {
+			return true
+		}
+	}
+	return false
+}
+
+// FlagSet returns a new *flag.FlagSet that has the set's global flags, uses
+// PrintUsage, and uses the set's writer for output.
+func (c *Command) FlagSet(set *Set) *flag.FlagSet {
+	fset := flag.NewFlagSet(c.Name, flag.ContinueOnError)
+	if set.GlobalFlags != nil {
+		set.GlobalFlags(fset)
+	}
+	fset.Usage = func() {
+		c.PrintUsage(set, fset)
+	}
+	fset.SetOutput(set.outWriter())
+	return fset
+}
+
+// PrintUsage prints, to standard error unless configured otherwise, the
+// command's synopsis, description, aliases, and default values of flags
+// (if fset is not nil).
+func (c *Command) PrintUsage(set *Set, fset *flag.FlagSet) {
+	f := set.outWriter()
+	if c.Synopsis != "" {
+		fmt.Fprintf(f, "%s %s\n\n", set.Name, c.Synopsis)
+	} else {
+		fmt.Fprintf(f, "Usage of %s %s:\n\n", set.Name, c.Name)
+	}
+	if c.Description != "" {
+		fmt.Fprint(f, c.Description + "\n\n")
+	}
+	if al := c.Aliases; len(al) > 0 {
+		fmt.Fprintf(f, "aliases: %s\n\n", strings.Join(al, ", "))
+	}
+	if fset != nil {
+		fmt.Fprint(f, "options:\n\n")
+		fset.PrintDefaults()
+	}
+}
+
+// PrintSynopsis prints, to standard error unless configured otherwise, the
+// command's synopsis.
+func (c *Command) PrintSynopsis(set *Set) {
+	fmt.Fprintf(set.outWriter(), "usage: %s %s\n", set.Name, c.Synopsis)
+}
+
+// summary returns the first line of a string.
+func summary(s string) string {
+	if i := strings.IndexRune(s, '\n'); i != -1 {
+		return s[:i]
+	}
+	return s
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.