A command-line arguments parser that will make you smile.

docopt-go

Build Status Coverage Status GoDoc

An implementation of docopt in the Go programming language.

docopt helps you create beautiful command-line interfaces easily:

package main

import (
	"fmt"
	"github.com/docopt/docopt-go"
)

func main() {
	  usage := `Naval Fate.

Usage:
  naval_fate ship new <name>...
  naval_fate ship <name> move <x> <y> [--speed=<kn>]
  naval_fate ship shoot <x> <y>
  naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  naval_fate -h | --help
  naval_fate --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.`

	  arguments, _ := docopt.ParseDoc(usage)
	  fmt.Println(arguments)
}

docopt parses command-line arguments based on a help message. Don't write parser code: a good help message already has all the necessary information in it.

Installation

Use the alias "docopt-go". To use docopt in your Go code:

import "github.com/docopt/docopt-go"

To install docopt in your $GOPATH:

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

API

Given a conventional command-line help message, docopt processes the arguments. See https://github.com/docopt/docopt#help-message-format for a description of the help message format.

This package exposes three different APIs, depending on the level of control required. The first, simplest way to parse your docopt usage is to just call:

docopt.ParseDoc(usage)

This will use os.Args[1:] as the argv slice, and use the default parser options. If you want to provide your own version string and args, then use:

docopt.ParseArgs(usage, argv, "1.2.3")

If the last parameter (version) is a non-empty string, it will be printed when --version is given in the argv slice. Finally, we can instantiate our own docopt.Parser which gives us control over how things like help messages are printed and whether to exit after displaying usage messages, etc.

parser := &docopt.Parser{
  HelpHandler: docopt.PrintHelpOnly,
  OptionsFirst: true,
}
opts, err := parser.ParseArgs(usage, argv, "")

In particular, setting your own custom HelpHandler function makes unit testing your own docs with example command line invocations much more enjoyable.

All three of these return a map of option names to the values parsed from argv, and an error or nil. You can get the values using the helpers, or just treat it as a regular map:

flag, _ := opts.Bool("--flag")
secs, _ := opts.Int("<seconds>")

Additionally, you can Bind these to a struct, assigning option values to the exported fields of that struct, all at once.

var config struct {
  Command string `docopt:"<cmd>"`
  Tries   int    `docopt:"-n"`
  Force   bool   // Gets the value of --force
}
opts.Bind(&config)

More documentation is available at godoc.org.

Unit Testing

Unit testing your own usage docs is recommended, so you can be sure that for a given command line invocation, the expected options are set. An example of how to do this is in the examples folder.

Tests

All tests from the Python version are implemented and passing at Travis CI. New language-agnostic tests have been added to test_golang.docopt.

To run tests for docopt-go, use go test.

