1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
5 // package cmd defines a RunFunc type, representing a process that can
6 // be invoked from a command line.
15 // A RunFunc runs a command with the given args, and returns an exit
17 type RunFunc func(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int
19 // Multi returns a command that looks up its first argument in m, and
20 // runs the resulting RunFunc with the remaining args.
24 // os.Exit(Multi(map[string]RunFunc{
25 // "foobar": func(prog string, args []string) int {
26 // fmt.Println(args[0])
29 // })("/usr/bin/multi", []string{"foobar", "baz"}))
31 // ...prints "baz" and exits 2.
32 func Multi(m map[string]RunFunc) RunFunc {
33 return func(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
35 fmt.Fprintf(stderr, "usage: %s command [args]", prog)
38 if cmd, ok := m[args[0]]; !ok {
39 fmt.Fprintf(stderr, "unrecognized command %q", args[0])
42 return cmd(prog+" "+args[0], args[1:], stdin, stdout, stderr)
47 // WithLateSubcommand wraps a RunFunc by skipping over some known
48 // flags to find a subcommand, and moving that subcommand to the front
49 // of the args before calling the wrapped RunFunc. For example:
51 // // Translate [ --format foo subcommand bar]
52 // // to [subcommand --format foo bar]
53 // WithLateSubcommand(fn, []string{"format"}, nil)
54 func WithLateSubcommand(run RunFunc, argFlags, boolFlags []string) RunFunc {
55 return func(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
56 flags := flag.NewFlagSet("prog", flag.ContinueOnError)
57 for _, arg := range argFlags {
58 flags.String(arg, "", "")
60 for _, arg := range boolFlags {
61 flags.Bool(arg, false, "")
63 // Ignore errors. We can't report a useful error
67 // Move the first arg after the recognized
68 // flags up to the front.
69 flagargs := len(args) - flags.NArg()
70 newargs := make([]string, len(args))
71 newargs[0] = args[flagargs]
72 copy(newargs[1:flagargs+1], args[:flagargs])
73 copy(newargs[flagargs+1:], args[flagargs+1:])
76 return run(prog, args, stdin, stdout, stderr)