Skip to content

Create a Script

John edited this page Nov 30, 2024 · 2 revisions

go_console.Script

When you want to create a simple command, you must create a go_console.Script object. In this case, can get rid of go_console.Script.Name and go_console.Script.Runner.

Note: go_console.Script.Runner will be executed when .Build() is called. (if defined)

package main

import (
  "github.com/DrSmithFr/go-console"
  "github.com/DrSmithFr/go-console/input/argument"
  "github.com/DrSmithFr/go-console/input/option"
)

func main() {

  //
  // Easy way to create a command with arguments and options
  //

  cmd := go_console.Script{
    Description: "The app:command command.",
    Arguments: []go_console.Argument{
      {
        Name:        "name",
        Value:       argument.Optional | argument.List,
        Description: "The name of the user.",
      },
    },
    Options: []go_console.Option{
      {
        Name:        "foo",
        Shortcut:    "f",
        Value:       option.None,
        Description: "The foo option.",
      },
    },
  }

  cmd.Build()
}

Script Help

We strongly recommend that you define a description for your command, arguments and options. This will be displayed when the user runs ./command --help

Script Input

The most interesting part of the commands are the arguments and options that you can make available. These arguments and options allow you to pass dynamic information from the terminal to the command.

Using Arguments

Arguments are the strings - separated by spaces - that come after the command name itself. They are ordered, and can be optional or required and/or list.

package main

import (
  "fmt"
  "github.com/DrSmithFr/go-console"
  "github.com/DrSmithFr/go-console/input/argument"
  "github.com/DrSmithFr/go-console/input/option"
)

func main() {

  // Declare the command with a struct
  cmd := go_console.Script{
    Description: "This is a test command",
    Arguments: []go_console.Argument{
      {
        Description: "The last name of the user",
        Name:        "name",
        Value:       argument.Required,
      },
    },
    Options: []go_console.Option{
      {
        Description: "The last name of the user",
        Name:        "foo",
        Shortcut:    "f",
        Value:       option.None,
      },
    },
  }
  // Build the command before using it
  cmd.Build()

  //
  // You now have access to a last_name argument in your command:
  //

  text := fmt.Sprintf("Hi %s", cmd.Input.Argument("name"))

  lastName := cmd.Input.Argument("last_name")

  if lastName != "" {
    text = fmt.Sprintf("%s %s", text, lastName)
  }

  // Using the Output as an io.Writer
  _, err := fmt.Fprintf(cmd.Output, "%s", text)

  if err != nil {
    panic(err)
  }

  // Using the Output Methode
  cmd.Output.Print("!")
}

The command can now be used in either of the following ways:

go run command-script John
> Hi John!

go run command John Smith
> Hi John Daligault!

It is also possible to let an argument take a list of values (imagine you want to greet all your friends). Only the last argument can be a list:

package main

import (
  "fmt"
  "github.com/DrSmithFr/go-console/input/argument"
  "github.com/DrSmithFr/go-console"
)

func main() {
  cmd := go_console.
    NewScript().
    AddInputArgument(
      argument.
        New("names", argument.List | argument.Required).
        SetDescription("Who do you want to greet?"),
    ).
    Build()

  //
  // You can access the names argument as an array:
  //

  names := cmd.Input.ArgumentList("names")

  for _, name := range names {
    cmd.PrintText(fmt.Sprintf("Hi %s!", name))
  }
}

To use this, specify as many names as you want:

go run command-script John Alex Fred

There are three argument variants you can use:

argument.Required

The argument is mandatory. The command doesn't run if the argument isn't provided;

argument.Optional

The argument is optional and therefore can be omitted. This is the default behavior of arguments;

argument.List

The argument can contain any number of values. For that reason, it must be used at the end of the argument list.

You can combine List with Required and Optional like this:

cmd := go_console.
  NewScript().
  AddInputArgument(
    argument.
      New("names", argument.List | argument.Required),
  ).
  Build()

Using Command Options

Unlike arguments, options are not ordered (meaning you can specify them in any order) and are specified with two dashes (e.g. --yell). Options are always optional, and can be setup to accept a value (e.g. --dir=src) or as a boolean flag without a value (e.g. --yell).

For example, add a new option to the command that can be used to specify how many times in a row the message should be printed:

package main

import (
  "fmt"
  "github.com/DrSmithFr/go-console/input/argument"
  "github.com/DrSmithFr/go-console/input/option"
  "github.com/DrSmithFr/go-console"
  "strconv"
)

func main() {
  cmd := go_console.
    NewScript().
    AddInputArgument(
      argument.
        New("name", argument.Required).
        SetDescription("Who do you want to greet?"),
    ).
    AddInputOption(
      option.
        New("iterations", option.Required).
        SetDescription("How many times should the message be printed?").
        SetDefault("1"),
    ).
    Build()

  //
  // Next, use this in the command to print the message multiple times:
  //

  iterations, _ := strconv.Atoi(cmd.Input.Option("iterations"))

  for i := 0; i < iterations; i++ {
    cmd.PrintText(
      fmt.Sprintf("Hi %s!", cmd.Input.Argument("name")),
    )
  }
}

Now, when you run the command, you can optionally specify a --iterations flag:

# no --iterations provided, the default (1) is used
$ php bin/console app:greet John
 Hi John!

$ php bin/console app:greet John --iterations=5
 Hi John!
 Hi John!
 Hi John!
 Hi John!
 Hi John!


$ php bin/console app:greet John --iterations=5 --yell
$ php bin/console app:greet John --yell --iterations=5
$ php bin/console app:greet --yell --iterations=5 John

You can also declare a one-letter shortcut that you can call with a single dash, like -i:

cmd := go_console.
  NewScript().
  AddInputOption(
    option.
      New("iterations", option.Required).
      SetShortcut("i"),
  ).
  Build()

Note that to comply with the docopt standard, long options can specify their values after a white space or an = sign (e.g. --iterations 5 or --iterations=5), but short options can only use white spaces or no separation at all (e.g. -i 5 or -i5).

While it is possible to separate an option from its value with a white space, using this form leads to an ambiguity should the option appear before the command name. For example, php bin/console --iterations 5 app:greet Fabien is ambiguous; Go-console would interpret 5 as the command name. To avoid this situation, always place options after the command name, or avoid using a space to separate the option name from its value.


There are four option variants you can use:

option.List

This option accepts multiple values (e.g. --dir=/foo --dir=/bar);

argument.None

Do not accept input for this option (e.g. --yell). This is the default behavior of options;

argument.Required

This value is required (e.g. --iterations=5 or -i5), the option itself is still optional;

argument.Optional

This option may or may not have a value (e.g. --yell or --yell=loud).

You can combine IS_ARRAY with REQUIRED and OPTIONAL like this:

cmd := go_console.
  NewCli().
  AddInputOption(
    option.New("iterations", option.List | option.Required),
  ).
  Build()
Clone this wiki locally