Search code examples
pythondocopt

Option with two arguments with docopt


I want to have an option that takes two arguments. I.e. would like to be able to use

$ ./foo --path "old" "new"

Or what I really want is:

$ ./foo --path "old" "new" --path "old" "new"

But I don't know how to do it? (In fact I fear that it might not be possible...)


What I don't want, but which is close

I know how to have a repeating option (see below), but that is really not what I want here.

#!/usr/bin/env python3
'''foo

Usage:
  foo [--path ARG]...

Options:
  --path=ARG  Repeating option.
'''

import docopt

args = docopt.docopt(__doc__)

print(args)

Could be called with

$ ./foo --path "old" --path "new"

Solution

  • This can be easily archived with docopt.

    Syntax: Usage: ./foo [--path <src> <dst>]...

    Input: ./foo --path src1 dst1 --path src2 dst2

    Code:

    >>> from docopt import docopt
    >>> doc = "Usage: ./foo [--path <src> <dst>]..."
    >>> argv = "--path old1 new1 --path old2 new2".split()
    >>> args = docopt(doc, argv)
    

    Result:

    {
      "--path": 2, 
      "<dst>": [
        "dst1", 
        "dst2"
      ], 
      "<src>": [
        "src1", 
        "src2"
      ]
    }
    

    And now do something with it:

    >>> if bool(args["--path"]):
    >>>     n = 1 if args["--path"] is True else if args["--path"]
    >>>     for i in range(0, n)]:
    >>>         print("{}, {}".format(args["<old>"][i], args["<new>"][i]))
    src1, dst1
    src2, dst2
    

    To add a multiple positional arguments, require path option and arguments to be in the correct order with parens "( )".

    Usage: ./foo [(--path <src> <dst>)]... <arg>...
    

    Attention: docopt doesn't raise a SystemExit in case the user mixes up the syntax and inputs ./foo arg --path src dst if you use options with multiple arguments like that. You will have to handle it yourself or add another (sub)command in front of it.

    Usage: ./foo [(--path <src> <dst>)]... bar <arg>...