Comments
  • protect real git binary by renaming examples

    protect real git binary by renaming examples

    Some example source files such as git.go share names with common command line utilities, such as the real git. This has the unfortunate consequence that users attempting to make use of docopt.go receive a fake git binary in $GOPATH/bin that can accidentally override the real git. Especially if the position of $GOPATH/bin in $PATH occurs before the directory of the real git binary appears in $PATH. This happens because the source files in the examples/ directory are automatically built and installed by the standard go tool, such as with go get github.com/docopt/docopt.go.

    Go users may wish to reposition $GOPATH/bin in their $PATH configuration, to ensure that non-Go binaries take precedence. This allows docopt.go to be used without conflicting with the regular git binary.

    However, for some users a configuration with $GOPATH/bin earlier in $PATH may actually be desirable, such as when overriding system binaries with custom binaries. That's okay, we can resolve this situation as well, by renaming the git.go source file to fakegit.go. This rename allows the real git binary to continue functioning with docopt.go installed, regardless of the user's choice of ordering in their $PATH.

    Some later commit could even exclude the example/ binaries from being installed to $GOPATH/bin, by refactoring the examples in terms of ..._test.go files, a common Go unit testing convention.

  • Refactor and API improvements

    Refactor and API improvements

    Hi there. I've been working on my own fork of this project for a while to clean up the API. I've reached a stage where I'm happy for my changes to be merged back in if you're interested in using them. You can see what's basically changed by reading the README: https://github.com/aviddiviner/docopt-go#api

    But I'll list the salient points here for your summary:

    • Instead of the previous single, all-purpose API exposed by this package, namely: Parse(doc string, argv []string, help bool, version string, optionsFirst bool, exit ...bool) (map[string]interface{}, error), I've added two simpler APIs, such as ParseDoc(doc string) (Opts, error), as well as a custom Parser that you can use.

    • I have left the Parse(...) function in place (using a new Parser under the hood), so there is no break in backward compatibility.

    • This configurable Parser was the reason I did this refactor; previously there was no way for me to unit test my own docopt docs (i.e. test some command line invocations and see that I was getting the correct options back). With the addition of the parser, you can control the usage printing / exit behaviour.

    • The new Opts type which is returned has some convenience methods for easy type conversion, so this code:

    opts, _ := Parse("Usage: foo <option>", nil, true, "", false, true)
    if opt, ok := opts["<option>"]; ok {
      if s, ok := opt.(string); ok {
        if val, err := strconv.Atoi(s); err != nil {
          ...
        }
      }
    }
    

    becomes this:

    opts, _ := ParseDoc("Usage: foo <option>")
    val, _ := opts.Int("<option>")
    

    while still being just a map[string]interface{} under the hood.

    • The examples in the examples/ folder are now tested as part of the build process. Some other small coverage improvements were made.

    And some other little fixes here and there. But mostly, it's about having a cleaner API, and being able to control the "exit and print usage" behaviour for testing.

    Take a look. I hope you like it, and would want to merge it back in! Let me know 😄

  • map[string]interface{} is cumbersome in Go

    map[string]interface{} is cumbersome in Go

    I know that in Python a dict works well. But in Go a map[string]interface{} is actually cumbersome as you have to cast the value to string or int. map[string]string would be better as it eliminates the casting, but still creates a lot of unnecessary Unmarshal work.

    I would suggest that docopt.go work more like Go's encoding packages (which uses reflect). Essentially something like this:

    type Options struct {
        Command string `docopt:"<command>"`
        Speed int `docopt:"--speed"`
        Duration time.Duration `docopt:"--duration"` // Use time.ParseDuration
        Custom CustomValue `docopt:"--custom"` // Uses type UnmarshalDocopt interface
        Map map[string]string `docopt:""` // Put the rest of the options here
        Other string // Ignore this because it doesn't have docopt: tag
    }
    
    var doc = `...` // Ussage/Options text here
    
    func main() {
        p := docopt.NewParser(doc, true, "App 2.0", false)
        var opt Options // can also be a map[string]string
        if err := p.Parse(&opt); err != nil {
            log.Fatal(err)
        }
    }
    

    This package does something similar to the above example, but all the options are specified in tags, which get really ...really... long. With this you simply specify the name in a tag as you would in the map.

    I would also consider it bad practice in Go to do an os.Exit inside of Parse/NewParser. The package user should have complete control over logging and exiting behavior inside their main. So I would suggest the above example look like this:

    func main() {
        p := docopt.NewParser(doc, false) // Removed two middle options
        var opt Options
        if err := p.Parse(&opt); err != nil {
            log.Fatal(err)
        }
        if opt.Version { // Added Version bool `docopt:"--version"` to Options
            println("App 2.0")
            return
        }
        if opt.Help { // Added Help bool `docopt:"--help"` to Options
            println(doc) // OR p.PrintHelp()
            return
        }
    }
    

    Another neat idea (and perhaps this should be in another issue) would be to have the ability to fill values from an ini file like this:

    type Options struct {
        Config string `docopt:"--config,ini"` // The "ini" flag tells docopt to read this string as a filename
        // ...
    }
    
  • Unwanted os.Exit()

    Unwanted os.Exit()

    Hi,

    I've just started a command line application that will act as an alternative for the 'man' command. One of the planned options is [--explain ]. For example,

    gman --explain "rsync -avF src dest"
    

    In the example above, I would like to use docopt to parse the rsync options. The problem is that docopt.Parse() may call os.Exit(). For this and other use cases, that is less than ideal. It would be nice to have a Parse method that did not call os.Exit(). Something like this would be great:

    func ParseContinue(doc string, argv []string, help bool, version string, optionsFirst bool) (map[string]interface{}, string, error) {
        args, output, err := parse(doc, argv, help, version, optionsFirst)
        return args, output, err
    }
    

    If I need to, of course, I can fork and add the method for my purpose, but I at least wanted to make you aware of the use case.

    FWIW, calling os.Exit() also prevents the call of any defer methods. I doubt that many people will call defer before parsing command line options, but it's another possible argument for such a method.

    Thanks.

  • Doesnt work with golang's way of defining arguments

    Doesnt work with golang's way of defining arguments

    If one uses docopt and at the same time uses a golang library like glog, due to the way these two parse, it difficult to even bring up a simple program.

  • Documentation needs to better explain how to handle the returned arguments

    Documentation needs to better explain how to handle the returned arguments

    ...especially since that part is the only thing golang specific.

    By chance I found this example that helped:

    https://github.com/docopt/docopt.go/blob/master/examples/type_assert/type_assert_example.go

    But it is not super clear nor easy to find

  • add Bind() API

    add Bind() API

    Currently, Parse() returns map[string]interface{}. It's inconvenience because it needs to do type assertion when using. So I added Bind() API in order to relieves its burden.

    Usage:

    var option struct {
        Command string `docopt:"<command>"`
        Verbose bool   `docopt:"--verbose"`
        Other   string
    }
    
    var usage = `...`
    
    func main() {
        args, _ := docopt.Parse(usage, nil, false, "", false)
        if err := docopt.Bind(&option, args); err != nil {
            log.Fatal(err)
        }
        fmt.Println(option)
    }
    

    Also this pull request is one solution of #4.

  • Add bad argument list to user error when possible

    Add bad argument list to user error when possible

    Addresses https://github.com/docopt/docopt.go/issues/37

    This allows Parse callers to emit the list of unexpected arguments in some common cases, e.g., extra arguments, out-of-order arguments.

  • allow newline after Usage / Options

    allow newline after Usage / Options

    it just outputs the help, no error or anything, kinda confusing, having them squished looks weird but that whitespace should be optional and left up to the author anyway. Same with leading/trailing whitespace, I'm not a fan of stdio that is shoved against the terminal edges so a tool forcing me to do that is a little meh

  • Not returning ints

    Not returning ints

    The documentation says "interface{} can be bool, int, string, []string.", implying (I guess?) that numeric arguments ought to be be an int in the arguments map. However, for options such as

      --scan-intv <s>  Repository scan interval, in seconds [default: 60]
    

    the "60" is returned as a string-typed interface{}.

  • Parsing errors

    Parsing errors

    Something not quite right here:

    $ taskcluster-proxy -h
    Usage: taskcluster-proxy [(-p|--port) <port>] [--client-id <clientId> --access-token <accessToken> [--certificate <certificate>]] ([-a|--all-scopes]|([-t|--task-id <taskId>] [-s|--scopes <scope>...]))
    $ taskcluster-proxy -p 4 --access-token 43434
    
    2018/03/01 19:44:01 {
      "--access-token": true,
      "--all-scopes": false,
      "--certificate": false,
      "--client-id": false,
      "--port": false,
      "--scopes": false,
      "--task-id": false,
      "-a": false,
      "-p": true,
      "-s": false,
      "-t": false,
      "\u003caccessToken\u003e": null,
      "\u003ccertificate\u003e": null,
      "\u003cclientId\u003e": "43434",
      "\u003cport\u003e": "4",
      "\u003cscope\u003e": [],
      "\u003ctaskId\u003e": null
    }
    

    As you see, the parsing should not succeed, since --access-token is specified without --client-id, yet the parsing succeeds, and assigns the access token to the <clientId> property.

  • Array values duplicated with OneOrMore options (...)

    Array values duplicated with OneOrMore options (...)

    The following usage

    Usage:
      %[1]s [-u <URL>...] (-D <DOMAINFILE> [-V <VOLUMEFILE> -p <STORAGEPOOL> --start])
      %[1]s [-u <URL>...] (-V <VOLUMEFILE> [-p <STORAGEPOOL>])
      %[1]s [-u <URL>...] (--domdata <DOMAINDATA> [--voldata <VOLUMEDATA> -p <STORAGEPOOL>] --start)
      %[1]s [-u <URL>...] (--voldata <VOLUMEDATA> [-p <STORAGEPOOL>])
      %[1]s [-u <URL>...] (-R <DOMAINNAME>)
    
    Options:
      -u, --url <URL>            server url [default: qemu:///system]
    *******
    

    with cli opts -u qemu+ssh://user@hostname/system -u test produces array with duplicated 2-nd value: [qemu+ssh://user@hostname/system test test test test test]

  • Adding ppc64le architecture support on travis-ci

    Adding ppc64le architecture support on travis-ci

    Hi, I had added ppc64le(Linux on Power) architecture support on travis-ci in the PR and looks like its been successfully added. Also job for go 1.4 on ppc64le architecture is excluded as the version is not supported. I believe it is ready for the final review and merge. The travis ci build logs can be verified from the link below. https://travis-ci.com/github/kishorkunal-raj/docopt.go/builds/191152052

    Reason behind running tests on ppc64le: This package is included in the ppc64le versions of RHEL and Ubuntu - this allows the top of tree to be tested continuously as it is for Intel, making it easier to catch any possible regressions on ppc64le before the distros begin their clones and builds. This reduces the work in integrating this package into future versions of RHEL/Ubuntu.

    Please have a look.

    Regards, Kishor Kunal Raj

  • Update to use `docopt.go` import which should be ok since Go 1.13

    Update to use `docopt.go` import which should be ok since Go 1.13

    Updated the repository to use github.com/docopt/docopt.go which since version Go 1.13 should work ok with Go modules (I know because other project I help maintain nats.go was one of the first projects ending with .go being able to use this approach without issues 😅 )

    Signed-off-by: Waldemar Quevedo [email protected]

  • boolean options don't seem to work

    boolean options don't seem to work

    Boolean options don't seem to work the way they should. Here is an example:

    package main
    
    import (
    	"fmt"
    	"github.com/docopt/docopt-go"
    )
    
    var usage string = `
    Mytest.
    
    Usage:
    	mytest [options]
    
    Options:
      --flag	a flag
    `
    
    func main() {
    	opts, _ := docopt.ParseDoc(usage)
    	flag, err := opts.Bool("--flag")
    	fmt.Println(flag)
    	fmt.Println(err)
    }
    
    $ go run mytest.go
    false
    key: "--flag" failed type conversion
    $ go run mytest.go --flag
    --flag requires argument
    Usage:
    	mytest [options]
    exit status 1
    $ go run mytest.go --flag=true
    false
    key: "--flag" failed type conversion
    $ go version
    go version go1.14.1 linux/amd64
    $ 
    
  • Parse docopt even if no args are passed

    Parse docopt even if no args are passed

    Hi. I am looking for a future to parse docopt even if no args were given for parser.

    Real use-case - I want to get all flags (by flag I mean all options a command can receive) and use them in autocomplete.

    Basically I need only keys from opts map[string]interface{} map of flags. I then filter them as I need.

    Example:

    doc = `Usage: somecli run [--debug] [--config=<config>] <app>
    Options:
      --debug                   Run app with debug
      --config=<config>         Run with a config file
      <app>                     An app to run
    `
    onlyFlage := true
    opts, err := docopt.ParseDoc(doc, onlyFlags)
    

    The values of flags doesn't matter in this case and can be default values (bool, empty string, nil, etc)

    I am ready to implement this feature if you are okay with an idea. Thanks!

go command line option parser

go-flags: a go library for parsing command line arguments This library provides similar functionality to the builtin flag library of go, but provides

Dec 22, 2022
Fully featured Go (golang) command line option parser with built-in auto-completion support.

go-getoptions Go option parser inspired on the flexibility of Perl’s GetOpt::Long. Table of Contents Quick overview Examples Simple script Program wit

Dec 14, 2022
A flexible command and option parser for Go

Writ Overview Writ is a flexible option parser with thorough test coverage. It's meant to be simple and "just work". Applications using writ look and

Dec 27, 2022
A Go library for implementing command-line interfaces.

Go CLI Library cli is a library for implementing powerful command-line interfaces in Go. cli is the library that powers the CLI for Packer, Serf, Cons

Jan 1, 2023
A command line tool that builds and (re)starts your web application everytime you save a Go or template fileA command line tool that builds and (re)starts your web application everytime you save a Go or template file

# Fresh Fresh is a command line tool that builds and (re)starts your web application everytime you save a Go or template file. If the web framework yo

Nov 22, 2021
argv - Go library to split command line string as arguments array using the bash syntax.

Argv Argv is a library for Go to split command line string into arguments array. Documentation Documentation can be found at Godoc Example func TestAr

Nov 19, 2022
A tool to enumerate all the command-line arguments used to start a Linux process written in Go.
A tool to enumerate all the command-line arguments used to start a Linux process written in Go.

ranwith A tool to enumerate all the command-line arguments used to start a Linux process written in Go. ranwith uses the Linux /proc directory to obta

Jun 30, 2022
Package osargs provides functions to parse command line arguments

osargs About Package osargs provides functions to parse command line arguments. It is published on https://github.com/vbsw/osargs and https://gitlab.c

May 8, 2022
Go cmd utility that prints its command line arguments using strings.Join

Results This is an exercise of the book The Go Programming Language, by Alan A. A. Donovan and Brian Kernighan. Comparison between different versions

Dec 18, 2021
To Make frp with no arguments and ini file ,which Conveniently in red teaming
To Make frp with no arguments and ini file ,which Conveniently in red teaming

frpBuilder To Make frp with no arguments ,which Conveniently in red teaming I will give a simple modified source code of frp and Builder(MFC C++) in t

Oct 25, 2022
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.

asciigraph Go package to make lightweight ASCII line graphs ╭┈╯. Installation go get github.com/guptarohit/asciigraph Usage Basic graph package main

Jan 1, 2023
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.

asciigraph Go package to make lightweight ASCII line graphs ╭┈╯. Installation go get github.com/guptarohit/asciigraph Usage Basic graph package main

Jan 8, 2023
This is a small tool designed to scrape one or more URLs given as command arguments.

HTTP-FETCH This is a small tool designed to scrape one or more URLs given as command arguments. Usage http-fetch [--metadata] ...URLs The output files

Nov 23, 2021
shops is a simple command-line tool written in Go that helps you simplify the way you manage configuration across a set of machines.

shops is a simple command-line tool written in Go that helps you simplify the way you manage configuration across a set of machines. shops is your configuration management tool of choice when Chef, Puppet, Ansible are all too complicated and all you really want to do is run a bunch of regular shell against a set of hosts.

Jul 5, 2021
An open-source GitLab command line tool bringing GitLab's cool features to your command line
An open-source GitLab command line tool bringing GitLab's cool features to your command line

GLab is an open source GitLab CLI tool bringing GitLab to your terminal next to where you are already working with git and your code without switching

Dec 30, 2022
A command line tool to prompt for a value to be included in another command line.

readval is a command line tool which is designed for one specific purpose—to prompt for a value to be included in another command line. readval prints

Dec 22, 2021
Golisp-wtf - A lisp interpreter (still just a parser) implementation in golang. You may yell "What the fuck!?.." when you see the shitty code.

R6RS Scheme Lisp dialect interpreter This is an implementation of a subset of R6RS Scheme Lisp dialect in golang. The work is still in progress. At th

Jan 7, 2022
Bofin - A command line tool that can be used by to make Weblink development more productive

Bofin A command line tool that can be used by to make Weblink development more p

Jan 13, 2022
A simple go program which checks if your websites are running and runs forever (stop it with ctrl+c). It takes two optional arguments, comma separated string with urls and an interval.

uptime A simple go program which checks if your websites are running and runs forever (stop it with ctrl+c). It takes two optional arguments: -interva

Dec 15, 2022
Go linter that warns about number of arguments in functions.

argslen linter Argslen is a linter that checks for long list of argument in functions. The default limit is 5 (maxArguments) and skip the test files (

Sep 17, 2022