Merge "runtimes/google/rt: bring back tests for runtime shutdown."
diff --git a/lib/cmdline/cmdline.go b/lib/cmdline/cmdline.go
deleted file mode 100644
index 5c71607..0000000
--- a/lib/cmdline/cmdline.go
+++ /dev/null
@@ -1,506 +0,0 @@
-// Package cmdline provides a data-driven framework to simplify writing
-// command-line programs.  It includes built-in support for formatted help.
-//
-// Commands may be linked together to form a command tree.  Since commands may
-// be arbitrarily nested within other commands, it's easy to create wrapper
-// programs that invoke existing commands.
-//
-// The syntax for each command-line program is:
-//
-//   command [flags] [subcommand [flags]]* [args]
-//
-// Each sequence of flags on the command-line is associated with the command
-// that immediately precedes them.  Global flags registered with the standard
-// flags package are allowed anywhere a command-specific flag is allowed.
-package cmdline
-
-import (
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strconv"
-	"strings"
-
-	"veyron.io/veyron/veyron/lib/textutil"
-)
-
-// ErrExitCode may be returned by the Run function of a Command to cause the
-// program to exit with a specific error code.
-type ErrExitCode int
-
-func (x ErrExitCode) Error() string {
-	return fmt.Sprintf("exit code %d", x)
-}
-
-// ErrUsage is returned to indicate an error in command usage; e.g. unknown
-// flags, subcommands or args.  It corresponds to exit code 1.
-const ErrUsage = ErrExitCode(1)
-
-// Command represents a single command in a command-line program.  A program
-// with subcommands is represented as a root Command with children representing
-// each subcommand.  The command graph must be a tree; each command may either
-// have exactly one parent (a sub-command), or no parent (the root), and cycles
-// are not allowed.  This makes it easier to display the usage for subcommands.
-type Command struct {
-	Name     string       // Name of the command.
-	Short    string       // Short description, shown in help called on parent.
-	Long     string       // Long description, shown in help called on itself.
-	Flags    flag.FlagSet // Flags for the command.
-	ArgsName string       // Name of the args, shown in usage line.
-	ArgsLong string       // Long description of the args, shown in help.
-
-	// Children of the command.  The framework will match args[0] against each
-	// child's name, and call Run on the first matching child.
-	Children []*Command
-
-	// Topics that provide additional info via the default help command.
-	Topics []Topic
-
-	// Run is a function that runs cmd with args.  If both Children and Run are
-	// specified, Run will only be called if none of the children match.  It is an
-	// error if neither is specified.  The special ErrExitCode error may be
-	// returned to indicate the command should exit with a specific exit code.
-	Run func(cmd *Command, args []string) error
-
-	// parent holds the parent of this Command, or nil if this is the root.
-	parent *Command
-
-	// stdout and stderr are set through Init.
-	stdout, stderr io.Writer
-
-	// parseFlags holds the merged flags used for parsing.  Each command starts
-	// with its own Flags, and we merge in all global flags.  If the same flag is
-	// specified in both sets, the command's own flag wins.
-	parseFlags *flag.FlagSet
-
-	// isDefaultHelp indicates whether this is the the default help command
-	// provided by the framework.
-	isDefaultHelp bool
-
-	// TODO(toddw): If necessary we can add alias support, e.g. for abbreviations.
-	//   Alias map[string]string
-}
-
-// Topic represents an additional help topic that is accessed via the default
-// help command.
-type Topic struct {
-	Name  string // Name of the topic.
-	Short string // Short description, shown in help for the command.
-	Long  string // Long description, shown in help for this topic.
-}
-
-// style describes the formatting style for usage descriptions.
-type style int
-
-const (
-	styleText  style = iota // Default style, good for cmdline output.
-	styleGoDoc              // Style good for godoc processing.
-)
-
-// String returns the human-readable representation of the style.
-func (s *style) String() string {
-	switch *s {
-	case styleText:
-		return "text"
-	case styleGoDoc:
-		return "godoc"
-	default:
-		panic(fmt.Errorf("Unhandled style %d", *s))
-	}
-}
-
-// Set implements the flag.Value interface method.
-func (s *style) Set(value string) error {
-	switch value {
-	case "text":
-		*s = styleText
-	case "godoc":
-		*s = styleGoDoc
-	default:
-		return fmt.Errorf("Unknown style %q", value)
-	}
-	return nil
-}
-
-// Stdout is where output goes.  Typically os.Stdout.
-func (cmd *Command) Stdout() io.Writer {
-	return cmd.stdout
-}
-
-// Stderr is where error messages go.  Typically os.Stderr
-func (cmd *Command) Stderr() io.Writer {
-	return cmd.stderr
-}
-
-// UsageErrorf prints the error message represented by the printf-style format
-// string and args, followed by the usage description of cmd.  Returns ErrUsage
-// to make it easy to use from within the cmd.Run function.
-func (cmd *Command) UsageErrorf(format string, v ...interface{}) error {
-	fmt.Fprint(cmd.stderr, "ERROR: ")
-	fmt.Fprintf(cmd.stderr, format, v...)
-	fmt.Fprint(cmd.stderr, "\n\n")
-	cmd.writeUsage(cmd.stderr)
-	return ErrUsage
-}
-
-// Have a reasonable default for the output width in runes.
-const defaultWidth = 80
-
-func outputWidth() int {
-	if width, err := strconv.Atoi(os.Getenv("CMDLINE_WIDTH")); err == nil && width != 0 {
-		return width
-	}
-	if _, width, err := textutil.TerminalSize(); err == nil && width != 0 {
-		return width
-	}
-	return defaultWidth
-}
-
-func (cmd *Command) writeUsage(w io.Writer) {
-	lineWriter := textutil.NewUTF8LineWriter(w, outputWidth())
-	cmd.usage(lineWriter, true)
-	lineWriter.Flush()
-}
-
-// usage prints the usage of cmd to the writer.  The firstCall boolean is set to
-// false when printing usage for multiple commands, and is used to avoid
-// printing redundant information (e.g. help command, global flags).
-func (cmd *Command) usage(w *textutil.LineWriter, firstCall bool) {
-	fmt.Fprintln(w, cmd.Long)
-	fmt.Fprintln(w)
-	// Usage line.
-	hasFlags := numFlags(&cmd.Flags) > 0
-	fmt.Fprintln(w, "Usage:")
-	path := cmd.namePath()
-	pathf := "   " + path
-	if hasFlags {
-		pathf += " [flags]"
-	}
-	if len(cmd.Children) > 0 {
-		fmt.Fprintln(w, pathf, "<command>")
-	}
-	if cmd.Run != nil {
-		if cmd.ArgsName != "" {
-			fmt.Fprintln(w, pathf, cmd.ArgsName)
-		} else {
-			fmt.Fprintln(w, pathf)
-		}
-	}
-	if len(cmd.Children) == 0 && cmd.Run == nil {
-		// This is a specification error.
-		fmt.Fprintln(w, pathf, "[ERROR: neither Children nor Run is specified]")
-	}
-	// Commands.
-	const minNameWidth = 11
-	if len(cmd.Children) > 0 {
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, "The", path, "commands are:")
-		nameWidth := minNameWidth
-		for _, child := range cmd.Children {
-			if len(child.Name) > nameWidth {
-				nameWidth = len(child.Name)
-			}
-		}
-		// Print as a table with aligned columns Name and Short.
-		w.SetIndents(spaces(3), spaces(3+nameWidth+1))
-		for _, child := range cmd.Children {
-			// Don't repeatedly list default help command.
-			if !child.isDefaultHelp || firstCall {
-				fmt.Fprintf(w, "%-[1]*[2]s %[3]s", nameWidth, child.Name, child.Short)
-				w.Flush()
-			}
-		}
-		w.SetIndents()
-		if firstCall {
-			fmt.Fprintf(w, "Run \"%s help [command]\" for command usage.\n", path)
-		}
-	}
-	// Args.
-	if cmd.Run != nil && cmd.ArgsLong != "" {
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, cmd.ArgsLong)
-	}
-	// Help topics.
-	if len(cmd.Topics) > 0 {
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, "The", path, "additional help topics are:")
-		nameWidth := minNameWidth
-		for _, topic := range cmd.Topics {
-			if len(topic.Name) > nameWidth {
-				nameWidth = len(topic.Name)
-			}
-		}
-		// Print as a table with aligned columns Name and Short.
-		w.SetIndents(spaces(3), spaces(3+nameWidth+1))
-		for _, topic := range cmd.Topics {
-			fmt.Fprintf(w, "%-[1]*[2]s %[3]s", nameWidth, topic.Name, topic.Short)
-			w.Flush()
-		}
-		w.SetIndents()
-		if firstCall {
-			fmt.Fprintf(w, "Run \"%s help [topic]\" for topic details.\n", path)
-		}
-	}
-	// Flags.
-	if hasFlags {
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, "The", path, "flags are:")
-		printFlags(w, &cmd.Flags)
-	}
-	// Global flags.
-	if numFlags(flag.CommandLine) > 0 && firstCall {
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, "The global flags are:")
-		printFlags(w, flag.CommandLine)
-	}
-}
-
-// namePath returns the path of command names up to cmd.
-func (cmd *Command) namePath() string {
-	var path []string
-	for ; cmd != nil; cmd = cmd.parent {
-		path = append([]string{cmd.Name}, path...)
-	}
-	return strings.Join(path, " ")
-}
-
-func numFlags(set *flag.FlagSet) (num int) {
-	set.VisitAll(func(*flag.Flag) {
-		num++
-	})
-	return
-}
-
-func printFlags(w *textutil.LineWriter, set *flag.FlagSet) {
-	set.VisitAll(func(f *flag.Flag) {
-		fmt.Fprintf(w, " -%s=%s", f.Name, f.DefValue)
-		w.SetIndents(spaces(3))
-		fmt.Fprintln(w, f.Usage)
-		w.SetIndents()
-	})
-}
-
-func spaces(count int) string {
-	return strings.Repeat(" ", count)
-}
-
-// newDefaultHelp creates a new default help command.  We need to create new
-// instances since the parent for each help command is different.
-func newDefaultHelp() *Command {
-	helpStyle := styleText
-	help := &Command{
-		Name:  helpName,
-		Short: "Display help for commands or topics",
-		Long: `
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-`,
-		ArgsName: "[command/topic ...]",
-		ArgsLong: `
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-`,
-		Run: func(cmd *Command, args []string) error {
-			// Help applies to its parent - e.g. "foo help" applies to the foo command.
-			lineWriter := textutil.NewUTF8LineWriter(cmd.stdout, outputWidth())
-			defer lineWriter.Flush()
-			return runHelp(lineWriter, cmd.parent, args, helpStyle)
-		},
-		isDefaultHelp: true,
-	}
-	help.Flags.Var(&helpStyle, "style", `The formatting style for help output, either "text" or "godoc".`)
-	return help
-}
-
-const helpName = "help"
-
-// runHelp runs the "help" command.
-func runHelp(w *textutil.LineWriter, cmd *Command, args []string, style style) error {
-	if len(args) == 0 {
-		cmd.usage(w, true)
-		return nil
-	}
-	if args[0] == "..." {
-		recursiveHelp(w, cmd, style, true)
-		return nil
-	}
-	// Try to display help for the subcommand.
-	subName, subArgs := args[0], args[1:]
-	for _, child := range cmd.Children {
-		if child.Name == subName {
-			return runHelp(w, child, subArgs, style)
-		}
-	}
-	// Try to display help for the help topic.
-	for _, topic := range cmd.Topics {
-		if topic.Name == subName {
-			fmt.Fprintln(w, topic.Long)
-			return nil
-		}
-	}
-	return cmd.UsageErrorf("%s: unknown command or topic %q", cmd.namePath(), subName)
-}
-
-// recursiveHelp prints help recursively via DFS from this cmd onward.
-func recursiveHelp(w *textutil.LineWriter, cmd *Command, style style, firstCall bool) {
-	if !firstCall {
-		lineBreak(w, style)
-		// Title-case required for godoc to recognize this as a section header.
-		header := strings.Title(cmd.namePath())
-		fmt.Fprintln(w, header)
-		fmt.Fprintln(w)
-	}
-	cmd.usage(w, firstCall)
-	for _, child := range cmd.Children {
-		// Don't repeatedly print default help command.
-		if !child.isDefaultHelp || firstCall {
-			recursiveHelp(w, child, style, false)
-		}
-	}
-	for _, topic := range cmd.Topics {
-		lineBreak(w, style)
-		// Title-case required for godoc to recognize this as a section header.
-		header := strings.Title(cmd.namePath()+" "+topic.Name) + " - help topic"
-		fmt.Fprintln(w, header)
-		fmt.Fprintln(w)
-		fmt.Fprintln(w, topic.Long)
-	}
-}
-
-func lineBreak(w *textutil.LineWriter, style style) {
-	w.Flush()
-	switch style {
-	case styleText:
-		width := w.Width()
-		if width < 0 {
-			// If the user has chosen an "unlimited" word-wrapping width, we still
-			// need a reasonable width for our visual line break.
-			width = defaultWidth
-		}
-		fmt.Fprintln(w, strings.Repeat("=", width))
-	case styleGoDoc:
-		fmt.Fprintln(w)
-	}
-	w.Flush()
-}
-
-func trimNewlines(s *string) { *s = strings.Trim(*s, "\n") }
-
-// Init initializes all nodes in the command tree rooted at cmd.  Init must be
-// called before Execute.
-func (cmd *Command) Init(parent *Command, stdout, stderr io.Writer) {
-	cmd.parent = parent
-	cmd.stdout = stdout
-	cmd.stderr = stderr
-	trimNewlines(&cmd.Short)
-	trimNewlines(&cmd.Long)
-	trimNewlines(&cmd.ArgsLong)
-	for tx := range cmd.Topics {
-		trimNewlines(&cmd.Topics[tx].Short)
-		trimNewlines(&cmd.Topics[tx].Long)
-	}
-	// Add help command, if it doesn't already exist.
-	hasHelp := false
-	for _, child := range cmd.Children {
-		if child.Name == helpName {
-			hasHelp = true
-			break
-		}
-	}
-	if !hasHelp && cmd.Name != helpName && len(cmd.Children) > 0 {
-		cmd.Children = append(cmd.Children, newDefaultHelp())
-	}
-	// Merge command-specific and global flags into parseFlags.  We want to handle
-	// all error output ourselves, so we:
-	//   1) Set flag.ContinueOnError so that Parse() doesn't exit or panic.
-	//   2) Discard all output (can't be nil, that means stderr).
-	//   3) Set an empty Usage function (can't be nil, that means default).
-	cmd.parseFlags = flag.NewFlagSet(cmd.Name, flag.ContinueOnError)
-	cmd.parseFlags.SetOutput(ioutil.Discard)
-	cmd.parseFlags.Usage = emptyUsage
-	mergeFlags(cmd.parseFlags, &cmd.Flags)
-	mergeFlags(cmd.parseFlags, flag.CommandLine)
-	// Call children recursively.
-	for _, child := range cmd.Children {
-		child.Init(cmd, stdout, stderr)
-	}
-}
-
-func mergeFlags(dst, src *flag.FlagSet) {
-	src.VisitAll(func(f *flag.Flag) {
-		trimNewlines(&f.Usage)
-		if dst.Lookup(f.Name) == nil {
-			dst.Var(f.Value, f.Name, f.Usage)
-		}
-	})
-}
-
-func emptyUsage() {}
-
-// Execute the command with the given args.  The returned error is ErrUsage if
-// there are usage errors, otherwise it is whatever the leaf command returns
-// from its Run function.
-func (cmd *Command) Execute(args []string) error {
-	path := cmd.namePath()
-	// Parse the merged flags.
-	if err := cmd.parseFlags.Parse(args); err != nil {
-		if err == flag.ErrHelp {
-			cmd.writeUsage(cmd.stdout)
-			return nil
-		}
-		return cmd.UsageErrorf("%s: %v", path, err)
-	}
-	args = cmd.parseFlags.Args()
-	// Look for matching children.
-	if len(args) > 0 {
-		subName, subArgs := args[0], args[1:]
-		for _, child := range cmd.Children {
-			if child.Name == subName {
-				return child.Execute(subArgs)
-			}
-		}
-	}
-	// No matching children, try Run.
-	if cmd.Run != nil {
-		if cmd.ArgsName == "" && len(args) > 0 {
-			if len(cmd.Children) > 0 {
-				return cmd.UsageErrorf("%s: unknown command %q", path, args[0])
-			}
-			return cmd.UsageErrorf("%s doesn't take any arguments", path)
-		}
-		return cmd.Run(cmd, args)
-	}
-	switch {
-	case len(cmd.Children) == 0:
-		return cmd.UsageErrorf("%s: neither Children nor Run is specified", path)
-	case len(args) > 0:
-		return cmd.UsageErrorf("%s: unknown command %q", path, args[0])
-	default:
-		return cmd.UsageErrorf("%s: no command specified", path)
-	}
-}
-
-// Main executes the command tree rooted at cmd, writing output to os.Stdout,
-// writing errors to os.Stderr, and getting args from os.Args.  We'll call
-// os.Exit with a non-zero exit code on errors.  It's meant as a simple
-// one-liner for the main function of command-line tools.
-func (cmd *Command) Main() {
-	cmd.Init(nil, os.Stdout, os.Stderr)
-	if err := cmd.Execute(os.Args[1:]); err != nil {
-		if code, ok := err.(ErrExitCode); ok {
-			os.Exit(int(code))
-		}
-		fmt.Fprintln(os.Stderr, "ERROR:", err)
-		os.Exit(2)
-	}
-}
diff --git a/lib/cmdline/cmdline_test.go b/lib/cmdline/cmdline_test.go
deleted file mode 100644
index 6cf6b0e..0000000
--- a/lib/cmdline/cmdline_test.go
+++ /dev/null
@@ -1,2238 +0,0 @@
-package cmdline
-
-import (
-	"bytes"
-	"errors"
-	"flag"
-	"fmt"
-	"os"
-	"regexp"
-	"strings"
-	"testing"
-)
-
-var (
-	errEcho           = errors.New("echo error")
-	flagExtra         bool
-	optNoNewline      bool
-	flagTopLevelExtra bool
-	globalFlag1       string
-	globalFlag2       *int64
-)
-
-// runEcho is used to implement commands for our tests.
-func runEcho(cmd *Command, args []string) error {
-	if len(args) == 1 {
-		if args[0] == "error" {
-			return errEcho
-		} else if args[0] == "bad_arg" {
-			return cmd.UsageErrorf("Invalid argument %v", args[0])
-		}
-	}
-	if flagExtra {
-		args = append(args, "extra")
-	}
-	if flagTopLevelExtra {
-		args = append(args, "tlextra")
-	}
-	if optNoNewline {
-		fmt.Fprint(cmd.Stdout(), args)
-	} else {
-		fmt.Fprintln(cmd.Stdout(), args)
-	}
-	return nil
-}
-
-// runHello is another function for test commands.
-func runHello(cmd *Command, args []string) error {
-	if flagTopLevelExtra {
-		args = append(args, "tlextra")
-	}
-	fmt.Fprintln(cmd.Stdout(), strings.Join(append([]string{"Hello"}, args...), " "))
-	return nil
-}
-
-type testCase struct {
-	Args        []string
-	Err         error
-	Stdout      string
-	Stderr      string
-	GlobalFlag1 string
-	GlobalFlag2 int64
-}
-
-func init() {
-	os.Setenv("CMDLINE_WIDTH", "80") // make sure the formatting stays the same.
-	flag.StringVar(&globalFlag1, "global1", "", "global test flag 1")
-	globalFlag2 = flag.Int64("global2", 0, "global test flag 2")
-}
-
-func stripOutput(got string) string {
-	// The global flags include the flags from the testing package, so strip them
-	// out before the comparison.
-	re := regexp.MustCompile(" -test[^\n]+\n(?:   [^\n]+\n)+")
-	return re.ReplaceAllLiteralString(got, "")
-}
-
-func runTestCases(t *testing.T, cmd *Command, tests []testCase) {
-	for _, test := range tests {
-		// Reset global variables before running each test case.
-		var stdout bytes.Buffer
-		var stderr bytes.Buffer
-		flagExtra = false
-		flagTopLevelExtra = false
-		optNoNewline = false
-		globalFlag1 = ""
-		*globalFlag2 = 0
-
-		// Run the execute function and check against expected results.
-		cmd.Init(nil, &stdout, &stderr)
-		if err := cmd.Execute(test.Args); err != test.Err {
-			t.Errorf("Ran with args %q\n GOT error:\n%q\nWANT error:\n%q", test.Args, err, test.Err)
-		}
-		if got, want := stripOutput(stdout.String()), test.Stdout; got != want {
-			t.Errorf("Ran with args %q\n GOT stdout:\n%q\nWANT stdout:\n%q", test.Args, got, want)
-		}
-		if got, want := stripOutput(stderr.String()), test.Stderr; got != want {
-			t.Errorf("Ran with args %q\n GOT stderr:\n%q\nWANT stderr:\n%q", test.Args, got, want)
-		}
-		if got, want := globalFlag1, test.GlobalFlag1; got != want {
-			t.Errorf("global1 flag got %q, want %q", got, want)
-		}
-		if got, want := *globalFlag2, test.GlobalFlag2; got != want {
-			t.Errorf("global2 flag got %q, want %q", got, want)
-		}
-	}
-}
-
-func TestNoCommands(t *testing.T) {
-	cmd := &Command{
-		Name:  "nocmds",
-		Short: "Nocmds is invalid.",
-		Long:  "Nocmds has no commands and no run function.",
-	}
-
-	var tests = []testCase{
-		{
-			Args: []string{},
-			Err:  ErrUsage,
-			Stderr: `ERROR: nocmds: neither Children nor Run is specified
-
-Nocmds has no commands and no run function.
-
-Usage:
-   nocmds [ERROR: neither Children nor Run is specified]
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: nocmds: neither Children nor Run is specified
-
-Nocmds has no commands and no run function.
-
-Usage:
-   nocmds [ERROR: neither Children nor Run is specified]
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, cmd, tests)
-}
-
-func TestOneCommand(t *testing.T) {
-	cmdEcho := &Command{
-		Name:  "echo",
-		Short: "Print strings on stdout",
-		Long: `
-Echo prints any strings passed in to stdout.
-`,
-		Run:      runEcho,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
-	}
-
-	prog := &Command{
-		Name:     "onecmd",
-		Short:    "Onecmd program.",
-		Long:     "Onecmd only has the echo command.",
-		Children: []*Command{cmdEcho},
-	}
-
-	var tests = []testCase{
-		{
-			Args: []string{},
-			Err:  ErrUsage,
-			Stderr: `ERROR: onecmd: no command specified
-
-Onecmd only has the echo command.
-
-Usage:
-   onecmd <command>
-
-The onecmd commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "onecmd help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: onecmd: unknown command "foo"
-
-Onecmd only has the echo command.
-
-Usage:
-   onecmd <command>
-
-The onecmd commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "onecmd help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Onecmd only has the echo command.
-
-Usage:
-   onecmd <command>
-
-The onecmd commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "onecmd help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "echo"},
-			Stdout: `Echo prints any strings passed in to stdout.
-
-Usage:
-   onecmd echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "help"},
-			Stdout: `Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   onecmd help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The onecmd help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Onecmd only has the echo command.
-
-Usage:
-   onecmd <command>
-
-The onecmd commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "onecmd help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Onecmd Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   onecmd echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Onecmd Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   onecmd help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The onecmd help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: onecmd: unknown command or topic "foo"
-
-Onecmd only has the echo command.
-
-Usage:
-   onecmd <command>
-
-The onecmd commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "onecmd help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args:   []string{"echo", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args: []string{"echo", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args: []string{"echo", "bad_arg"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: Invalid argument bad_arg
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   onecmd echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
-
-func TestMultiCommands(t *testing.T) {
-	cmdEcho := &Command{
-		Run:   runEcho,
-		Name:  "echo",
-		Short: "Print strings on stdout",
-		Long: `
-Echo prints any strings passed in to stdout.
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
-	}
-	var cmdEchoOpt = &Command{
-		Run:   runEcho,
-		Name:  "echoopt",
-		Short: "Print strings on stdout, with opts",
-		// Try varying number of header/trailer newlines around the long description.
-		Long: `Echoopt prints any args passed in to stdout.
-
-
-`,
-		ArgsName: "[args]",
-		ArgsLong: "[args] are arbitrary strings that will be echoed.",
-	}
-	cmdEchoOpt.Flags.BoolVar(&optNoNewline, "n", false, "Do not output trailing newline")
-
-	prog := &Command{
-		Name:     "multi",
-		Short:    "Multi test command",
-		Long:     "Multi has two variants of echo.",
-		Children: []*Command{cmdEcho, cmdEchoOpt},
-	}
-	prog.Flags.BoolVar(&flagExtra, "extra", false, "Print an extra arg")
-
-	var tests = []testCase{
-		{
-			Args: []string{},
-			Err:  ErrUsage,
-			Stderr: `ERROR: multi: no command specified
-
-Multi has two variants of echo.
-
-Usage:
-   multi [flags] <command>
-
-The multi commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "multi help [command]" for command usage.
-
-The multi flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Multi has two variants of echo.
-
-Usage:
-   multi [flags] <command>
-
-The multi commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "multi help [command]" for command usage.
-
-The multi flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Multi has two variants of echo.
-
-Usage:
-   multi [flags] <command>
-
-The multi commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "multi help [command]" for command usage.
-
-The multi flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Multi Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   multi echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Multi Echoopt
-
-Echoopt prints any args passed in to stdout.
-
-Usage:
-   multi echoopt [flags] [args]
-
-[args] are arbitrary strings that will be echoed.
-
-The multi echoopt flags are:
- -n=false
-   Do not output trailing newline
-================================================================================
-Multi Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   multi help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The multi help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "echo"},
-			Stdout: `Echo prints any strings passed in to stdout.
-
-Usage:
-   multi echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "echoopt"},
-			Stdout: `Echoopt prints any args passed in to stdout.
-
-Usage:
-   multi echoopt [flags] [args]
-
-[args] are arbitrary strings that will be echoed.
-
-The multi echoopt flags are:
- -n=false
-   Do not output trailing newline
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: multi: unknown command or topic "foo"
-
-Multi has two variants of echo.
-
-Usage:
-   multi [flags] <command>
-
-The multi commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "multi help [command]" for command usage.
-
-The multi flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args:   []string{"echo", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args:   []string{"-extra", "echo", "foo", "bar"},
-			Stdout: "[foo bar extra]\n",
-		},
-		{
-			Args: []string{"echo", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args:   []string{"echoopt", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args:   []string{"-extra", "echoopt", "foo", "bar"},
-			Stdout: "[foo bar extra]\n",
-		},
-		{
-			Args:   []string{"echoopt", "-n", "foo", "bar"},
-			Stdout: "[foo bar]",
-		},
-		{
-			Args:   []string{"-extra", "echoopt", "-n", "foo", "bar"},
-			Stdout: "[foo bar extra]",
-		},
-		{
-			Args:        []string{"-global1=globalStringValue", "-extra", "echoopt", "-n", "foo", "bar"},
-			Stdout:      "[foo bar extra]",
-			GlobalFlag1: "globalStringValue",
-		},
-		{
-			Args:        []string{"-global2=42", "echoopt", "-n", "foo", "bar"},
-			Stdout:      "[foo bar]",
-			GlobalFlag2: 42,
-		},
-		{
-			Args:        []string{"-global1=globalStringOtherValue", "-global2=43", "-extra", "echoopt", "-n", "foo", "bar"},
-			Stdout:      "[foo bar extra]",
-			GlobalFlag1: "globalStringOtherValue",
-			GlobalFlag2: 43,
-		},
-		{
-			Args: []string{"echoopt", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args: []string{"echo", "-n", "foo", "bar"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: multi echo: flag provided but not defined: -n
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   multi echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"-nosuchflag", "echo", "foo", "bar"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: multi: flag provided but not defined: -nosuchflag
-
-Multi has two variants of echo.
-
-Usage:
-   multi [flags] <command>
-
-The multi commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "multi help [command]" for command usage.
-
-The multi flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
-
-func TestMultiLevelCommands(t *testing.T) {
-	cmdEcho := &Command{
-		Run:   runEcho,
-		Name:  "echo",
-		Short: "Print strings on stdout",
-		Long: `
-Echo prints any strings passed in to stdout.
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
-	}
-	cmdEchoOpt := &Command{
-		Run:   runEcho,
-		Name:  "echoopt",
-		Short: "Print strings on stdout, with opts",
-		// Try varying number of header/trailer newlines around the long description.
-		Long: `Echoopt prints any args passed in to stdout.
-
-
-`,
-		ArgsName: "[args]",
-		ArgsLong: "[args] are arbitrary strings that will be echoed.",
-	}
-	cmdEchoOpt.Flags.BoolVar(&optNoNewline, "n", false, "Do not output trailing newline")
-	cmdHello := &Command{
-		Run:   runHello,
-		Name:  "hello",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-	}
-	echoProg := &Command{
-		Name:     "echoprog",
-		Short:    "Set of echo commands",
-		Long:     "Echoprog has two variants of echo.",
-		Children: []*Command{cmdEcho, cmdEchoOpt},
-		Topics: []Topic{
-			{Name: "topic3", Short: "Help topic 3 short", Long: "Help topic 3 long."},
-		},
-	}
-	echoProg.Flags.BoolVar(&flagExtra, "extra", false, "Print an extra arg")
-	prog := &Command{
-		Name:     "toplevelprog",
-		Short:    "Top level prog",
-		Long:     "Toplevelprog has the echo subprogram and the hello command.",
-		Children: []*Command{echoProg, cmdHello},
-		Topics: []Topic{
-			{Name: "topic1", Short: "Help topic 1 short", Long: "Help topic 1 long."},
-			{Name: "topic2", Short: "Help topic 2 short", Long: "Help topic 2 long."},
-		},
-	}
-	prog.Flags.BoolVar(&flagTopLevelExtra, "tlextra", false, "Print an extra arg for all commands")
-
-	var tests = []testCase{
-		{
-			Args: []string{},
-			Err:  ErrUsage,
-			Stderr: `ERROR: toplevelprog: no command specified
-
-Toplevelprog has the echo subprogram and the hello command.
-
-Usage:
-   toplevelprog [flags] <command>
-
-The toplevelprog commands are:
-   echoprog    Set of echo commands
-   hello       Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "toplevelprog help [command]" for command usage.
-
-The toplevelprog additional help topics are:
-   topic1      Help topic 1 short
-   topic2      Help topic 2 short
-Run "toplevelprog help [topic]" for topic details.
-
-The toplevelprog flags are:
- -tlextra=false
-   Print an extra arg for all commands
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Toplevelprog has the echo subprogram and the hello command.
-
-Usage:
-   toplevelprog [flags] <command>
-
-The toplevelprog commands are:
-   echoprog    Set of echo commands
-   hello       Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "toplevelprog help [command]" for command usage.
-
-The toplevelprog additional help topics are:
-   topic1      Help topic 1 short
-   topic2      Help topic 2 short
-Run "toplevelprog help [topic]" for topic details.
-
-The toplevelprog flags are:
- -tlextra=false
-   Print an extra arg for all commands
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Toplevelprog has the echo subprogram and the hello command.
-
-Usage:
-   toplevelprog [flags] <command>
-
-The toplevelprog commands are:
-   echoprog    Set of echo commands
-   hello       Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "toplevelprog help [command]" for command usage.
-
-The toplevelprog additional help topics are:
-   topic1      Help topic 1 short
-   topic2      Help topic 2 short
-Run "toplevelprog help [topic]" for topic details.
-
-The toplevelprog flags are:
- -tlextra=false
-   Print an extra arg for all commands
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Toplevelprog Echoprog
-
-Echoprog has two variants of echo.
-
-Usage:
-   toplevelprog echoprog [flags] <command>
-
-The toplevelprog echoprog commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-
-The toplevelprog echoprog additional help topics are:
-   topic3      Help topic 3 short
-
-The toplevelprog echoprog flags are:
- -extra=false
-   Print an extra arg
-================================================================================
-Toplevelprog Echoprog Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   toplevelprog echoprog echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Toplevelprog Echoprog Echoopt
-
-Echoopt prints any args passed in to stdout.
-
-Usage:
-   toplevelprog echoprog echoopt [flags] [args]
-
-[args] are arbitrary strings that will be echoed.
-
-The toplevelprog echoprog echoopt flags are:
- -n=false
-   Do not output trailing newline
-================================================================================
-Toplevelprog Echoprog Topic3 - help topic
-
-Help topic 3 long.
-================================================================================
-Toplevelprog Hello
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   toplevelprog hello [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Toplevelprog Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   toplevelprog help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The toplevelprog help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-================================================================================
-Toplevelprog Topic1 - help topic
-
-Help topic 1 long.
-================================================================================
-Toplevelprog Topic2 - help topic
-
-Help topic 2 long.
-`,
-		},
-		{
-			Args: []string{"help", "echoprog"},
-			Stdout: `Echoprog has two variants of echo.
-
-Usage:
-   toplevelprog echoprog [flags] <command>
-
-The toplevelprog echoprog commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "toplevelprog echoprog help [command]" for command usage.
-
-The toplevelprog echoprog additional help topics are:
-   topic3      Help topic 3 short
-Run "toplevelprog echoprog help [topic]" for topic details.
-
-The toplevelprog echoprog flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "topic1"},
-			Stdout: `Help topic 1 long.
-`,
-		},
-		{
-			Args: []string{"help", "topic2"},
-			Stdout: `Help topic 2 long.
-`,
-		},
-		{
-			Args: []string{"echoprog", "help", "..."},
-			Stdout: `Echoprog has two variants of echo.
-
-Usage:
-   toplevelprog echoprog [flags] <command>
-
-The toplevelprog echoprog commands are:
-   echo        Print strings on stdout
-   echoopt     Print strings on stdout, with opts
-   help        Display help for commands or topics
-Run "toplevelprog echoprog help [command]" for command usage.
-
-The toplevelprog echoprog additional help topics are:
-   topic3      Help topic 3 short
-Run "toplevelprog echoprog help [topic]" for topic details.
-
-The toplevelprog echoprog flags are:
- -extra=false
-   Print an extra arg
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Toplevelprog Echoprog Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   toplevelprog echoprog echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Toplevelprog Echoprog Echoopt
-
-Echoopt prints any args passed in to stdout.
-
-Usage:
-   toplevelprog echoprog echoopt [flags] [args]
-
-[args] are arbitrary strings that will be echoed.
-
-The toplevelprog echoprog echoopt flags are:
- -n=false
-   Do not output trailing newline
-================================================================================
-Toplevelprog Echoprog Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   toplevelprog echoprog help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The toplevelprog echoprog help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-================================================================================
-Toplevelprog Echoprog Topic3 - help topic
-
-Help topic 3 long.
-`,
-		},
-		{
-			Args: []string{"echoprog", "help", "echoopt"},
-			Stdout: `Echoopt prints any args passed in to stdout.
-
-Usage:
-   toplevelprog echoprog echoopt [flags] [args]
-
-[args] are arbitrary strings that will be echoed.
-
-The toplevelprog echoprog echoopt flags are:
- -n=false
-   Do not output trailing newline
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "echoprog", "topic3"},
-			Stdout: `Help topic 3 long.
-`,
-		},
-		{
-			Args: []string{"echoprog", "help", "topic3"},
-			Stdout: `Help topic 3 long.
-`,
-		},
-		{
-			Args: []string{"help", "hello"},
-			Stdout: `Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   toplevelprog hello [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: toplevelprog: unknown command or topic "foo"
-
-Toplevelprog has the echo subprogram and the hello command.
-
-Usage:
-   toplevelprog [flags] <command>
-
-The toplevelprog commands are:
-   echoprog    Set of echo commands
-   hello       Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "toplevelprog help [command]" for command usage.
-
-The toplevelprog additional help topics are:
-   topic1      Help topic 1 short
-   topic2      Help topic 2 short
-Run "toplevelprog help [topic]" for topic details.
-
-The toplevelprog flags are:
- -tlextra=false
-   Print an extra arg for all commands
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args:   []string{"echoprog", "echo", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args:   []string{"echoprog", "-extra", "echo", "foo", "bar"},
-			Stdout: "[foo bar extra]\n",
-		},
-		{
-			Args: []string{"echoprog", "echo", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args:   []string{"echoprog", "echoopt", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args:   []string{"echoprog", "-extra", "echoopt", "foo", "bar"},
-			Stdout: "[foo bar extra]\n",
-		},
-		{
-			Args:   []string{"echoprog", "echoopt", "-n", "foo", "bar"},
-			Stdout: "[foo bar]",
-		},
-		{
-			Args:   []string{"echoprog", "-extra", "echoopt", "-n", "foo", "bar"},
-			Stdout: "[foo bar extra]",
-		},
-		{
-			Args: []string{"echoprog", "echoopt", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args:   []string{"--tlextra", "echoprog", "-extra", "echoopt", "foo", "bar"},
-			Stdout: "[foo bar extra tlextra]\n",
-		},
-		{
-			Args:   []string{"hello", "foo", "bar"},
-			Stdout: "Hello foo bar\n",
-		},
-		{
-			Args:   []string{"--tlextra", "hello", "foo", "bar"},
-			Stdout: "Hello foo bar tlextra\n",
-		},
-		{
-			Args: []string{"hello", "--extra", "foo", "bar"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: toplevelprog hello: flag provided but not defined: -extra
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   toplevelprog hello [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"-extra", "echoprog", "echoopt", "foo", "bar"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: toplevelprog: flag provided but not defined: -extra
-
-Toplevelprog has the echo subprogram and the hello command.
-
-Usage:
-   toplevelprog [flags] <command>
-
-The toplevelprog commands are:
-   echoprog    Set of echo commands
-   hello       Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "toplevelprog help [command]" for command usage.
-
-The toplevelprog additional help topics are:
-   topic1      Help topic 1 short
-   topic2      Help topic 2 short
-Run "toplevelprog help [topic]" for topic details.
-
-The toplevelprog flags are:
- -tlextra=false
-   Print an extra arg for all commands
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
-
-func TestMultiLevelCommandsOrdering(t *testing.T) {
-	cmdHello11 := &Command{
-		Name:  "hello11",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	cmdHello12 := &Command{
-		Name:  "hello12",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	cmdHello21 := &Command{
-		Name:  "hello21",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	cmdHello22 := &Command{
-		Name:  "hello22",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	cmdHello31 := &Command{
-		Name:  "hello31",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	cmdHello32 := &Command{
-		Name:  "hello32",
-		Short: "Print strings on stdout preceded by \"Hello\"",
-		Long: `
-Hello prints any strings passed in to stdout preceded by "Hello".
-`,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-		Run:      runHello,
-	}
-	progHello3 := &Command{
-		Name:     "prog3",
-		Short:    "Set of hello commands",
-		Long:     "Prog3 has two variants of hello.",
-		Children: []*Command{cmdHello31, cmdHello32},
-	}
-	progHello2 := &Command{
-		Name:     "prog2",
-		Short:    "Set of hello commands",
-		Long:     "Prog2 has two variants of hello and a subprogram prog3.",
-		Children: []*Command{cmdHello21, progHello3, cmdHello22},
-	}
-	progHello1 := &Command{
-		Name:     "prog1",
-		Short:    "Set of hello commands",
-		Long:     "Prog1 has two variants of hello and a subprogram prog2.",
-		Children: []*Command{cmdHello11, cmdHello12, progHello2},
-	}
-
-	var tests = []testCase{
-		{
-			Args: []string{},
-			Err:  ErrUsage,
-			Stderr: `ERROR: prog1: no command specified
-
-Prog1 has two variants of hello and a subprogram prog2.
-
-Usage:
-   prog1 <command>
-
-The prog1 commands are:
-   hello11     Print strings on stdout preceded by "Hello"
-   hello12     Print strings on stdout preceded by "Hello"
-   prog2       Set of hello commands
-   help        Display help for commands or topics
-Run "prog1 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
-
-Usage:
-   prog1 <command>
-
-The prog1 commands are:
-   hello11     Print strings on stdout preceded by "Hello"
-   hello12     Print strings on stdout preceded by "Hello"
-   prog2       Set of hello commands
-   help        Display help for commands or topics
-Run "prog1 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
-
-Usage:
-   prog1 <command>
-
-The prog1 commands are:
-   hello11     Print strings on stdout preceded by "Hello"
-   hello12     Print strings on stdout preceded by "Hello"
-   prog2       Set of hello commands
-   help        Display help for commands or topics
-Run "prog1 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Prog1 Hello11
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 hello11 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Hello12
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 hello12 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2
-
-Prog2 has two variants of hello and a subprogram prog3.
-
-Usage:
-   prog1 prog2 <command>
-
-The prog1 prog2 commands are:
-   hello21     Print strings on stdout preceded by "Hello"
-   prog3       Set of hello commands
-   hello22     Print strings on stdout preceded by "Hello"
-================================================================================
-Prog1 Prog2 Hello21
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello21 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3
-
-Prog3 has two variants of hello.
-
-Usage:
-   prog1 prog2 prog3 <command>
-
-The prog1 prog2 prog3 commands are:
-   hello31     Print strings on stdout preceded by "Hello"
-   hello32     Print strings on stdout preceded by "Hello"
-================================================================================
-Prog1 Prog2 Prog3 Hello31
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello31 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Hello32
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello32 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Hello22
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello22 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   prog1 help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The prog1 help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"prog2", "help", "..."},
-			Stdout: `Prog2 has two variants of hello and a subprogram prog3.
-
-Usage:
-   prog1 prog2 <command>
-
-The prog1 prog2 commands are:
-   hello21     Print strings on stdout preceded by "Hello"
-   prog3       Set of hello commands
-   hello22     Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "prog1 prog2 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Prog1 Prog2 Hello21
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello21 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3
-
-Prog3 has two variants of hello.
-
-Usage:
-   prog1 prog2 prog3 <command>
-
-The prog1 prog2 prog3 commands are:
-   hello31     Print strings on stdout preceded by "Hello"
-   hello32     Print strings on stdout preceded by "Hello"
-================================================================================
-Prog1 Prog2 Prog3 Hello31
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello31 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Hello32
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello32 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Hello22
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello22 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   prog1 prog2 help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The prog1 prog2 help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"prog2", "prog3", "help", "..."},
-			Stdout: `Prog3 has two variants of hello.
-
-Usage:
-   prog1 prog2 prog3 <command>
-
-The prog1 prog2 prog3 commands are:
-   hello31     Print strings on stdout preceded by "Hello"
-   hello32     Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "prog1 prog2 prog3 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Prog1 Prog2 Prog3 Hello31
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello31 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Hello32
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello32 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   prog1 prog2 prog3 help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The prog1 prog2 prog3 help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "prog2", "prog3", "..."},
-			Stdout: `Prog3 has two variants of hello.
-
-Usage:
-   prog1 prog2 prog3 <command>
-
-The prog1 prog2 prog3 commands are:
-   hello31     Print strings on stdout preceded by "Hello"
-   hello32     Print strings on stdout preceded by "Hello"
-   help        Display help for commands or topics
-Run "prog1 prog2 prog3 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Prog1 Prog2 Prog3 Hello31
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello31 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Hello32
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello32 [strings]
-
-[strings] are arbitrary strings that will be printed.
-================================================================================
-Prog1 Prog2 Prog3 Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   prog1 prog2 prog3 help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The prog1 prog2 prog3 help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "-style=godoc", "..."},
-			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
-
-Usage:
-   prog1 <command>
-
-The prog1 commands are:
-   hello11     Print strings on stdout preceded by "Hello"
-   hello12     Print strings on stdout preceded by "Hello"
-   prog2       Set of hello commands
-   help        Display help for commands or topics
-Run "prog1 help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-
-Prog1 Hello11
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 hello11 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Hello12
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 hello12 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Prog2
-
-Prog2 has two variants of hello and a subprogram prog3.
-
-Usage:
-   prog1 prog2 <command>
-
-The prog1 prog2 commands are:
-   hello21     Print strings on stdout preceded by "Hello"
-   prog3       Set of hello commands
-   hello22     Print strings on stdout preceded by "Hello"
-
-Prog1 Prog2 Hello21
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello21 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Prog2 Prog3
-
-Prog3 has two variants of hello.
-
-Usage:
-   prog1 prog2 prog3 <command>
-
-The prog1 prog2 prog3 commands are:
-   hello31     Print strings on stdout preceded by "Hello"
-   hello32     Print strings on stdout preceded by "Hello"
-
-Prog1 Prog2 Prog3 Hello31
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello31 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Prog2 Prog3 Hello32
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 prog3 hello32 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Prog2 Hello22
-
-Hello prints any strings passed in to stdout preceded by "Hello".
-
-Usage:
-   prog1 prog2 hello22 [strings]
-
-[strings] are arbitrary strings that will be printed.
-
-Prog1 Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   prog1 help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The prog1 help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-	}
-
-	runTestCases(t, progHello1, tests)
-}
-
-func TestCommandAndArgs(t *testing.T) {
-	cmdEcho := &Command{
-		Name:  "echo",
-		Short: "Print strings on stdout",
-		Long: `
-Echo prints any strings passed in to stdout.
-`,
-		Run:      runEcho,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
-	}
-
-	prog := &Command{
-		Name:     "cmdargs",
-		Short:    "Cmdargs program.",
-		Long:     "Cmdargs has the echo command and a Run function with args.",
-		Children: []*Command{cmdEcho},
-		Run:      runHello,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be printed.",
-	}
-
-	var tests = []testCase{
-		{
-			Args:   []string{},
-			Stdout: "Hello\n",
-		},
-		{
-			Args:   []string{"foo"},
-			Stdout: "Hello foo\n",
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Cmdargs has the echo command and a Run function with args.
-
-Usage:
-   cmdargs <command>
-   cmdargs [strings]
-
-The cmdargs commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdargs help [command]" for command usage.
-
-[strings] are arbitrary strings that will be printed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "echo"},
-			Stdout: `Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdargs echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Cmdargs has the echo command and a Run function with args.
-
-Usage:
-   cmdargs <command>
-   cmdargs [strings]
-
-The cmdargs commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdargs help [command]" for command usage.
-
-[strings] are arbitrary strings that will be printed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Cmdargs Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdargs echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Cmdargs Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   cmdargs help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The cmdargs help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: cmdargs: unknown command or topic "foo"
-
-Cmdargs has the echo command and a Run function with args.
-
-Usage:
-   cmdargs <command>
-   cmdargs [strings]
-
-The cmdargs commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdargs help [command]" for command usage.
-
-[strings] are arbitrary strings that will be printed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args:   []string{"echo", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args: []string{"echo", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args: []string{"echo", "bad_arg"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: Invalid argument bad_arg
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdargs echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
-
-func TestCommandAndRunNoArgs(t *testing.T) {
-	cmdEcho := &Command{
-		Name:  "echo",
-		Short: "Print strings on stdout",
-		Long: `
-Echo prints any strings passed in to stdout.
-`,
-		Run:      runEcho,
-		ArgsName: "[strings]",
-		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
-	}
-
-	prog := &Command{
-		Name:     "cmdrun",
-		Short:    "Cmdrun program.",
-		Long:     "Cmdrun has the echo command and a Run function with no args.",
-		Children: []*Command{cmdEcho},
-		Run:      runHello,
-	}
-
-	var tests = []testCase{
-		{
-			Args:   []string{},
-			Stdout: "Hello\n",
-		},
-		{
-			Args: []string{"foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: cmdrun: unknown command "foo"
-
-Cmdrun has the echo command and a Run function with no args.
-
-Usage:
-   cmdrun <command>
-   cmdrun
-
-The cmdrun commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdrun help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help"},
-			Stdout: `Cmdrun has the echo command and a Run function with no args.
-
-Usage:
-   cmdrun <command>
-   cmdrun
-
-The cmdrun commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdrun help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "echo"},
-			Stdout: `Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdrun echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "..."},
-			Stdout: `Cmdrun has the echo command and a Run function with no args.
-
-Usage:
-   cmdrun <command>
-   cmdrun
-
-The cmdrun commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdrun help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-================================================================================
-Cmdrun Echo
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdrun echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-================================================================================
-Cmdrun Help
-
-Help with no args displays the usage of the parent command.
-
-Help with args displays the usage of the specified sub-command or help topic.
-
-"help ..." recursively displays help for all commands and topics.
-
-The output is formatted to a target width in runes.  The target width is
-determined by checking the environment variable CMDLINE_WIDTH, falling back on
-the terminal width from the OS, falling back on 80 chars.  By setting
-CMDLINE_WIDTH=x, if x > 0 the width is x, if x < 0 the width is unlimited, and
-if x == 0 or is unset one of the fallbacks is used.
-
-Usage:
-   cmdrun help [flags] [command/topic ...]
-
-[command/topic ...] optionally identifies a specific sub-command or help topic.
-
-The cmdrun help flags are:
- -style=text
-   The formatting style for help output, either "text" or "godoc".
-`,
-		},
-		{
-			Args: []string{"help", "foo"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: cmdrun: unknown command or topic "foo"
-
-Cmdrun has the echo command and a Run function with no args.
-
-Usage:
-   cmdrun <command>
-   cmdrun
-
-The cmdrun commands are:
-   echo        Print strings on stdout
-   help        Display help for commands or topics
-Run "cmdrun help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args:   []string{"echo", "foo", "bar"},
-			Stdout: "[foo bar]\n",
-		},
-		{
-			Args: []string{"echo", "error"},
-			Err:  errEcho,
-		},
-		{
-			Args: []string{"echo", "bad_arg"},
-			Err:  ErrUsage,
-			Stderr: `ERROR: Invalid argument bad_arg
-
-Echo prints any strings passed in to stdout.
-
-Usage:
-   cmdrun echo [strings]
-
-[strings] are arbitrary strings that will be echoed.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
-
-func TestLongCommandsHelp(t *testing.T) {
-	cmdLong := &Command{
-		Name:  "thisisaverylongcommand",
-		Short: "the short description of the very long command is very long, and will have to be wrapped",
-		Long:  "The long description of the very long command is also very long, and will similarly have to be wrapped",
-		Run:   runEcho,
-	}
-	cmdShort := &Command{
-		Name:  "x",
-		Short: "description of short command.",
-		Long:  "blah blah blah",
-		Run:   runEcho,
-	}
-	prog := &Command{
-		Name:     "program",
-		Short:    "Test help strings when there are long commands.",
-		Long:     "Test help strings when there are long commands.",
-		Children: []*Command{cmdShort, cmdLong},
-	}
-	var tests = []testCase{
-		{
-			Args: []string{"help"},
-			Stdout: `Test help strings when there are long commands.
-
-Usage:
-   program <command>
-
-The program commands are:
-   x                      description of short command.
-   thisisaverylongcommand the short description of the very long command is very
-                          long, and will have to be wrapped
-   help                   Display help for commands or topics
-Run "program help [command]" for command usage.
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-		{
-			Args: []string{"help", "thisisaverylongcommand"},
-			Stdout: `The long description of the very long command is also very long, and will
-similarly have to be wrapped
-
-Usage:
-   program thisisaverylongcommand
-
-The global flags are:
- -global1=
-   global test flag 1
- -global2=0
-   global test flag 2
-`,
-		},
-	}
-	runTestCases(t, prog, tests)
-}
diff --git a/lib/filelocker/locker.go b/lib/filelocker/locker.go
index 5e6674f..43dfd5f 100644
--- a/lib/filelocker/locker.go
+++ b/lib/filelocker/locker.go
@@ -18,7 +18,7 @@
 // Lock locks the provided file.
 //
 // If the file is already locked then the calling goroutine
-// blocks until the lock can be acquired.
+// blocks until the lock can be grabbed.
 //
 // The file must exist otherwise an error is returned.
 func Lock(filepath string) (Unlocker, error) {
@@ -32,6 +32,21 @@
 	return &unlocker{file}, nil
 }
 
+// TryLock tries to grab a lock on the provided file and
+// returns an error if it fails. This function is non-blocking.
+//
+// The file must exist otherwise an error is returned.
+func TryLock(filepath string) (Unlocker, error) {
+	file, err := os.Open(filepath)
+	if err != nil {
+		return nil, err
+	}
+	if err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
+		return nil, err
+	}
+	return &unlocker{file}, nil
+}
+
 // unlocker implements Unlocker.
 type unlocker struct {
 	file *os.File
diff --git a/lib/filelocker/locker_test.go b/lib/filelocker/locker_test.go
index 0060210..f3ce658 100644
--- a/lib/filelocker/locker_test.go
+++ b/lib/filelocker/locker_test.go
@@ -6,6 +6,7 @@
 	"io"
 	"io/ioutil"
 	"os"
+	"syscall"
 	"testing"
 	"time"
 
@@ -14,7 +15,7 @@
 )
 
 func init() {
-	modules.RegisterChild("testLockUnlockChild", "", testLockUnlockChild)
+	modules.RegisterChild("testLockChild", "", testLockChild)
 }
 
 func TestHelperProcess(t *testing.T) {
@@ -39,7 +40,7 @@
 	}
 }
 
-func testLockUnlockChild(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+func testLockChild(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
 	// Lock the file
 	unlocker, err := Lock(args[1])
 	if err != nil {
@@ -58,13 +59,13 @@
 	return nil
 }
 
-func TestLockUnlockInterProcess(t *testing.T) {
+func TestLockInterProcess(t *testing.T) {
 	filepath := newFile()
 	defer os.Remove(filepath)
 
 	sh := modules.NewShell()
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	h, err := sh.Start("testLockUnlockChild", nil, filepath)
+	h, err := sh.Start("testLockChild", nil, filepath)
 	if err != nil {
 		t.Fatalf("sh.Start failed: %v", err)
 	}
@@ -97,7 +98,7 @@
 	s.ExpectEOF()
 }
 
-func TestLockUnlockIntraProcess(t *testing.T) {
+func TestLockIntraProcess(t *testing.T) {
 	filepath := newFile()
 	defer os.Remove(filepath)
 
@@ -127,3 +128,33 @@
 		t.Fatal("Another goroutine failed to grab the lock after this goroutine released it")
 	}
 }
+
+func TestTryLock(t *testing.T) {
+	filepath := newFile()
+	defer os.Remove(filepath)
+
+	sh := modules.NewShell()
+	defer sh.Cleanup(os.Stderr, os.Stderr)
+	h, err := sh.Start("testLockChild", nil, filepath)
+	if err != nil {
+		t.Fatalf("sh.Start failed: %v", err)
+	}
+	s := expect.NewSession(t, h.Stdout(), time.Minute)
+
+	// Test that child grabbed the lock.
+	s.Expect("locked")
+
+	// Test that parent cannot grab the lock, and then send a message
+	// to the child to release the lock.
+	if _, err := TryLock(filepath); err != syscall.EWOULDBLOCK {
+		t.Fatal("TryLock returned error: %v, want: %v", err, syscall.EWOULDBLOCK)
+	}
+
+	// Test that the parent can grab the lock after the child has released it.
+	h.Stdin().Write([]byte("unlock\n"))
+	s.Expect("unlocked")
+	if _, err = TryLock(filepath); err != nil {
+		t.Fatalf("TryLock failed: %v", err)
+	}
+	s.ExpectEOF()
+}
diff --git a/lib/textutil/doc.go b/lib/textutil/doc.go
deleted file mode 100644
index cd28c8c..0000000
--- a/lib/textutil/doc.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// Package textutil implements utilities for handling human-readable text.
-//
-// This package includes a combination of low-level and high-level utilities.
-// The main high-level utility is available as NewUTF8LineWriter.
-package textutil
diff --git a/lib/textutil/line_writer.go b/lib/textutil/line_writer.go
deleted file mode 100644
index c7df3a5..0000000
--- a/lib/textutil/line_writer.go
+++ /dev/null
@@ -1,445 +0,0 @@
-package textutil
-
-import (
-	"fmt"
-	"io"
-	"unicode"
-)
-
-// LineWriter implements an io.Writer filter that formats input text into output
-// lines with a given target width in runes.
-//
-// Each input rune is classified into one of three kinds:
-//   EOL:    end-of-line, consisting of \f, \n, \r, \v, U+2028 or U+2029
-//   Space:  defined by unicode.IsSpace
-//   Letter: everything else
-//
-// The input text is expected to consist of words, defined as sequences of
-// letters.  Sequences of words form paragraphs, where paragraphs are separated
-// by either blank lines (that contain no letters), or an explicit U+2029
-// ParagraphSeparator.  Input lines with leading spaces are treated verbatim.
-//
-// Paragraphs are output as word-wrapped lines; line breaks only occur at word
-// boundaries.  Output lines are usually no longer than the target width.  The
-// exceptions are single words longer than the target width, which are output on
-// their own line, and verbatim lines, which may be arbitrarily longer or
-// shorter than the width.
-//
-// Output lines never contain trailing spaces.  Only verbatim output lines may
-// contain leading spaces.  Spaces separating input words are output verbatim,
-// unless it would result in a line with leading or trailing spaces.
-//
-// EOL runes within the input text are never written to the output; the output
-// line terminator and paragraph separator may be configured, and some EOL may
-// be output as a single space ' ' to maintain word separation.
-//
-// The algorithm greedily fills each output line with as many words as it can,
-// assuming that all Unicode code points have the same width.  Invalid UTF-8 is
-// silently transformed to the replacement character U+FFFD and treated as a
-// single rune.
-//
-// Flush must be called after the last call to Write; the input is buffered.
-//
-//   Implementation note: line breaking is a complicated topic.  This approach
-//   attempts to be simple and useful; a full implementation conforming to
-//   Unicode Standard Annex #14 would be complicated, and is not implemented.
-//   Languages that don't use spaces to separate words (e.g. CJK) won't work
-//   well under the current approach.
-//
-//   http://www.unicode.org/reports/tr14 [Unicode Line Breaking Algorithm]
-//   http://www.unicode.org/versions/Unicode4.0.0/ch05.pdf [5.8 Newline Guidelines]
-type LineWriter struct {
-	// State configured by the user.
-	w            io.Writer
-	runeDecoder  RuneChunkDecoder
-	width        runePos
-	lineTerm     []byte
-	paragraphSep string
-	indents      []string
-
-	// The buffer contains a single output line.
-	lineBuf byteRuneBuffer
-
-	// Keep track of the previous state and rune.
-	prevState state
-	prevRune  rune
-
-	// Keep track of blank input lines.
-	inputLineHasLetter bool
-
-	// lineBuf positions where the line starts (after separators and indents), a
-	// new word has started and the last word has ended.
-	lineStart    bytePos
-	newWordStart bytePos
-	lastWordEnd  bytePos
-
-	// Keep track of paragraph terminations and line indices, so we can output the
-	// paragraph separator and indents correctly.
-	terminateParagraph bool
-	paragraphLineIndex int
-	wroteFirstLine     bool
-}
-
-type state int
-
-const (
-	stateWordWrap  state = iota // Perform word-wrapping [start state]
-	stateVerbatim               // Verbatim output-line, no word-wrapping
-	stateSkipSpace              // Skip spaces in input line.
-)
-
-// NewLineWriter returns a new LineWriter with the given target width in runes,
-// producing output on the underlying writer w.  The dec and enc are used to
-// respectively decode runes from Write calls, and encode runes to w.
-func NewLineWriter(w io.Writer, width int, dec RuneChunkDecoder, enc RuneEncoder) *LineWriter {
-	ret := &LineWriter{
-		w:            w,
-		runeDecoder:  dec,
-		width:        runePos(width),
-		lineTerm:     []byte("\n"),
-		paragraphSep: "\n",
-		prevState:    stateWordWrap,
-		prevRune:     LineSeparator,
-		lineBuf:      byteRuneBuffer{enc: enc},
-	}
-	ret.resetLine()
-	return ret
-}
-
-// NewUTF8LineWriter returns a new LineWriter filter that implements io.Writer,
-// and decodes and encodes runes in UTF-8.
-func NewUTF8LineWriter(w io.Writer, width int) *LineWriter {
-	return NewLineWriter(w, width, &UTF8ChunkDecoder{}, UTF8Encoder{})
-}
-
-// Width returns the target width in runes.  If width < 0 the width is
-// unlimited; each paragraph is output as a single line.
-func (w *LineWriter) Width() int { return int(w.width) }
-
-// SetLineTerminator sets the line terminator for subsequent Write calls.  Every
-// output line is terminated with term; EOL runes from the input are never
-// written to the output.  A new LineWriter instance uses "\n" as the default
-// line terminator.
-//
-// Calls Flush internally, and returns any Flush error.
-func (w *LineWriter) SetLineTerminator(term string) error {
-	if err := w.Flush(); err != nil {
-		return err
-	}
-	w.lineTerm = []byte(term)
-	w.resetLine()
-	return nil
-}
-
-// SetParagraphSeparator sets the paragraph separator for subsequent Write
-// calls.  Every consecutive pair of non-empty paragraphs is separated with sep;
-// EOL runes from the input are never written to the output.  A new LineWriter
-// instance uses "\n" as the default paragraph separator.
-//
-// Calls Flush internally, and returns any Flush error.
-func (w *LineWriter) SetParagraphSeparator(sep string) error {
-	if err := w.Flush(); err != nil {
-		return err
-	}
-	w.paragraphSep = sep
-	w.resetLine()
-	return nil
-}
-
-// SetIndents sets the indentation for subsequent Write calls.  Multiple indents
-// may be set, corresponding to the indent to use for the corresponding
-// paragraph line.  E.g. SetIndents("AA", "BBB", C") means the first line in
-// each paragraph is indented with "AA", the second line in each paragraph is
-// indented with "BBB", and all subsequent lines in each paragraph are indented
-// with "C".
-//
-// SetIndents() is equivalent to SetIndents(""), SetIndents("", ""), etc.
-//
-// A new LineWriter instance has no indents by default.
-//
-// Calls Flush internally, and returns any Flush error.
-func (w *LineWriter) SetIndents(indents ...string) error {
-	if err := w.Flush(); err != nil {
-		return err
-	}
-	// Copy indents in case the user passed the slice via SetIndents(p...), and
-	// canonicalize the all empty case to nil.
-	allEmpty := true
-	w.indents = make([]string, len(indents))
-	for ix, indent := range indents {
-		w.indents[ix] = indent
-		if indent != "" {
-			allEmpty = false
-		}
-	}
-	if allEmpty {
-		w.indents = nil
-	}
-	w.resetLine()
-	return nil
-}
-
-// Write implements io.Writer by buffering data into the LineWriter w.  Actual
-// writes to the underlying writer may occur, and may include data buffered in
-// either this Write call or previous Write calls.
-//
-// Flush must be called after the last call to Write.
-func (w *LineWriter) Write(data []byte) (int, error) {
-	return RuneChunkWrite(w.runeDecoder, w.addRune, data)
-}
-
-// Flush flushes any remaining buffered text, and resets the paragraph line
-// count back to 0, so that indents will be applied starting from the first
-// line.  It does not imply a paragraph separator; repeated calls to Flush with
-// no intervening calls to other methods is equivalent to a single Flush.
-//
-// Flush must be called after the last call to Write, and may be called an
-// arbitrary number of times before the last Write.
-func (w *LineWriter) Flush() error {
-	if err := RuneChunkFlush(w.runeDecoder, w.addRune); err != nil {
-		return err
-	}
-	// Add U+2028 to force the last line (if any) to be written.
-	if err := w.addRune(LineSeparator); err != nil {
-		return err
-	}
-	// Reset the paragraph line count.
-	w.paragraphLineIndex = 0
-	w.resetLine()
-	return nil
-}
-
-// addRune is called every time w.runeDecoder decodes a full rune.
-func (w *LineWriter) addRune(r rune) error {
-	state, lineBreak := w.nextState(r, w.updateRune(r))
-	if lineBreak {
-		if err := w.writeLine(); err != nil {
-			return err
-		}
-	}
-	w.bufferRune(r, state, lineBreak)
-	w.prevState = state
-	w.prevRune = r
-	return nil
-}
-
-// We classify each incoming rune into three kinds for easier handling.
-type kind int
-
-const (
-	kindEOL kind = iota
-	kindSpace
-	kindLetter
-)
-
-func runeKind(r rune) kind {
-	switch r {
-	case '\f', '\n', '\r', '\v', LineSeparator, ParagraphSeparator:
-		return kindEOL
-	}
-	if unicode.IsSpace(r) {
-		return kindSpace
-	}
-	return kindLetter
-}
-
-func (w *LineWriter) updateRune(r rune) bool {
-	forceLineBreak := false
-	switch kind := runeKind(r); kind {
-	case kindEOL:
-		// Update lastWordEnd if the last word just ended.
-		if w.newWordStart != -1 {
-			w.newWordStart = -1
-			w.lastWordEnd = w.lineBuf.ByteLen()
-		}
-		switch {
-		case w.prevRune == '\r' && r == '\n':
-			// Treat "\r\n" as a single EOL; we've already handled the logic for '\r',
-			// so there's nothing to do when we see '\n'.
-		case r == LineSeparator:
-			// Treat U+2028 as a pure line break; it's never a paragraph break.
-			forceLineBreak = true
-		case r == ParagraphSeparator || !w.inputLineHasLetter:
-			// The paragraph has just been terminated if we see an explicit U+2029, or
-			// if we see a blank line, which may contain spaces.
-			forceLineBreak = true
-			w.terminateParagraph = true
-		}
-		w.inputLineHasLetter = false
-	case kindSpace:
-		// Update lastWordEnd if the last word just ended.
-		if w.newWordStart != -1 {
-			w.newWordStart = -1
-			w.lastWordEnd = w.lineBuf.ByteLen()
-		}
-	case kindLetter:
-		// Update newWordStart if a new word just started.
-		if w.newWordStart == -1 {
-			w.newWordStart = w.lineBuf.ByteLen()
-		}
-		w.inputLineHasLetter = true
-		w.terminateParagraph = false
-	default:
-		panic(fmt.Errorf("textutil: updateRune unhandled kind %d", kind))
-	}
-	return forceLineBreak
-}
-
-// nextState returns the next state and whether we should break the line.
-//
-// Here's a handy table that describes all the scenarios in which we will line
-// break input text, grouped by the reason for the break.  The current position
-// is the last non-* rune in each pattern, which is where we decide to break.
-//
-//              w.prevState   Next state   Buffer reset
-//              -----------   ----------   ------------
-//   ===== Force line break (U+2028 / U+2029, blank line) =====
-//   a..*|***   *             wordWrap     empty
-//   a._.|***   *             wordWrap     empty
-//   a+**|***   *             wordWrap     empty
-//
-//   ===== verbatim: wait for any EOL =====
-//   _*.*|***   verbatim      wordWrap     empty
-//
-//   ===== wordWrap: switch to verbatim =====
-//   a._*|***   wordWrap      verbatim     empty
-//
-//   ===== wordWrap: line is too wide =====
-//   abc.|***   wordWrap      wordWrap     empty
-//   abcd|.**   wordWrap      wordWrap     empty
-//   abcd|e.*   wordWrap      wordWrap     empty
-//   a_cd|.**   wordWrap      wordWrap     empty
-//
-//   abc_|***   wordWrap      skipSpace    empty
-//   abcd|_**   wordWrap      skipSpace    empty
-//   abcd|e_*   wordWrap      skipSpace    empty
-//   a_cd|_**   wordWrap      skipSpace    empty
-//
-//   a_cd|e**   wordWrap      start        newWordStart
-//
-//   LEGEND
-//     abcde  Letter
-//     .      End-of-line
-//     +      End-of-line (only U+2028 / U+2029)
-//     _      Space
-//     *      Any rune (letter, line-end or space)
-//     |      Visual indication of width=4, has no width itself.
-//
-// Note that Flush calls behave exactly as if an explicit U+2028 line separator
-// were added to the end of all buffered data.
-func (w *LineWriter) nextState(r rune, forceLineBreak bool) (state, bool) {
-	if forceLineBreak {
-		return stateWordWrap, true
-	}
-	kind := runeKind(r)
-	// Handle non word-wrap states, which are easy.
-	switch w.prevState {
-	case stateVerbatim:
-		if kind == kindEOL {
-			return stateWordWrap, true
-		}
-		return stateVerbatim, false
-	case stateSkipSpace:
-		if kind == kindSpace {
-			return stateSkipSpace, false
-		}
-		return stateWordWrap, false
-	}
-	// Handle stateWordWrap, which is more complicated.
-
-	// Switch to the verbatim state when we see a space right after an EOL.
-	if runeKind(w.prevRune) == kindEOL && kind == kindSpace {
-		return stateVerbatim, true
-	}
-	// Break on EOL or space when the line is too wide.  See above table.
-	if w.width >= 0 && w.width <= w.lineBuf.RuneLen()+1 {
-		switch kind {
-		case kindEOL:
-			return stateWordWrap, true
-		case kindSpace:
-			return stateSkipSpace, true
-		}
-		// case kindLetter falls through
-	}
-	// Handle the newWordStart case in the above table.
-	if w.width >= 0 && w.width < w.lineBuf.RuneLen()+1 && w.newWordStart != w.lineStart {
-		return stateWordWrap, true
-	}
-	// Stay in the wordWrap state and don't break the line.
-	return stateWordWrap, false
-}
-
-func (w *LineWriter) writeLine() error {
-	if w.lastWordEnd == -1 {
-		// Don't write blank lines, but we must reset the line in case the paragraph
-		// has just been terminated.
-		w.resetLine()
-		return nil
-	}
-	// Write the line (without trailing spaces) followed by the line terminator.
-	line := w.lineBuf.Bytes()[:w.lastWordEnd]
-	if _, err := w.w.Write(line); err != nil {
-		return err
-	}
-	if _, err := w.w.Write(w.lineTerm); err != nil {
-		return err
-	}
-	// Reset the line buffer.
-	w.wroteFirstLine = true
-	w.paragraphLineIndex++
-	if w.newWordStart != -1 {
-		// If we have an unterminated new word, we must be in the newWordStart case
-		// in the table above.  Handle the special buffer reset here.
-		newWord := string(w.lineBuf.Bytes()[w.newWordStart:])
-		w.resetLine()
-		w.newWordStart = w.lineBuf.ByteLen()
-		w.lineBuf.WriteString(newWord)
-	} else {
-		w.resetLine()
-	}
-	return nil
-}
-
-func (w *LineWriter) resetLine() {
-	w.lineBuf.Reset()
-	w.newWordStart = -1
-	w.lastWordEnd = -1
-	// Write the paragraph separator if the previous paragraph has terminated.
-	// This consumes no runes from the line width.
-	if w.wroteFirstLine && w.terminateParagraph {
-		w.lineBuf.WriteString0Runes(w.paragraphSep)
-		w.paragraphLineIndex = 0
-	}
-	// Add indent; a non-empty indent consumes runes from the line width.
-	var indent string
-	switch {
-	case w.paragraphLineIndex < len(w.indents):
-		indent = w.indents[w.paragraphLineIndex]
-	case len(w.indents) > 0:
-		indent = w.indents[len(w.indents)-1]
-	}
-	w.lineBuf.WriteString(indent)
-	w.lineStart = w.lineBuf.ByteLen()
-}
-
-func (w *LineWriter) bufferRune(r rune, state state, lineBreak bool) {
-	// Never add leading spaces to the buffer in the wordWrap state.
-	wordWrapNoLeadingSpaces := state == stateWordWrap && !lineBreak
-	switch kind := runeKind(r); kind {
-	case kindEOL:
-		// When we're word-wrapping and we see a letter followed by EOL, we convert
-		// the EOL into a single space in the buffer, to break the previous word
-		// from the next word.
-		if wordWrapNoLeadingSpaces && runeKind(w.prevRune) == kindLetter {
-			w.lineBuf.WriteRune(' ')
-		}
-	case kindSpace:
-		if wordWrapNoLeadingSpaces || state == stateVerbatim {
-			w.lineBuf.WriteRune(r)
-		}
-	case kindLetter:
-		w.lineBuf.WriteRune(r)
-	default:
-		panic(fmt.Errorf("textutil: bufferRune unhandled kind %d", kind))
-	}
-}
diff --git a/lib/textutil/line_writer_test.go b/lib/textutil/line_writer_test.go
deleted file mode 100644
index 29db23f..0000000
--- a/lib/textutil/line_writer_test.go
+++ /dev/null
@@ -1,268 +0,0 @@
-package textutil
-
-import (
-	"bytes"
-	"io"
-	"strings"
-	"testing"
-)
-
-type lp struct {
-	line, para string
-}
-
-var (
-	allIndents  = [][]int{nil, {}, {1}, {2}, {1, 2}, {2, 1}}
-	allIndents1 = [][]int{{1}, {2}, {1, 2}, {2, 1}}
-)
-
-func TestLineWriter(t *testing.T) {
-	tests := []struct {
-		Width   int
-		Indents [][]int
-		In      string // See xlateIn for details on the format
-		Want    string // See xlateWant for details on the format
-	}{
-		// Completely blank input yields empty output.
-		{4, allIndents, "", ""},
-		{4, allIndents, " ", ""},
-		{4, allIndents, "  ", ""},
-		{4, allIndents, "   ", ""},
-		{4, allIndents, "    ", ""},
-		{4, allIndents, "     ", ""},
-		{4, allIndents, "      ", ""},
-		{4, allIndents, "F N  R   V    L     P      ", ""},
-		// Single words never get word-wrapped, even if they're long.
-		{4, allIndents, "a", "0a."},
-		{4, allIndents, "ab", "0ab."},
-		{4, allIndents, "abc", "0abc."},
-		{4, allIndents, "abcd", "0abcd."},
-		{4, allIndents, "abcde", "0abcde."},
-		{4, allIndents, "abcdef", "0abcdef."},
-		// Word-wrapping boundary conditions.
-		{4, allIndents, "abc ", "0abc."},
-		{4, allIndents, "abc  ", "0abc."},
-		{4, allIndents, "abcN", "0abc."},
-		{4, allIndents, "abcN ", "0abc."},
-		{4, allIndents, "abcd ", "0abcd."},
-		{4, allIndents, "abcd  ", "0abcd."},
-		{4, allIndents, "abcdN", "0abcd."},
-		{4, allIndents, "abcdN ", "0abcd."},
-		{4, [][]int{nil}, "a cd", "0a cd."},
-		{4, [][]int{nil}, "a cd ", "0a cd."},
-		{4, [][]int{nil}, "a cdN", "0a cd."},
-		{4, allIndents1, "a cd", "0a.1cd."},
-		{4, allIndents1, "a cd ", "0a.1cd."},
-		{4, allIndents1, "a cdN", "0a.1cd."},
-		{4, allIndents, "a cde", "0a.1cde."},
-		{4, allIndents, "a cde ", "0a.1cde."},
-		{4, allIndents, "a cdeN", "0a.1cde."},
-		{4, [][]int{nil}, "a  d", "0a  d."},
-		{4, [][]int{nil}, "a  d ", "0a  d."},
-		{4, [][]int{nil}, "a  dN", "0a  d."},
-		{4, allIndents1, "a  d", "0a.1d."},
-		{4, allIndents1, "a  d ", "0a.1d."},
-		{4, allIndents1, "a  dN", "0a.1d."},
-		{4, allIndents, "a  de", "0a.1de."},
-		{4, allIndents, "a  de ", "0a.1de."},
-		{4, allIndents, "a  deN", "0a.1de."},
-		// Multi-line word-wrapping boundary conditions.
-		{4, allIndents, "abc e", "0abc.1e."},
-		{4, allIndents, "abc.e", "0abc.1e."},
-		{4, allIndents, "abc efgh", "0abc.1efgh."},
-		{4, allIndents, "abc.efgh", "0abc.1efgh."},
-		{4, allIndents, "abc efghi", "0abc.1efghi."},
-		{4, allIndents, "abc.efghi", "0abc.1efghi."},
-		{4, [][]int{nil}, "abc e gh", "0abc.1e gh."},
-		{4, [][]int{nil}, "abc.e.gh", "0abc.1e gh."},
-		{4, allIndents1, "abc e gh", "0abc.1e.2gh."},
-		{4, allIndents1, "abc.e.gh", "0abc.1e.2gh."},
-		{4, allIndents, "abc e ghijk", "0abc.1e.2ghijk."},
-		{4, allIndents, "abc.e.ghijk", "0abc.1e.2ghijk."},
-		// Verbatim lines.
-		{4, allIndents, " b", "0 b."},
-		{4, allIndents, "  bc", "0  bc."},
-		{4, allIndents, "   bcd", "0   bcd."},
-		{4, allIndents, "    bcde", "0    bcde."},
-		{4, allIndents, "     bcdef", "0     bcdef."},
-		{4, allIndents, "      bcdefg", "0      bcdefg."},
-		{4, allIndents, " b de ghijk", "0 b de ghijk."},
-		// Verbatim lines before word-wrapped lines.
-		{4, allIndents, " b.vw yz", "0 b.1vw.2yz."},
-		{4, allIndents, "  bc.vw yz", "0  bc.1vw.2yz."},
-		{4, allIndents, "   bcd.vw yz", "0   bcd.1vw.2yz."},
-		{4, allIndents, "    bcde.vw yz", "0    bcde.1vw.2yz."},
-		{4, allIndents, "     bcdef.vw yz", "0     bcdef.1vw.2yz."},
-		{4, allIndents, "      bcdefg.vw yz", "0      bcdefg.1vw.2yz."},
-		{4, allIndents, " b de ghijk.vw yz", "0 b de ghijk.1vw.2yz."},
-		// Verbatim lines after word-wrapped lines.
-		{4, allIndents, "vw yz. b", "0vw.1yz.2 b."},
-		{4, allIndents, "vw yz.  bc", "0vw.1yz.2  bc."},
-		{4, allIndents, "vw yz.   bcd", "0vw.1yz.2   bcd."},
-		{4, allIndents, "vw yz.    bcde", "0vw.1yz.2    bcde."},
-		{4, allIndents, "vw yz.     bcdef", "0vw.1yz.2     bcdef."},
-		{4, allIndents, "vw yz.      bcdefg", "0vw.1yz.2      bcdefg."},
-		{4, allIndents, "vw yz. b de ghijk", "0vw.1yz.2 b de ghijk."},
-		// Verbatim lines between word-wrapped lines.
-		{4, allIndents, "vw yz. b.mn pq", "0vw.1yz.2 b.2mn.2pq."},
-		{4, allIndents, "vw yz.  bc.mn pq", "0vw.1yz.2  bc.2mn.2pq."},
-		{4, allIndents, "vw yz.   bcd.mn pq", "0vw.1yz.2   bcd.2mn.2pq."},
-		{4, allIndents, "vw yz.    bcde.mn pq", "0vw.1yz.2    bcde.2mn.2pq."},
-		{4, allIndents, "vw yz.     bcdef.mn pq", "0vw.1yz.2     bcdef.2mn.2pq."},
-		{4, allIndents, "vw yz.      bcdefg.mn pq", "0vw.1yz.2      bcdefg.2mn.2pq."},
-		{4, allIndents, "vw yz. b de ghijk.mn pq", "0vw.1yz.2 b de ghijk.2mn.2pq."},
-		// Multi-paragraphs via explicit U+2029, and multi-newline.
-		{4, allIndents, "ab de ghPij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.ghPij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de gh Pij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.gh Pij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de ghNNij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.ghNNij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de ghNNNij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.ghNNNij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de gh N Nij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.gh N Nij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de gh N N Nij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.gh N N Nij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		// Special-case /r/n is a single EOL, but may be combined.
-		{4, allIndents, "ab de ghRNij lm op", "0ab.1de.2gh.2ij.2lm.2op."},
-		{4, allIndents, "ab.de.ghRNij.lm.op", "0ab.1de.2gh.2ij.2lm.2op."},
-		{4, allIndents, "ab de gh RNij lm op", "0ab.1de.2gh.2ij.2lm.2op."},
-		{4, allIndents, "ab.de.gh RNij.lm.op", "0ab.1de.2gh.2ij.2lm.2op."},
-		{4, allIndents, "ab de ghRNRNij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.ghRNRNij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de gh RN RNij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.gh RN RNij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab de ghR Nij lm op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		{4, allIndents, "ab.de.ghR Nij.lm.op", "0ab.1de.2gh.:0ij.1lm.2op."},
-		// Line separator via explicit U+2028 ends lines, but not paragraphs.
-		{4, allIndents, "aLcd", "0a.1cd."},
-		{4, allIndents, "a Lcd", "0a.1cd."},
-		{4, allIndents, "aLLcd", "0a.1cd."},
-		{4, allIndents, "a LLcd", "0a.1cd."},
-		// 0 width ends up with one word per line, except verbatim lines.
-		{0, allIndents, "a c e", "0a.1c.2e."},
-		{0, allIndents, "a cd fghij", "0a.1cd.2fghij."},
-		{0, allIndents, "a. cd fghij.l n", "0a.1 cd fghij.2l.2n."},
-		// -1 width ends up with all words on same line, except verbatim lines.
-		{-1, allIndents, "a c e", "0a c e."},
-		{-1, allIndents, "a cd fghij", "0a cd fghij."},
-		{-1, allIndents, "a. cd fghij.l n", "0a.1 cd fghij.2l n."},
-	}
-	for _, test := range tests {
-		// Run with a variety of chunk sizes.
-		for _, sizes := range [][]int{nil, {1}, {2}, {1, 2}, {2, 1}} {
-			// Run with a variety of line terminators and paragraph separators.
-			for _, lp := range []lp{{}, {"\n", "\n"}, {"L", "P"}, {"LLL", "PPP"}} {
-				// Run with a variety of indents.
-				if len(test.Indents) == 0 {
-					t.Errorf("%d %q %q has no indents, use [][]int{nil} rather than nil", test.Width, test.In, test.Want)
-				}
-				for _, indents := range test.Indents {
-					var buf bytes.Buffer
-					w := newUTF8LineWriter(t, &buf, test.Width, lp, indents)
-					lineWriterWriteFlush(t, w, xlateIn(test.In), sizes)
-					if got, want := buf.String(), xlateWant(test.Want, lp, indents); got != want {
-						t.Errorf("%q sizes:%v lp:%q indents:%v got %q, want %q", test.In, sizes, lp, indents, got, want)
-					}
-				}
-			}
-		}
-	}
-}
-
-// xlateIn translates our test.In pattern into an actual input string to feed
-// into the writer.  The point is to make it easy to specify the various control
-// sequences in a single character, so it's easier to understand.
-func xlateIn(text string) string {
-	text = strings.Replace(text, "F", "\f", -1)
-	text = strings.Replace(text, "N", "\n", -1)
-	text = strings.Replace(text, ".", "\n", -1) // Also allow . for easier reading
-	text = strings.Replace(text, "R", "\r", -1)
-	text = strings.Replace(text, "V", "\v", -1)
-	text = strings.Replace(text, "L", "\u2028", -1)
-	text = strings.Replace(text, "P", "\u2029", -1)
-	return text
-}
-
-// xlateWant translates our test.Want pattern into an actual expected string to
-// compare against the output.  The point is to make it easy to read and write
-// the expected patterns, and to make it easy to test various indents.
-func xlateWant(text string, lp lp, indents []int) string {
-	// Dot "." and colon ":" in the want string indicate line terminators and
-	// paragraph separators, respectively.
-	line := lp.line
-	if line == "" {
-		line = "\n"
-	}
-	text = strings.Replace(text, ".", line, -1)
-	para := lp.para
-	if para == "" {
-		para = "\n"
-	}
-	text = strings.Replace(text, ":", para, -1)
-	// The numbers in the want string indicate paragraph line numbers, to make it
-	// easier to automatically replace for various indent configurations.
-	switch len(indents) {
-	case 0:
-		text = strings.Replace(text, "0", "", -1)
-		text = strings.Replace(text, "1", "", -1)
-		text = strings.Replace(text, "2", "", -1)
-	case 1:
-		text = strings.Replace(text, "0", spaces(indents[0]), -1)
-		text = strings.Replace(text, "1", spaces(indents[0]), -1)
-		text = strings.Replace(text, "2", spaces(indents[0]), -1)
-	case 2:
-		text = strings.Replace(text, "0", spaces(indents[0]), -1)
-		text = strings.Replace(text, "1", spaces(indents[1]), -1)
-		text = strings.Replace(text, "2", spaces(indents[1]), -1)
-	case 3:
-		text = strings.Replace(text, "0", spaces(indents[0]), -1)
-		text = strings.Replace(text, "1", spaces(indents[1]), -1)
-		text = strings.Replace(text, "2", spaces(indents[2]), -1)
-	}
-	return text
-}
-
-func spaces(count int) string {
-	return strings.Repeat(" ", count)
-}
-
-func newUTF8LineWriter(t *testing.T, buf io.Writer, width int, lp lp, indents []int) *LineWriter {
-	w := NewUTF8LineWriter(buf, width)
-	if lp.line != "" || lp.para != "" {
-		if err := w.SetLineTerminator(lp.line); err != nil {
-			t.Errorf("SetLineTerminator(%q) got %v, want nil", lp.line, err)
-		}
-		if err := w.SetParagraphSeparator(lp.para); err != nil {
-			t.Errorf("SetParagraphSeparator(%q) got %v, want nil", lp.para, err)
-		}
-	}
-	if indents != nil {
-		indentStrs := make([]string, len(indents))
-		for ix, indent := range indents {
-			indentStrs[ix] = spaces(indent)
-		}
-		if err := w.SetIndents(indentStrs...); err != nil {
-			t.Errorf("SetIndents(%v) got %v, want nil", indentStrs, err)
-		}
-	}
-	return w
-}
-
-func lineWriterWriteFlush(t *testing.T, w *LineWriter, text string, sizes []int) {
-	// Write chunks of different sizes until we've exhausted the input.
-	remain := text
-	for ix := 0; len(remain) > 0; ix++ {
-		var chunk []byte
-		chunk, remain = nextChunk(remain, sizes, ix)
-		got, err := w.Write(chunk)
-		if want := len(chunk); got != want || err != nil {
-			t.Errorf("%q Write(%q) got (%d,%v), want (%d,nil)", text, chunk, got, err, want)
-		}
-	}
-	// Flush the writer.
-	if err := w.Flush(); err != nil {
-		t.Errorf("%q Flush() got %v, want nil", text, err)
-	}
-}
diff --git a/lib/textutil/rune.go b/lib/textutil/rune.go
deleted file mode 100644
index 57db02e..0000000
--- a/lib/textutil/rune.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package textutil
-
-import (
-	"bytes"
-)
-
-// TODO(toddw): Add UTF16 support.
-
-const (
-	EOF                = rune(-1) // Indicates the end of a rune stream.
-	LineSeparator      = '\u2028' // Unicode line separator rune.
-	ParagraphSeparator = '\u2029' // Unicode paragraph separator rune.
-)
-
-// RuneEncoder is the interface to an encoder of a stream of runes into
-// bytes.Buffer.
-type RuneEncoder interface {
-	// Encode encodes r into buf.
-	Encode(r rune, buf *bytes.Buffer)
-}
-
-// RuneStreamDecoder is the interface to a decoder of a contiguous stream of
-// runes.
-type RuneStreamDecoder interface {
-	// Next returns the next rune.  Invalid encodings are returned as U+FFFD.
-	// Returns EOF at the end of the stream.
-	Next() rune
-	// BytePos returns the current byte position in the original data buffer.
-	BytePos() int
-}
-
-// RuneChunkDecoder is the interface to a decoder of a stream of encoded runes
-// that may be arbitrarily chunked.
-//
-// Implementations of RuneChunkDecoder are commonly used to implement io.Writer
-// wrappers, to handle buffering when chunk boundaries may occur in the middle
-// of an encoded rune.
-type RuneChunkDecoder interface {
-	// Decode returns a RuneStreamDecoder that decodes the data chunk.  Call Next
-	// repeatedly on the returned stream until it returns EOF to decode the chunk.
-	Decode(chunk []byte) RuneStreamDecoder
-	// DecodeLeftover returns a RuneStreamDecoder that decodes leftover buffered
-	// data.  Call Next repeatedly on the returned stream until it returns EOF to
-	// ensure all buffered data is processed.
-	DecodeLeftover() RuneStreamDecoder
-}
-
-// RuneChunkWrite is a helper that calls d.Decode(data) and repeatedly calls
-// Next in a loop, calling fn for every rune that is decoded.  Returns the
-// number of bytes in data that were successfully processed.  If fn returns an
-// error, Write will return with that error, without processing any more data.
-//
-// This is a convenience for implementing io.Writer, given a RuneChunkDecoder.
-func RuneChunkWrite(d RuneChunkDecoder, fn func(rune) error, data []byte) (int, error) {
-	stream := d.Decode(data)
-	for r := stream.Next(); r != EOF; r = stream.Next() {
-		if err := fn(r); err != nil {
-			return stream.BytePos(), err
-		}
-	}
-	return stream.BytePos(), nil
-}
-
-// RuneChunkFlush is a helper that calls d.DecodeLeftover and repeatedly calls
-// Next in a loop, calling fn for every rune that is decoded.  If fn returns an
-// error, Flush will return with that error, without processing any more data.
-//
-// This is a convenience for implementing an additional Flush() call on an
-// implementation of io.Writer, given a RuneChunkDecoder.
-func RuneChunkFlush(d RuneChunkDecoder, fn func(rune) error) error {
-	stream := d.DecodeLeftover()
-	for r := stream.Next(); r != EOF; r = stream.Next() {
-		if err := fn(r); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// bytePos and runePos distinguish positions that are used in either domain;
-// we're trying to avoid silly mistakes like adding a bytePos to a runePos.
-type bytePos int
-type runePos int
-
-// byteRuneBuffer maintains a buffer with both byte and rune based positions.
-type byteRuneBuffer struct {
-	enc     RuneEncoder
-	buf     bytes.Buffer
-	runeLen runePos
-}
-
-func (b *byteRuneBuffer) ByteLen() bytePos { return bytePos(b.buf.Len()) }
-func (b *byteRuneBuffer) RuneLen() runePos { return b.runeLen }
-func (b *byteRuneBuffer) Bytes() []byte    { return b.buf.Bytes() }
-
-func (b *byteRuneBuffer) Reset() {
-	b.buf.Reset()
-	b.runeLen = 0
-}
-
-// WriteRune writes r into b.
-func (b *byteRuneBuffer) WriteRune(r rune) {
-	b.enc.Encode(r, &b.buf)
-	b.runeLen++
-}
-
-// WriteString writes str into b.
-func (b *byteRuneBuffer) WriteString(str string) {
-	for _, r := range str {
-		b.WriteRune(r)
-	}
-}
-
-// WriteString0Runes writes str into b, not incrementing the rune length.
-func (b *byteRuneBuffer) WriteString0Runes(str string) {
-	for _, r := range str {
-		b.enc.Encode(r, &b.buf)
-	}
-}
diff --git a/lib/textutil/utf8.go b/lib/textutil/utf8.go
deleted file mode 100644
index 349033e..0000000
--- a/lib/textutil/utf8.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package textutil
-
-import (
-	"bytes"
-	"fmt"
-	"unicode/utf8"
-)
-
-// UTF8Encoder implements RuneEncoder for the UTF-8 encoding.
-type UTF8Encoder struct{}
-
-var _ RuneEncoder = UTF8Encoder{}
-
-// Encode encodes r into buf in the UTF-8 encoding.
-func (UTF8Encoder) Encode(r rune, buf *bytes.Buffer) { buf.WriteRune(r) }
-
-// UTF8ChunkDecoder implements RuneChunkDecoder for a stream of UTF-8 data that
-// is arbitrarily chunked.
-//
-// UTF-8 is a byte-wise encoding that may use multiple bytes to encode a single
-// rune.  This decoder buffers partial runes that have been split across chunks,
-// so that a full rune is returned when the subsequent data chunk is provided.
-//
-// This is commonly used to implement an io.Writer wrapper over UTF-8 text.  It
-// is useful since the data provided to Write calls may be arbitrarily chunked.
-//
-// The zero UTF8ChunkDecoder is a decoder with an empty buffer.
-type UTF8ChunkDecoder struct {
-	// The only state we keep is the last partial rune we've encountered.
-	partial    [utf8.UTFMax]byte
-	partialLen int
-}
-
-var _ RuneChunkDecoder = (*UTF8ChunkDecoder)(nil)
-
-// Decode returns a RuneStreamDecoder that decodes the data chunk.  Call Next
-// repeatedly on the returned stream until it returns EOF to decode the chunk.
-//
-// If the data is chunked in the middle of an encoded rune, the final partial
-// rune in the chunk will be buffered, and the next call to Decode will continue
-// by combining the buffered data with the next chunk.
-//
-// Invalid encodings are transformed into U+FFFD, one byte at a time.  See
-// unicode/utf8.DecodeRune for details.
-func (d *UTF8ChunkDecoder) Decode(chunk []byte) RuneStreamDecoder {
-	return &utf8Stream{d, chunk, 0}
-}
-
-// DecodeLeftover returns a RuneStreamDecoder that decodes leftover buffered
-// data.  Call Next repeatedly on the returned stream until it returns EOF to
-// ensure all buffered data is processed.
-//
-// Since the only data that is buffered is the final partial rune, the returned
-// RuneStreamDecoder will only contain U+FFFD or EOF.
-func (d *UTF8ChunkDecoder) DecodeLeftover() RuneStreamDecoder {
-	return &utf8LeftoverStream{d, 0}
-}
-
-// nextRune decodes the next rune, logically combining any previously buffered
-// data with the data chunk.  It returns the decoded rune and the byte size of
-// the data that was used for the decoding.
-//
-// The returned size may be > 0 even if the returned rune == EOF, if a partial
-// rune was detected and buffered.  The returned size may be 0 even if the
-// returned rune != EOF, if previously buffered data was decoded.
-func (d *UTF8ChunkDecoder) nextRune(data []byte) (rune, int) {
-	if d.partialLen > 0 {
-		return d.nextRunePartial(data)
-	}
-	r, size := utf8.DecodeRune(data)
-	if r == utf8.RuneError && !utf8.FullRune(data) {
-		// Initialize the partial rune buffer with remaining data.
-		d.partialLen = copy(d.partial[:], data)
-		return d.verifyPartial(d.partialLen, data)
-	}
-	return r, size
-}
-
-// nextRunePartial implements nextRune when there is a previously buffered
-// partial rune.
-func (d *UTF8ChunkDecoder) nextRunePartial(data []byte) (rune, int) {
-	// Append as much data as we can to the partial rune, and see if it's full.
-	oldLen := d.partialLen
-	d.partialLen += copy(d.partial[oldLen:], data)
-	if !utf8.FullRune(d.partial[:d.partialLen]) {
-		// We still don't have a full rune - keep waiting.
-		return d.verifyPartial(d.partialLen-oldLen, data)
-	}
-	// We finally have a full rune.
-	r, size := utf8.DecodeRune(d.partial[:d.partialLen])
-	if size < oldLen {
-		// This occurs when we have a multi-byte rune that has the right number of
-		// bytes, but is an invalid code point.
-		//
-		// Say oldLen=2, and we just received the third byte of a 3-byte rune which
-		// isn't a UTF-8 trailing byte.  In this case utf8.DecodeRune returns U+FFFD
-		// and size=1, to indicate we should skip the first byte.
-		//
-		// We shift the unread portion of the old partial data forward, and update
-		// the partial len so that it's strictly decreasing.  The strictly
-		// decreasing property isn't necessary for correctness, but helps avoid
-		// repeatedly copying data into the partial buffer unecessarily.
-		copy(d.partial[:], d.partial[size:oldLen])
-		d.partialLen = oldLen - size
-		return r, 0
-	}
-	// We've used all the old buffered data; start decoding directly from data.
-	d.partialLen = 0
-	return r, size - oldLen
-}
-
-// verifyPartial is called when we don't have a full rune, and ncopy bytes have
-// been copied from data into the decoder partial rune buffer.  We expect that
-// all data has been buffered and we return EOF and the total size of the data.
-func (d *UTF8ChunkDecoder) verifyPartial(ncopy int, data []byte) (rune, int) {
-	if ncopy < len(data) {
-		// Something's very wrong if we managed to fill d.partial without copying
-		// all the data; any sequence of utf8.UTFMax bytes must be a full rune.
-		panic(fmt.Errorf("UTF8ChunkDecoder: partial rune %v with leftover data %v", d.partial[:d.partialLen], data[ncopy:]))
-	}
-	return EOF, len(data)
-}
-
-// utf8Stream implements UTF8ChunkDecoder.Decode.
-type utf8Stream struct {
-	d    *UTF8ChunkDecoder
-	data []byte
-	pos  int
-}
-
-var _ RuneStreamDecoder = (*utf8Stream)(nil)
-
-func (s *utf8Stream) Next() rune {
-	if s.pos == len(s.data) {
-		return EOF
-	}
-	r, size := s.d.nextRune(s.data[s.pos:])
-	s.pos += size
-	return r
-}
-
-func (s *utf8Stream) BytePos() int {
-	return s.pos
-}
-
-// utf8LeftoverStream implements UTF8ChunkDecoder.DecodeLeftover.
-type utf8LeftoverStream struct {
-	d   *UTF8ChunkDecoder
-	pos int
-}
-
-var _ RuneStreamDecoder = (*utf8LeftoverStream)(nil)
-
-func (s *utf8LeftoverStream) Next() rune {
-	if s.d.partialLen == 0 {
-		return EOF
-	}
-	r, size := utf8.DecodeRune(s.d.partial[:s.d.partialLen])
-	copy(s.d.partial[:], s.d.partial[size:])
-	s.d.partialLen -= size
-	s.pos += size
-	return r
-}
-
-func (s *utf8LeftoverStream) BytePos() int {
-	return s.pos
-}
diff --git a/lib/textutil/utf8_test.go b/lib/textutil/utf8_test.go
deleted file mode 100644
index 7517bef..0000000
--- a/lib/textutil/utf8_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package textutil
-
-import (
-	"reflect"
-	"testing"
-)
-
-func TestUTF8ChunkDecoder(t *testing.T) {
-	r2 := "Δ"
-	r3 := "王"
-	r4 := "\U0001F680"
-	tests := []struct {
-		Text string
-		Want []rune
-	}{
-		{"", nil},
-		{"a", []rune{'a'}},
-		{"abc", []rune{'a', 'b', 'c'}},
-		{"abc def ghi", []rune{'a', 'b', 'c', ' ', 'd', 'e', 'f', ' ', 'g', 'h', 'i'}},
-		// 2-byte runes.
-		{"ΔΘΠΣΦ", []rune{'Δ', 'Θ', 'Π', 'Σ', 'Φ'}},
-		// 3-byte runes.
-		{"王普澤世界", []rune{'王', '普', '澤', '世', '界'}},
-		// 4-byte runes.
-		{"\U0001F680\U0001F681\U0001F682\U0001F683", []rune{'\U0001F680', '\U0001F681', '\U0001F682', '\U0001F683'}},
-		// Mixed-bytes.
-		{"aΔ王\U0001F680æ™®Θb", []rune{'a', 'Δ', '王', '\U0001F680', 'æ™®', 'Θ', 'b'}},
-		// Error runes translated to U+FFFD.
-		{"\uFFFD", []rune{'\uFFFD'}},
-		{"a\uFFFDb", []rune{'a', '\uFFFD', 'b'}},
-		{"\xFF", []rune{'\uFFFD'}},
-		{"a\xFFb", []rune{'a', '\uFFFD', 'b'}},
-		// Multi-byte full runes.
-		{r2, []rune{[]rune(r2)[0]}},
-		{r3, []rune{[]rune(r3)[0]}},
-		{r4, []rune{[]rune(r4)[0]}},
-		// Partial runes translated to U+FFFD.
-		{r2[:1], []rune{'\uFFFD'}},
-		{r3[:1], []rune{'\uFFFD'}},
-		{r3[:2], []rune{'\uFFFD', '\uFFFD'}},
-		{r4[:1], []rune{'\uFFFD'}},
-		{r4[:2], []rune{'\uFFFD', '\uFFFD'}},
-		{r4[:3], []rune{'\uFFFD', '\uFFFD', '\uFFFD'}},
-		// Leading partial runes translated to U+FFFD.
-		{r2[:1] + "b", []rune{'\uFFFD', 'b'}},
-		{r3[:1] + "b", []rune{'\uFFFD', 'b'}},
-		{r3[:2] + "b", []rune{'\uFFFD', '\uFFFD', 'b'}},
-		{r4[:1] + "b", []rune{'\uFFFD', 'b'}},
-		{r4[:2] + "b", []rune{'\uFFFD', '\uFFFD', 'b'}},
-		{r4[:3] + "b", []rune{'\uFFFD', '\uFFFD', '\uFFFD', 'b'}},
-		// Trailing partial runes translated to U+FFFD.
-		{"a" + r2[:1], []rune{'a', '\uFFFD'}},
-		{"a" + r3[:1], []rune{'a', '\uFFFD'}},
-		{"a" + r3[:2], []rune{'a', '\uFFFD', '\uFFFD'}},
-		{"a" + r4[:1], []rune{'a', '\uFFFD'}},
-		{"a" + r4[:2], []rune{'a', '\uFFFD', '\uFFFD'}},
-		{"a" + r4[:3], []rune{'a', '\uFFFD', '\uFFFD', '\uFFFD'}},
-		// Bracketed partial runes translated to U+FFFD.
-		{"a" + r2[:1] + "b", []rune{'a', '\uFFFD', 'b'}},
-		{"a" + r3[:1] + "b", []rune{'a', '\uFFFD', 'b'}},
-		{"a" + r3[:2] + "b", []rune{'a', '\uFFFD', '\uFFFD', 'b'}},
-		{"a" + r4[:1] + "b", []rune{'a', '\uFFFD', 'b'}},
-		{"a" + r4[:2] + "b", []rune{'a', '\uFFFD', '\uFFFD', 'b'}},
-		{"a" + r4[:3] + "b", []rune{'a', '\uFFFD', '\uFFFD', '\uFFFD', 'b'}},
-	}
-	for _, test := range tests {
-		// Run with a variety of chunk sizes.
-		for _, sizes := range [][]int{nil, {1}, {2}, {1, 2}, {2, 1}, {3}, {1, 2, 3}} {
-			got := runeChunkWriteFlush(t, test.Text, sizes)
-			if want := test.Want; !reflect.DeepEqual(got, want) {
-				t.Errorf("%q got %v, want %v", test.Text, got, want)
-			}
-		}
-	}
-}
-
-func runeChunkWriteFlush(t *testing.T, text string, sizes []int) []rune {
-	var dec UTF8ChunkDecoder
-	var runes []rune
-	addRune := func(r rune) error {
-		runes = append(runes, r)
-		return nil
-	}
-	// Write chunks of different sizes until we've exhausted the input text.
-	remain := text
-	for ix := 0; len(remain) > 0; ix++ {
-		var chunk []byte
-		chunk, remain = nextChunk(remain, sizes, ix)
-		got, err := RuneChunkWrite(&dec, addRune, chunk)
-		if want := len(chunk); got != want || err != nil {
-			t.Errorf("%q RuneChunkWrite(%q) got (%d,%v), want (%d,nil)", text, chunk, got, err, want)
-		}
-	}
-	// Flush the decoder.
-	if err := RuneChunkFlush(&dec, addRune); err != nil {
-		t.Errorf("%q RuneChunkFlush got %v, want nil", text, err)
-	}
-	return runes
-}
-
-func nextChunk(text string, sizes []int, index int) (chunk []byte, remain string) {
-	if len(sizes) == 0 {
-		return []byte(text), ""
-	}
-	size := sizes[index%len(sizes)]
-	if size >= len(text) {
-		return []byte(text), ""
-	}
-	return []byte(text[:size]), text[size:]
-}
diff --git a/lib/textutil/util.go b/lib/textutil/util.go
deleted file mode 100644
index 85402de..0000000
--- a/lib/textutil/util.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package textutil
-
-import (
-	"syscall"
-	"unsafe"
-)
-
-// TerminalSize returns the dimensions of the terminal, if it's available from
-// the OS, otherwise returns an error.
-func TerminalSize() (row, col int, _ error) {
-	// Try getting the terminal size from stdout, stderr and stdin respectively.
-	// We try each of these in turn because the mechanism we're using fails if any
-	// of the fds is redirected on the command line.  E.g. "tool | less" redirects
-	// the stdout of tool to the stdin of less, and will mean tool cannot retrieve
-	// the terminal size from stdout.
-	//
-	// TODO(toddw): This probably only works on some linux / unix variants; add
-	// build tags and support different platforms.
-	if row, col, err := terminalSize(syscall.Stdout); err == nil {
-		return row, col, err
-	}
-	if row, col, err := terminalSize(syscall.Stderr); err == nil {
-		return row, col, err
-	}
-	return terminalSize(syscall.Stdin)
-}
-
-func terminalSize(fd int) (int, int, error) {
-	var ws winsize
-	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&ws))); err != 0 {
-		return 0, 0, err
-	}
-	return int(ws.row), int(ws.col), nil
-}
-
-// winsize must correspond to the struct defined in "sys/ioctl.h".  Do not
-// export this struct; it's a platform-specific implementation detail.
-type winsize struct {
-	row, col, xpixel, ypixel uint16
-}
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 15d20ef..2121314 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -106,8 +106,10 @@
 		delete(c.vcMap, ep.String())
 	}
 	sm := c.streamMgr
+	vcOpts := make([]stream.VCOpt, len(c.vcOpts))
+	copy(vcOpts, c.vcOpts)
 	c.vcMapMu.Unlock()
-	vc, err := sm.Dial(ep, c.vcOpts...)
+	vc, err := sm.Dial(ep, vcOpts...)
 	c.vcMapMu.Lock()
 	if err != nil {
 		return nil, err
diff --git a/security/util.go b/security/util.go
index e7ed33f..ea9df1c 100644
--- a/security/util.go
+++ b/security/util.go
@@ -118,28 +118,6 @@
 	return json.NewEncoder(w).Encode(acl)
 }
 
-// CaveatValidators returns the set of security.CaveatValidators
-// obtained by decoding the provided caveat bytes.
-//
-// It is an error if any of the provided caveat bytes cannot
-// be decoded into a security.CaveatValidator.
-// TODO(suharshs,ashankar,ataly): Rather than quitting on non-decodable caveats, just skip
-// them and return on caveats that we can decode.
-func CaveatValidators(caveats ...security.Caveat) ([]security.CaveatValidator, error) {
-	if len(caveats) == 0 {
-		return nil, nil
-	}
-	validators := make([]security.CaveatValidator, len(caveats))
-	for i, c := range caveats {
-		var v security.CaveatValidator
-		if err := vom.NewDecoder(bytes.NewReader(c.ValidatorVOM)).Decode(&v); err != nil {
-			return nil, fmt.Errorf("caveat bytes could not be VOM-decoded: %s", err)
-		}
-		validators[i] = v
-	}
-	return validators, nil
-}
-
 // ThirdPartyCaveats returns the set of security.ThirdPartyCaveats
 // that could be successfully decoded from the provided caveat bytes.
 func ThirdPartyCaveats(caveats ...security.Caveat) []security.ThirdPartyCaveat {
diff --git a/security/util_test.go b/security/util_test.go
index daf4fc1..2274a70 100644
--- a/security/util_test.go
+++ b/security/util_test.go
@@ -5,7 +5,6 @@
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rand"
-	"fmt"
 	"reflect"
 	"testing"
 
@@ -133,29 +132,14 @@
 		{C{newCaveat(tp)}, V{tp}, TP{tp}},
 		{C{newCaveat(fp), newCaveat(tp)}, V{fp, tp}, TP{tp}},
 	}
-	for i, d := range testdata {
-		// Test CaveatValidators.
-		got, err := CaveatValidators(d.caveats...)
-		if err != nil {
-			t.Errorf("CaveatValidators(%v) failed: %s", d.caveats, err)
-			continue
-		}
-		if !reflect.DeepEqual(got, d.validators) {
-			fmt.Println("TEST ", i)
-			t.Errorf("CaveatValidators(%v): got: %#v, want: %#v", d.caveats, got, d.validators)
-			continue
-		}
-		if _, err := CaveatValidators(append(d.caveats, invalid)...); err == nil {
-			t.Errorf("CaveatValidators(%v) succeeded unexpectedly", d.caveats)
-			continue
-		}
+	for _, d := range testdata {
 		// Test ThirdPartyCaveats.
 		if got := ThirdPartyCaveats(d.caveats...); !reflect.DeepEqual(got, d.tpCaveats) {
 			t.Errorf("ThirdPartyCaveats(%v): got: %#v, want: %#v", d.caveats, got, d.tpCaveats)
 			continue
 		}
 		if got := ThirdPartyCaveats(append(d.caveats, invalid)...); !reflect.DeepEqual(got, d.tpCaveats) {
-			t.Errorf("ThirdPartyCaveats(%v): got: %#v, want: %#v", d.caveats, got, d.tpCaveats)
+			t.Errorf("ThirdPartyCaveats(%v, invalid): got: %#v, want: %#v", d.caveats, got, d.tpCaveats)
 			continue
 		}
 	}
diff --git a/services/identity/auditor/blessing_auditor.go b/services/identity/auditor/blessing_auditor.go
index b00d28d..998797c 100644
--- a/services/identity/auditor/blessing_auditor.go
+++ b/services/identity/auditor/blessing_auditor.go
@@ -129,21 +129,13 @@
 	if err = vom.NewDecoder(bytes.NewBuffer(dbentry.caveats)).Decode(&b.Caveats); err != nil {
 		return BlessingEntry{DecodeError: fmt.Errorf("failed to decode caveats: %s", err)}
 	}
-	if b.RevocationCaveatID, err = revocationCaveatID(b.Caveats); err != nil {
-		return BlessingEntry{DecodeError: fmt.Errorf("error getting revocationCaveatID: %s", err)}
-	}
+	b.RevocationCaveatID = revocationCaveatID(b.Caveats)
 	return b
 }
 
-func revocationCaveatID(caveats []security.Caveat) (string, error) {
-	validators, err := vsecurity.CaveatValidators(caveats...)
-	if err != nil {
-		return "", err
+func revocationCaveatID(caveats []security.Caveat) string {
+	for _, tpcav := range vsecurity.ThirdPartyCaveats(caveats...) {
+		return tpcav.ID()
 	}
-	for _, cav := range validators {
-		if tpcav, ok := cav.(security.ThirdPartyCaveat); ok {
-			return tpcav.ID(), nil
-		}
-	}
-	return "", nil
+	return ""
 }
diff --git a/services/mgmt/logreader/impl/logfile.go b/services/mgmt/logreader/impl/logfile.go
index b29f416..fd6f354 100644
--- a/services/mgmt/logreader/impl/logfile.go
+++ b/services/mgmt/logreader/impl/logfile.go
@@ -12,6 +12,7 @@
 	"strings"
 
 	"veyron.io/veyron/veyron2/ipc"
+	"veyron.io/veyron/veyron2/services/mgmt/logreader"
 	"veyron.io/veyron/veyron2/services/mgmt/logreader/types"
 	"veyron.io/veyron/veyron2/verror"
 	"veyron.io/veyron/veyron2/vlog"
@@ -26,7 +27,7 @@
 
 // NewLogFileService returns a new log file server.
 func NewLogFileService(root, suffix string) interface{} {
-	return &logfileService{filepath.Clean(root), suffix}
+	return logreader.LogFileServer(&logfileService{filepath.Clean(root), suffix})
 }
 
 // translateNameToFilename returns the file name that corresponds to the object
@@ -53,7 +54,7 @@
 }
 
 // Size returns the size of the log file, in bytes.
-func (i *logfileService) Size(call ipc.ServerCall) (int64, error) {
+func (i *logfileService) Size(ipc.ServerContext) (int64, error) {
 	vlog.VI(1).Infof("%v.Size()", i.suffix)
 	fname, err := translateNameToFilename(i.root, i.suffix)
 	if err != nil {
@@ -74,7 +75,7 @@
 }
 
 // ReadLog returns log entries from the log file.
-func (i *logfileService) ReadLog(call ipc.ServerCall, startpos int64, numEntries int32, follow bool) (int64, error) {
+func (i *logfileService) ReadLog(ctx logreader.LogFileReadLogContext, startpos int64, numEntries int32, follow bool) (int64, error) {
 	vlog.VI(1).Infof("%v.ReadLog(%v, %v, %v)", i.suffix, startpos, numEntries, follow)
 	fname, err := translateNameToFilename(i.root, i.suffix)
 	if err != nil {
@@ -87,7 +88,7 @@
 		}
 		return 0, errOperationFailed
 	}
-	reader := newFollowReader(call, f, startpos, follow)
+	reader := newFollowReader(ctx, f, startpos, follow)
 	if numEntries == types.AllEntries {
 		numEntries = int32(math.MaxInt32)
 	}
@@ -102,7 +103,7 @@
 		if err != nil {
 			return reader.tell(), errOperationFailed
 		}
-		if err := call.Send(types.LogEntry{Position: offset, Line: line}); err != nil {
+		if err := ctx.SendStream().Send(types.LogEntry{Position: offset, Line: line}); err != nil {
 			return reader.tell(), err
 		}
 	}
diff --git a/services/mgmt/logreader/impl/reader.go b/services/mgmt/logreader/impl/reader.go
index 0a063b1..97d1272 100644
--- a/services/mgmt/logreader/impl/reader.go
+++ b/services/mgmt/logreader/impl/reader.go
@@ -14,7 +14,7 @@
 // - it aborts when the parent RPC is canceled.
 type followReader struct {
 	reader io.ReadSeeker
-	call   ipc.ServerCall
+	ctx    ipc.ServerContext
 	offset int64
 	follow bool
 	err    error
@@ -22,11 +22,11 @@
 }
 
 // newFollowReader is the factory for followReader.
-func newFollowReader(call ipc.ServerCall, reader io.ReadSeeker, startpos int64, follow bool) *followReader {
+func newFollowReader(ctx ipc.ServerContext, reader io.ReadSeeker, startpos int64, follow bool) *followReader {
 	_, err := reader.Seek(startpos, 0)
 	return &followReader{
 		reader: reader,
-		call:   call,
+		ctx:    ctx,
 		offset: startpos,
 		follow: follow,
 		err:    err,
@@ -43,9 +43,9 @@
 		return 0, f.err
 	}
 	for {
-		if f.call != nil {
+		if f.ctx != nil {
 			select {
-			case <-f.call.Done():
+			case <-f.ctx.Done():
 				return 0, errCanceled
 			default:
 			}
diff --git a/services/mgmt/pprof/impl/server.go b/services/mgmt/pprof/impl/server.go
index 8f2f39a..21e300d 100644
--- a/services/mgmt/pprof/impl/server.go
+++ b/services/mgmt/pprof/impl/server.go
@@ -8,12 +8,13 @@
 	"time"
 
 	"veyron.io/veyron/veyron2/ipc"
+	spprof "veyron.io/veyron/veyron2/services/mgmt/pprof"
 	"veyron.io/veyron/veyron2/verror"
 )
 
 // NewPProfService returns a new pprof service implementation.
 func NewPProfService() interface{} {
-	return &pprofService{}
+	return spprof.PProfServer(&pprofService{})
 }
 
 type pprofService struct {
@@ -39,14 +40,12 @@
 // addresses that pprof needs. Passing debug=1 adds comments translating
 // addresses to function names and line numbers, so that a programmer
 // can read the profile without tools.
-//
-// TODO(toddw): Change ipc.ServerCall into a struct stub context.
-func (pprofService) Profile(call ipc.ServerCall, name string, debug int32) error {
+func (pprofService) Profile(ctx spprof.PProfProfileContext, name string, debug int32) error {
 	profile := pprof.Lookup(name)
 	if profile == nil {
 		return verror.NoExistf("profile does not exist")
 	}
-	if err := profile.WriteTo(&streamWriter{call}, int(debug)); err != nil {
+	if err := profile.WriteTo(&streamWriter{ctx.SendStream()}, int(debug)); err != nil {
 		return verror.Convert(err)
 	}
 	return nil
@@ -54,13 +53,11 @@
 
 // CPUProfile enables CPU profiling for the requested duration and
 // streams the profile data.
-//
-// TODO(toddw): Change ipc.ServerCall into a struct stub context.
-func (pprofService) CPUProfile(call ipc.ServerCall, seconds int32) error {
+func (pprofService) CPUProfile(ctx spprof.PProfCPUProfileContext, seconds int32) error {
 	if seconds <= 0 || seconds > 3600 {
 		return verror.BadArgf("invalid number of seconds: %d", seconds)
 	}
-	if err := pprof.StartCPUProfile(&streamWriter{call}); err != nil {
+	if err := pprof.StartCPUProfile(&streamWriter{ctx.SendStream()}); err != nil {
 		return verror.Convert(err)
 	}
 	time.Sleep(time.Duration(seconds) * time.Second)
@@ -82,11 +79,13 @@
 }
 
 type streamWriter struct {
-	call ipc.ServerCall
+	sender interface {
+		Send(item []byte) error
+	}
 }
 
 func (w *streamWriter) Write(p []byte) (int, error) {
-	if err := w.call.Send(p); err != nil {
+	if err := w.sender.Send(p); err != nil {
 		return 0, err
 	}
 	return len(p), nil
diff --git a/services/mgmt/stats/impl/stats.go b/services/mgmt/stats/impl/stats.go
index 1b4b7dc..b398ee8 100644
--- a/services/mgmt/stats/impl/stats.go
+++ b/services/mgmt/stats/impl/stats.go
@@ -5,11 +5,13 @@
 import (
 	"time"
 
-	"veyron.io/veyron/veyron/lib/stats"
+	libstats "veyron.io/veyron/veyron/lib/stats"
 
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
+	"veyron.io/veyron/veyron2/services/mgmt/stats"
 	"veyron.io/veyron/veyron2/services/mgmt/stats/types"
+	"veyron.io/veyron/veyron2/services/watch"
 	watchtypes "veyron.io/veyron/veyron2/services/watch/types"
 	"veyron.io/veyron/veyron2/vdl/vdlutil"
 	"veyron.io/veyron/veyron2/verror"
@@ -30,19 +32,19 @@
 // NewStatsService returns a stats server implementation. The value of watchFreq
 // is used to specify the time between WatchGlob updates.
 func NewStatsService(suffix string, watchFreq time.Duration) interface{} {
-	return &statsService{suffix, watchFreq}
+	return stats.StatsServer(&statsService{suffix, watchFreq})
 }
 
 // Glob returns the name of all objects that match pattern.
-func (i *statsService) Glob(ctx *ipc.GlobContextStub, pattern string) error {
+func (i *statsService) Glob(ctx ipc.GlobContext, pattern string) error {
 	vlog.VI(1).Infof("%v.Glob(%q)", i.suffix, pattern)
 
-	it := stats.Glob(i.suffix, pattern, time.Time{}, false)
+	it := libstats.Glob(i.suffix, pattern, time.Time{}, false)
 	for it.Advance() {
 		ctx.SendStream().Send(naming.VDLMountEntry{Name: it.Value().Key})
 	}
 	if err := it.Err(); err != nil {
-		if err == stats.ErrNotFound {
+		if err == libstats.ErrNotFound {
 			return errNotFound
 		}
 		return errOperationFailed
@@ -52,7 +54,7 @@
 
 // WatchGlob returns the name and value of the objects that match the request,
 // followed by periodic updates when values change.
-func (i *statsService) WatchGlob(call ipc.ServerCall, req watchtypes.GlobRequest) error {
+func (i *statsService) WatchGlob(ctx watch.GlobWatcherWatchGlobContext, req watchtypes.GlobRequest) error {
 	vlog.VI(1).Infof("%v.WatchGlob(%+v)", i.suffix, req)
 
 	var t time.Time
@@ -60,7 +62,7 @@
 	for {
 		prevTime := t
 		t = time.Now()
-		it := stats.Glob(i.suffix, req.Pattern, prevTime, true)
+		it := libstats.Glob(i.suffix, req.Pattern, prevTime, true)
 		changes := []watchtypes.Change{}
 		for it.Advance() {
 			v := it.Value()
@@ -72,18 +74,18 @@
 			changes = append(changes, c)
 		}
 		if err := it.Err(); err != nil {
-			if err == stats.ErrNotFound {
+			if err == libstats.ErrNotFound {
 				return errNotFound
 			}
 			return errOperationFailed
 		}
 		for _, change := range changes {
-			if err := call.Send(change); err != nil {
+			if err := ctx.SendStream().Send(change); err != nil {
 				return err
 			}
 		}
 		select {
-		case <-call.Done():
+		case <-ctx.Done():
 			break Loop
 		case <-time.After(i.watchFreq):
 		}
@@ -95,11 +97,11 @@
 func (i *statsService) Value(ctx ipc.ServerContext) (vdlutil.Any, error) {
 	vlog.VI(1).Infof("%v.Value()", i.suffix)
 
-	v, err := stats.Value(i.suffix)
+	v, err := libstats.Value(i.suffix)
 	switch err {
-	case stats.ErrNotFound:
+	case libstats.ErrNotFound:
 		return nil, errNotFound
-	case stats.ErrNoValue:
+	case libstats.ErrNoValue:
 		return nil, errNoValue
 	case nil:
 		return v, nil
diff --git a/services/mgmt/vtrace/impl/vtrace.go b/services/mgmt/vtrace/impl/vtrace.go
index 3f29f26..d389436 100644
--- a/services/mgmt/vtrace/impl/vtrace.go
+++ b/services/mgmt/vtrace/impl/vtrace.go
@@ -2,6 +2,7 @@
 
 import (
 	"veyron.io/veyron/veyron2/ipc"
+	svtrace "veyron.io/veyron/veyron2/services/mgmt/vtrace"
 	"veyron.io/veyron/veyron2/uniqueid"
 	"veyron.io/veyron/veyron2/verror2"
 	"veyron.io/veyron/veyron2/vtrace"
@@ -19,13 +20,12 @@
 	return *tr, nil
 }
 
-// TODO(toddw): Change ipc.ServerCall into a struct stub context.
-func (v *vtraceService) AllTraces(call ipc.ServerCall) error {
+func (v *vtraceService) AllTraces(ctx svtrace.StoreAllTracesContext) error {
 	// TODO(mattr): Consider changing the store to allow us to iterate through traces
 	// when there are many.
 	traces := v.store.TraceRecords()
 	for i := range traces {
-		if err := call.Send(traces[i]); err != nil {
+		if err := ctx.SendStream().Send(traces[i]); err != nil {
 			return err
 		}
 	}
@@ -33,5 +33,5 @@
 }
 
 func NewVtraceService(store vtrace.Store) interface{} {
-	return &vtraceService{store}
+	return svtrace.StoreServer(&vtraceService{store})
 }
diff --git a/tools/application/impl.go b/tools/application/impl.go
index 2d06ad5..e37608f 100644
--- a/tools/application/impl.go
+++ b/tools/application/impl.go
@@ -11,9 +11,8 @@
 	"strings"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/services/mgmt/repository"
-
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/application"
diff --git a/tools/application/main.go b/tools/application/main.go
index a99a159..9e5d556 100644
--- a/tools/application/main.go
+++ b/tools/application/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/binary/impl.go b/tools/binary/impl.go
index 1df2314..69f0f51 100644
--- a/tools/binary/impl.go
+++ b/tools/binary/impl.go
@@ -3,7 +3,7 @@
 import (
 	"fmt"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/services/mgmt/lib/binary"
 )
 
diff --git a/tools/binary/main.go b/tools/binary/main.go
index a99a159..9e5d556 100644
--- a/tools/binary/main.go
+++ b/tools/binary/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/build/impl.go b/tools/build/impl.go
index 1d39669..a4b9b87 100644
--- a/tools/build/impl.go
+++ b/tools/build/impl.go
@@ -10,8 +10,7 @@
 	"strings"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
-
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/rt"
 	vbuild "veyron.io/veyron/veyron2/services/mgmt/build"
diff --git a/tools/build/main.go b/tools/build/main.go
index a99a159..9e5d556 100644
--- a/tools/build/main.go
+++ b/tools/build/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/debug/impl.go b/tools/debug/impl.go
index 36faee4..f3dc121 100644
--- a/tools/debug/impl.go
+++ b/tools/debug/impl.go
@@ -12,12 +12,11 @@
 	"sync"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/lib/glob"
 	"veyron.io/veyron/veyron/lib/signals"
 	"veyron.io/veyron/veyron/services/mgmt/pprof/client"
 	istats "veyron.io/veyron/veyron/services/mgmt/stats"
-
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
diff --git a/tools/debug/main.go b/tools/debug/main.go
index a99a159..9e5d556 100644
--- a/tools/debug/main.go
+++ b/tools/debug/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/mgmt/nodex/acl_impl.go b/tools/mgmt/nodex/acl_impl.go
index 384d0a7..ca2b0a9 100644
--- a/tools/mgmt/nodex/acl_impl.go
+++ b/tools/mgmt/nodex/acl_impl.go
@@ -6,13 +6,12 @@
 	"fmt"
 	"sort"
 
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
 	"veyron.io/veyron/veyron2/services/security/access"
 	"veyron.io/veyron/veyron2/verror"
-
-	"veyron.io/veyron/veyron/lib/cmdline"
 )
 
 var cmdGet = &cmdline.Command{
diff --git a/tools/mgmt/nodex/associate_impl.go b/tools/mgmt/nodex/associate_impl.go
index a3d2a49..342c35f 100644
--- a/tools/mgmt/nodex/associate_impl.go
+++ b/tools/mgmt/nodex/associate_impl.go
@@ -4,8 +4,7 @@
 	"fmt"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
-
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
 )
diff --git a/tools/mgmt/nodex/impl.go b/tools/mgmt/nodex/impl.go
index e062da2..3507e12 100644
--- a/tools/mgmt/nodex/impl.go
+++ b/tools/mgmt/nodex/impl.go
@@ -3,13 +3,12 @@
 import (
 	"fmt"
 
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
-
-	"veyron.io/veyron/veyron/lib/cmdline"
 )
 
 var cmdInstall = &cmdline.Command{
diff --git a/tools/mgmt/nodex/instance_impl.go b/tools/mgmt/nodex/instance_impl.go
index 251db6f..f328193 100644
--- a/tools/mgmt/nodex/instance_impl.go
+++ b/tools/mgmt/nodex/instance_impl.go
@@ -5,10 +5,9 @@
 import (
 	"fmt"
 
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/node"
-
-	"veyron.io/veyron/veyron/lib/cmdline"
 )
 
 var cmdStop = &cmdline.Command{
diff --git a/tools/mgmt/nodex/main.go b/tools/mgmt/nodex/main.go
index b3c5b7b..9e5d556 100644
--- a/tools/mgmt/nodex/main.go
+++ b/tools/mgmt/nodex/main.go
@@ -1,13 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-// TODO(rjkroege): The below fails because _test.go files are present. Fix this.
-//  An alternative in Sam/Acme: Edit /\/\*/+1, /\*\//-1 <./nodex help -style'='godoc ...
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index 99bd958..efa69fc 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -4,8 +4,7 @@
 	"fmt"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
-
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
diff --git a/tools/mounttable/main.go b/tools/mounttable/main.go
index a99a159..9e5d556 100644
--- a/tools/mounttable/main.go
+++ b/tools/mounttable/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/namespace/impl.go b/tools/namespace/impl.go
index 759548d..a1f1f47 100644
--- a/tools/namespace/impl.go
+++ b/tools/namespace/impl.go
@@ -4,7 +4,7 @@
 	"fmt"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vlog"
diff --git a/tools/namespace/main.go b/tools/namespace/main.go
index a99a159..9e5d556 100644
--- a/tools/namespace/main.go
+++ b/tools/namespace/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/principal/main.go b/tools/principal/main.go
index 5112eef..9096bb3 100644
--- a/tools/principal/main.go
+++ b/tools/principal/main.go
@@ -12,17 +12,16 @@
 	"os/user"
 	"time"
 
+	"veyron.io/lib/cmdline"
+	profile "veyron.io/veyron/veyron/profiles/static"
+	vsecurity "veyron.io/veyron/veyron/security"
+	"veyron.io/veyron/veyron/services/identity"
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 	"veyron.io/veyron/veyron2/vom"
-
-	"veyron.io/veyron/veyron/lib/cmdline"
-	profile "veyron.io/veyron/veyron/profiles/static"
-	vsecurity "veyron.io/veyron/veyron/security"
-	"veyron.io/veyron/veyron/services/identity"
 )
 
 var (
diff --git a/tools/profile/impl.go b/tools/profile/impl.go
index 2216a60..459b2ab 100644
--- a/tools/profile/impl.go
+++ b/tools/profile/impl.go
@@ -4,10 +4,9 @@
 	"fmt"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
 	"veyron.io/veyron/veyron/services/mgmt/profile"
 	"veyron.io/veyron/veyron/services/mgmt/repository"
-
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/services/mgmt/build"
 )
diff --git a/tools/profile/main.go b/tools/profile/main.go
index a99a159..9e5d556 100644
--- a/tools/profile/main.go
+++ b/tools/profile/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main
 
diff --git a/tools/vrpc/impl.go b/tools/vrpc/impl.go
index 8891515..7d0e560 100644
--- a/tools/vrpc/impl.go
+++ b/tools/vrpc/impl.go
@@ -6,9 +6,9 @@
 	"io"
 	"time"
 
-	"veyron.io/veyron/veyron/lib/cmdline"
+	"veyron.io/lib/cmdline"
+	_ "veyron.io/veyron/veyron/profiles/static"
 	idl_test_base "veyron.io/veyron/veyron/tools/vrpc/test_base"
-
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
index 49e94e1..f585f2b 100644
--- a/tools/vrpc/impl_test.go
+++ b/tools/vrpc/impl_test.go
@@ -6,15 +6,14 @@
 	"strings"
 	"testing"
 
+	"veyron.io/lib/cmdline"
+	"veyron.io/veyron/veyron/profiles"
+	"veyron.io/veyron/veyron/tools/vrpc/test_base"
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/vlog"
-
-	"veyron.io/veyron/veyron/lib/cmdline"
-	"veyron.io/veyron/veyron/profiles"
-	"veyron.io/veyron/veyron/tools/vrpc/test_base"
 )
 
 type server struct{}
diff --git a/tools/vrpc/main.go b/tools/vrpc/main.go
index 3c2043c..f52ab6f 100644
--- a/tools/vrpc/main.go
+++ b/tools/vrpc/main.go
@@ -1,11 +1,5 @@
 // The following enables go generate to generate the doc.go file.
-// Things to look out for:
-// 1) go:generate evaluates double-quoted strings into a single argument.
-// 2) go:generate performs $NAME expansion, so the bash cmd can't contain '$'.
-// 3) We generate into a *.tmp file first, otherwise go run will pick up the
-//    initially empty *.go file, and fail.
-//
-//go:generate bash -c "{ echo -e '// This file was auto-generated via go generate.\n// DO NOT UPDATE MANUALLY\n\n/*' && veyron go run *.go help -style=godoc ... && echo -e '*/\npackage main'; } > ./doc.go.tmp && mv ./doc.go.tmp ./doc.go"
+//go:generate go run $VEYRON_ROOT/lib/cmdline/testdata/gendoc.go .
 
 package main