Skip to content

Multi-word program name #41

Open
keleshev opened this Issue Jul 29, 2012 · 13 comments

7 participants

@keleshev
docopt member

There might be a need to allow multi-word program names as follows

Usage: python program.py [options]

or

Usage: python3 program.py [options]

or

Usage: python program.zip [options] 

Even something like:

Usage: python -v program.py [options]

or

Usage: python -m module [options]

There is no obvious way to do it right now in docopt. Any feedback is appreciated.

  • Is this needed?
  • If yes, what should API look like?
@shabbyrobe
docopt member

I think this is needed.

What about adding a parameter to docopt that gets run through python's "{yep}".format(**tokens) method in the extras function prior to output?

You could even add the version value to the tokens prior to doing the format:

"""
Thingy thing v{version}

Usage: {program} --this --that --the-other

  -h, --help  Help
  --quack     Escaped bracketage {{yep}}
"""
import docopt
if __name__ == "__main__":
    args = docopt.docopt(__doc__, version="1.2.3", 
        tokens={'program':'python -v %s' % __file__})

It would be trivial to implement the simplest case of key/value substitution in the PHP version (though not some of the more complex stuff that python's format method offers like nested attribute access and the like).

If this portability is a concern, you could do something like this instead of a format():

for token, sub in {'{'+k+'}': v for k, v in tokens.items()}.items():
    doc = doc.replace(token, sub)
@keleshev
docopt member
keleshev commented Aug 1, 2012

This proposition is sound; also with respect for python versions that don't support format(). But this breaks WYSIWYG, and gives very little in return.

You can now do docopt(__doc__.format(...)) so you proposition has redundant functionality (in addition to solving the issue).

@shabbyrobe
docopt member

If you don't like the idea of adding the extra layer of token substitution, what about just replacing {program}, like so:

"""
Thingy thing v1.2.3

Usage: {program} --this --that --the-other

  -h, --help  Help
"""
import docopt
if __name__ == "__main__":
    args = docopt.docopt(__doc__, program='python -v %s' % __file__)

I only added the extra token substitution because I thought "well, it's gotta do something like this in the code anyway, so why not open it up?". It's not essential.

If you want it to support multi-word program names like python -v program.py, it either has to be able to find where the program name ends and the docopt stuff begins (not really possible with python -v program.py --docopt --stuff --here, or substitute it in when the help is printed and no sooner so it doesn't get picked up by the parser. The proposed fix is targeted at the latter.

@keleshev
docopt member
keleshev commented Oct 8, 2012

Maybe something like:

"""Usage: python -v prog.py <this> <that>"""

print docopt(__doc__, program='python -v prog.py')

WYSIWYG, but not DRY

@EvanED
EvanED commented Oct 24, 2012

I'm just skimming through some issues... what about making it possible to delimit the "program" with {...} or something like that:

"""Usage: {python -v prog.py} <this> <that>"""

print docopt(__doc__)

It's DRY and almost WYSIWYG...

@encukou
encukou commented Nov 30, 2012

Or:

"""Usage: python -v prog.py <this> <that>"""

print docopt(__doc__, program='prog.py')

WYSIWYG and almost DRY

@keleshev
docopt member
keleshev commented Apr 8, 2013

The following is most appealing to me.

"""Usage: python -v prog.py <this> <that>"""

print docopt(__doc__, program='python -v prog.py')

But I close this, because it doesn't seem that anyone missed that in 40 years.

@keleshev keleshev closed this Apr 8, 2013
@njsmith
njsmith commented Mar 23, 2014

Oh, too bad, I was just trying to figure out if I could switch to docopt for a project but this rules it out :-/

(I'm using the python -mfoo system to easily distribute a bunch of small ad hoc utilities along with my package.)

@keleshev keleshev reopened this Feb 24, 2015
@keleshev
docopt member

Ok, after some thought and #262 I'm reconsidering this. One reason is that I'm working on a PEG grammar for docopt, and program name could not really be parsed with PEG without knowing it in advance. It could be extracted with a regex, but providing it as program= smoothes it out (falling back to regex as a default).

@keleshev
docopt member

We just need to decide on the keyword name. program? POSIX calls that utility_name, so maybe that?

@voieducode
docopt member
@Darthfett

Without this problem fixed, it limits the ability to use docopt for samples that run with your library.

For example:

GenLib
    __init__.py
    genlib/
        __init__.py
        genlib.py
    samples/
        __init__.py
        S1/
            __init__.py
            s1.py

And then s1.py:

"""Sample 1 for Generic Library

Usage: python -m GenLib.samples.S1.s1

"""

from docopt import docopt
from ... import genlib

if __name__ == '__main__':
    args = docopt(__doc__)

And then making the call like in the usage:

$ python -m GenLib.samples.S1.s1

This fails and docopt prints the usage information.

@keleshev
docopt member

@Darthfett if you or someone else can submit a pull-request, I'll merge it. Hint: you need to change how formal_usage function converts "usage: prog foo bar prog baz" into "( foo bar ) | ( baz )":

https://github.com/docopt/docopt/blob/463d780a698cbacb1cf5590ae849b8f890baf25d/docopt.py#L470

Another hit: base your work on 0.6.x branch, not master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.