From 738fc184ef2421f504f3b98506f4a58574b56b82 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Tue, 4 Jun 2019 05:48:59 -0700 Subject: [PATCH 1/2] Subcommands example --- examples.txt | 1 + .../command-line-subcommands.go | 57 +++++ .../command-line-subcommands.hash | 2 + .../command-line-subcommands.sh | 21 ++ public/command-line-flags | 2 +- public/command-line-subcommands | 239 ++++++++++++++++++ public/index.html | 2 + 7 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 examples/command-line-subcommands/command-line-subcommands.go create mode 100644 examples/command-line-subcommands/command-line-subcommands.hash create mode 100644 examples/command-line-subcommands/command-line-subcommands.sh create mode 100644 public/command-line-subcommands diff --git a/examples.txt b/examples.txt index 9e13b51..2c1539b 100644 --- a/examples.txt +++ b/examples.txt @@ -59,6 +59,7 @@ Writing Files Line Filters Command-Line Arguments Command-Line Flags +Command-Line Subcommands Environment Variables HTTP Clients Spawning Processes diff --git a/examples/command-line-subcommands/command-line-subcommands.go b/examples/command-line-subcommands/command-line-subcommands.go new file mode 100644 index 0000000..132c9ec --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.go @@ -0,0 +1,57 @@ +// Some command-line tools, like the `go` tool or `git` +// have many *subcommands*, each with its own set of +// flags. For example, `go build` and `go get` are two +// different subcommands of the `go` tool. +// The `flag` package lets us easily define simple +// subcommands that have their own flags. + +package main + +import ( + "flag" + "fmt" + "os" +) + +func main() { + + // We declare a subcommand using the `NewFlagSet` + // function, and proceed to define new flags specific + // for this subcommand. + fooCmd := flag.NewFlagSet("foo", flag.ExitOnError) + fooEnable := fooCmd.Bool("enable", false, "enable") + fooName := fooCmd.String("name", "", "name") + + // For a different subcommand we can define different + // supported flags. + barCmd := flag.NewFlagSet("bar", flag.ExitOnError) + barLevel := barCmd.Int("level", 0, "level") + + // The subcommand is expected as the first argument + // to the program. + if len(os.Args) < 2 { + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } + + // Check which subcommand is invoked. + switch os.Args[1] { + case "foo": + + // For every subcommand, we parse its own flags and + // have access to trailing positional arguments. + fooCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'foo'") + fmt.Println(" enable:", *fooEnable) + fmt.Println(" name:", *fooName) + fmt.Println(" tail:", fooCmd.Args()) + case "bar": + barCmd.Parse(os.Args[2:]) + fmt.Println("subcommand 'bar'") + fmt.Println(" level:", *barLevel) + fmt.Println(" tail:", barCmd.Args()) + default: + fmt.Println("expected 'foo' or 'bar' subcommands") + os.Exit(1) + } +} diff --git a/examples/command-line-subcommands/command-line-subcommands.hash b/examples/command-line-subcommands/command-line-subcommands.hash new file mode 100644 index 0000000..b26ba5f --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.hash @@ -0,0 +1,2 @@ +673d7811734cfd8f8f5bcb411e12def1e158cf0b +V7xR3wMkquz diff --git a/examples/command-line-subcommands/command-line-subcommands.sh b/examples/command-line-subcommands/command-line-subcommands.sh new file mode 100644 index 0000000..a7cec9a --- /dev/null +++ b/examples/command-line-subcommands/command-line-subcommands.sh @@ -0,0 +1,21 @@ +$ go build command-line-subcommands.go + +# First invoke the foo subcommand +$ ./command-line-subcommands foo -enable -name=joe a1 a2 +subcommand 'foo' + enable: true + name: joe + tail: [a1 a2] + +# Now try bar +$ ./command-line-subcommands bar -level 8 a1 +subcommand 'bar' + level: 8 + tail: [a1] + +# But bar won't accept foo's flags +$ ./command-line-subcommands bar -enable a1 +flag provided but not defined: -enable +Usage of bar: + -level int + level diff --git a/public/command-line-flags b/public/command-line-flags index 47341d4..b2eb253 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -297,7 +297,7 @@ way to parameterize programs.

- Next example: Environment Variables. + Next example: Command-Line Subcommands.

+

Go by Example: Command-Line Subcommands

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Some command-line tools, like the go tool or git +have many subcommands, each with its own set of +flags. For example, go build and go get are two +different subcommands of the go tool. +The flag package lets us easily define simple +subcommands that have their own flags.

