Exploring Go Packages: Docopt

In this tutorial, we walk through basic concepts and help messages in Docopt. You’ll learn about a practical use case that you can code right now.

Jane Kozhevnikova
Level Up Coding

--

A picture of mine

› Shortly about Docopt

Docopt is a command-line interface description language. It has many implementations for different programming languages. In this tutorial, we’ll discuss the Go version: Docopt Go.

This library gives programmers the ability to describe a program interface with a well-structured help message.

› Before You Begin

Install Docopt on your computer with this command:

$ go get -u -v github.com/docopt/docopt.go

The -u flag instructs go get to use the network to update the named packages and their dependencies. By default, get uses the network to check out missing packages but does not use it to look for updates to existing packages.

The -v flag enables verbose progress and debug output.

See this resource to learn more about the go get command.

Import the library in your *.go file as follows:

import docopt “github.com/docopt/docopt-go”

› Writing Help Message

A help message (or usage message, or doc) is what users see when they

  • invoke a program,
  • type a flag like --hor -h,
  • type invalid arguments.

This message includes the name of the program, its usage, and options. If you use the command line, you are already familiar with help messages or usage messages. In Linux, you can usually type program --helpto get a list of acceptable arguments of the program.

In this tutorial, we write a help message for a program that outputs:

  • a list of random numbers of a specified count and range, or
  • a list of random letters of a specific count and language.

This is our usage message:

Let’s analyze a command, numbers, from the preceding message:

randx numbers --count <count> [--range <range>...]

  • randx — a name of the program,
  • numbers — a command,
  • --count— an option of the command,
  • <count> — a value of the option — count,
  • [--range <range>…] — an optional parameter which requires a value or several values,
  • [--verbose]— an optional flag.

We have two commands, numbers and letters (bool), to enable the numbers or letters mode, respectively. If one of them is true, another is false.

The — count(int) option is required for both the numbers andletters commands. The program outputs a list of numbers or letters of the specified count.

$ randx numbers --count 1

$ randx letters --count 1

To declare an optional argument --range([]string), we use square brackets. Three dots in the square brackets mean that you can pass several arguments to the command prompt. For example,

- — range 1,10 --range 1,11 or
--range 1-10 --range 1-11 or
--range 1:10 --range 1:11

This option sets a range of random numbers. If there are two arguments, the program outputs two lists with the specified ranges.

The optional argument, --lang (string), is also in square brackets. The option accepts a language. Therefore the program outputs letters of the specified language.

The program must return a help message when the required option is not set and/or the arguments are invalid. Both --range and --lang options can be omitted.

Also, we have three options (or just flags) without operands in the usage message:

  • -h / --help — output the usage message,
  • --verboseoutput the details of what a program does; the flag is used to inform a user what the program actually does, including errors while performing a required action. This can be helpful for troubleshooting problems.
  • --version — output the version of the program which you use.

› Writing Code

Docopt can parse all your command-line arguments in a struct. To achieve this, create a new struct, call it config, and define all the fields according to the doc discussed earlier:

In this struct, we specify every command, flag, and option. If you want to declare both short and long option names, type
docopt:"-short_name,--long_name". For example: docopt:"-c,--count".

Declare your help message in the var() section:

Parse arguments with docopt.ParseArgs() method. The return value is a map with all the arguments. Then, bind the map to the given struct. We need to parse all arguments when the program initializes.

We specify the version of our program as the last parameter in the docopt.ParseArgs(usage, nil, "version_is_here")method. The program prints the version when the option --version is called.

To access a struct field, use a dot:

› Usage

In this section, you can find several cases of how to use Docopt in the command line.

›› Letters Mode

$ go run main.go letters --count 9 
$ go run main.go letters -c 9
letters: true
--count: 9
--lang:
--verbose: false
$ go run main.go letters --count 9 --lang en
$ go run main.go letters -c 9 -l en
letters: true
--count: 9
--lang: en
--verbose: false

›› Numbers Mode

$ go run main.go numbers --count 9 
$ go run main.go numbers -c 9
numbers: true
--count: 9
--range: []
--verbose: false
$ go run main.go numbers --count 10 --range 9,10
$ go run main.go numbers -c 10 -r 9,10
numbers: true
--count: 10
--range: [9,10]
--verbose: false
$ go run main.go numbers --count 10 --range 9,10 --range 0,15numbers: true
--count: 10
--range: [9,10 0,15]
--verbose: false

›› Verbose

$ go run main.go numbers --count 18 --range 9,19 --verbose 
$ go run main.go numbers -c 18 -r 9,19 --verbose
numbers: true
--count: 18
--range: [9,19]
--verbose: true

› About Author

Jane is a Go programmer and technical writer in software engineering. She has been writing technical material for 5 years in both English and Russian. She completed her specialist degree in Information Security from Novosibirsk State Technical University, and specializes in the information security of automated systems. You can follow her on Twitter and see her other written work at publications.enthusiastic.io.

--

--