+ +
+ + +
+ + + +
package main
+
+ +
+ + + +
import (
+    "flag"
+    "fmt"
+    "os"
+)
+
+ +
+ + + +
func main() {
+
+ +
+

We declare a subcommand using the NewFlagSet +function, and proceed to define new flags specific +for this subcommand.

+ +
+ +
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
+    fooEnable := fooCmd.Bool("enable", false, "enable")
+    fooName := fooCmd.String("name", "", "name")
+
+ +
+

For a different subcommand we can define different +supported flags.

+ +
+ +
    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
+    barLevel := barCmd.Int("level", 0, "level")
+
+ +
+

The subcommand is expected as the first argument +to the program.

+ +
+ +
    if len(os.Args) < 2 {
+        fmt.Println("expected 'foo' or 'bar' subcommands")
+        os.Exit(1)
+    }
+
+ +
+

Check which subcommand is invoked.

+ +
+ +
    switch os.Args[1] {
+    case "foo":
+
+ +
+

For every subcommand, we parse its own flags and +have access to trailing positional arguments.

+ +
+ +
        fooCmd.Parse(os.Args[2:])
+        fmt.Println("subcommand 'foo'")
+        fmt.Println("  enable:", *fooEnable)
+        fmt.Println("  name:", *fooName)
+        fmt.Println("  tail:", fooCmd.Args())
+    case "bar":
+        barCmd.Parse(os.Args[2:])
+        fmt.Println("subcommand 'bar'")
+        fmt.Println("  level:", *barLevel)
+        fmt.Println("  tail:", barCmd.Args())
+    default:
+        fmt.Println("expected 'foo' or 'bar' subcommands")
+        os.Exit(1)
+    }
+}
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
$ go build command-line-subcommands.go 
+
+ +
+

First invoke the foo subcommand

+ +
+ +
$ ./command-line-subcommands foo -enable -name=joe a1 a2
+subcommand 'foo'
+  enable: true
+  name: joe
+  tail: [a1 a2]
+
+ +
+

Now try bar

+ +
+ +
$ ./command-line-subcommands bar -level 8 a1
+subcommand 'bar'
+  level: 8
+  tail: [a1]
+
+ +
+

But bar won’t accept foo’s flags

+ +
+ +
$ ./command-line-subcommands bar -enable a1
+flag provided but not defined: -enable
+Usage of bar:
+  -level int
+    	bar level
+
+ +
+ + +

+ Next example: Environment Variables. +

+ + +
+ + diff --git a/public/index.html b/public/index.html index 6b5727f..ca79490 100644 --- a/public/index.html +++ b/public/index.html @@ -145,6 +145,8 @@
  • Command-Line Flags
  • +
  • Command-Line Subcommands
  • +
  • Environment Variables
  • HTTP Clients
  • From af633e81f3d4b1087d743752fd83d298379b5f32 Mon Sep 17 00:00:00 2001 From: Mark McGranaghan Date: Tue, 4 Jun 2019 07:25:49 -0700 Subject: [PATCH 2/2] Presentation tweak --- .../command-line-subcommands/command-line-subcommands.go | 6 +++--- .../command-line-subcommands.hash | 4 ++-- public/command-line-subcommands | 8 ++++---- public/variables | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/command-line-subcommands/command-line-subcommands.go b/examples/command-line-subcommands/command-line-subcommands.go index 132c9ec..af57b21 100644 --- a/examples/command-line-subcommands/command-line-subcommands.go +++ b/examples/command-line-subcommands/command-line-subcommands.go @@ -36,10 +36,10 @@ func main() { // Check which subcommand is invoked. switch os.Args[1] { - case "foo": - // For every subcommand, we parse its own flags and - // have access to trailing positional arguments. + // For every subcommand, we parse its own flags and + // have access to trailing positional arguments. + case "foo": fooCmd.Parse(os.Args[2:]) fmt.Println("subcommand 'foo'") fmt.Println(" enable:", *fooEnable) diff --git a/examples/command-line-subcommands/command-line-subcommands.hash b/examples/command-line-subcommands/command-line-subcommands.hash index b26ba5f..f22bcc8 100644 --- a/examples/command-line-subcommands/command-line-subcommands.hash +++ b/examples/command-line-subcommands/command-line-subcommands.hash @@ -1,2 +1,2 @@ -673d7811734cfd8f8f5bcb411e12def1e158cf0b -V7xR3wMkquz +5a0ec258e4992e9b93b11d48f2f249092ff3db66 +gtgSAg76N4I diff --git a/public/command-line-subcommands b/public/command-line-subcommands index 190970c..f53c19f 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -32,7 +32,7 @@ subcommands that have their own flags.

    - +
    package main
     
    @@ -124,7 +124,6 @@ to the program.

        switch os.Args[1] {
    -    case "foo":
     
    @@ -138,7 +137,8 @@ have access to trailing positional arguments.

    -
            fooCmd.Parse(os.Args[2:])
    +            
        case "foo":
    +        fooCmd.Parse(os.Args[2:])
             fmt.Println("subcommand 'foo'")
             fmt.Println("  enable:", *fooEnable)
             fmt.Println("  name:", *fooName)
    @@ -218,7 +218,7 @@ have access to trailing positional arguments.

    flag provided but not defined: -enable Usage of bar: -level int - bar level + level
    diff --git a/public/variables b/public/variables index a02f89a..a10e9c0 100644 --- a/public/variables +++ b/public/variables @@ -150,7 +150,7 @@ initializing a variable, e.g. for 1 2 true 0 -short +apple