views:

430

answers:

4

What is the "cleanest" way to implement an command-line UI, similar to git's, for example:

git push origin/master
git remote add origin git://example.com master

Ideally also allowing the more flexible parsing, for example,

jump_to_folder app theappname v2
jump_to_folder app theappname source
jump_to_folder app theappname source v2
jump_to_folder app theappname build v1
jump_to_folder app theappname build 1
jump_to_folder app theappname v2 build

jump_to_folder is the scripts name, app is the command, theappname is a "fixed-location" parameter, "build" and "v2" etc are arguments (For example, possible arguments would be any number/any number prefixed with a v, or build/source/tmp/config)

I could just manually parse the arguments with a series of if/else/elifs, but there must be a more elegant way to do this?

As an entirely theoretically example, I could describe the UI schema..

app:
    fixed: application_name

    optional params:
        arg subsection:
            "build"
            "source"
            "tmp"
            "config"

        arg version:
            integer
            "v" + integer

Then parse the supplied arguments though the above schema, and get a dictionary:

>>> print schema.parse(["app", "theappname", "v1", "source"])
{
    "application_name": "theappname",
    "params":{
        "subsection": "source",
        "version":"v1"
    }
}

Does such a system exist? If not, how would I go about implementing something along these lines?

+2  A: 

Straight from one of my scripts:

import sys

def prog1_func1_act1(): print "pfa1"
def prog2_func2_act2(): print "pfa2"

commands = {
    "prog1 func1 act1": prog1_func1_act1,
    "prog2 func2 act2": prog2_func2_act2
}

try:
    commands[" ".join(sys.argv[1:])]()
except KeyError:
    print "Usage: ", commands.keys()

It's a pretty quick and dirty solution, but works great for my usage. If I were to clean it up a bit, I would probably add argparse to the mix for parsing positional and keyword arguments.

Mosor
The problem with this is the arguments are fixed.. For example, you couldn't easily have a "v001".."v102" option, short of creating a key for every combination..
dbr
Yes I know, and that's why I mentioned argparse. For example, if you have relatively few "commands" and "actions", but a lot of parameters, you can dispatch to specific action with the approach I use, and then pass parameters (and optional keyword arguments) to your script that uses argparse.
Mosor
plus, you can add a meta-command 'help' that prints out the contents of commands and shows their .__doc__ strings
pjz
also, the args aren't really fixed because the commands in the command list take all the args, so they can be parse in each command (and common parsings can be factored out). Or, if you mean that the command list is limited, consider overriding __getkey__ in a commands object.
pjz
+1  A: 

Python has a module for parsing command line options, optparse.

Egil
Unfortunatly it parses command line *options*, not *arguments* as dbr asks
Piotr Lesnicki
Exactly. It's best suited for "-f 2 -v -z 55" type arguments, as far as I can tell, unless I am missing something?
dbr
+5  A: 

The cmd module would probably work well for this.

Example:

import cmd

class Calc(cmd.Cmd):
    def do_add(self, arg):
        print sum(map(int, arg.split()))

if __name__ == '__main__':
    Calc().cmdloop()

Run it:

$python calc.py
(Cmd) add 4 5
9
(Cmd) help

Undocumented commands:
======================
add  help

(Cmd)

See the Python docs or PyMOTW site for more info.

davidavr
A: 

Here's my suggestion.

  1. Change your grammar slightly.

  2. Use optparse.

Ideally also allowing the more flexible parsing, for example,

jump_to_folder -n theappname -v2 cmd 
jump_to_folder -n theappname cmd source 
jump_to_folder -n theappname -v2 cmd source 
jump_to_folder -n theappname -v1 cmd build 
jump_to_folder -n theappname -1 cmd build 
jump_to_folder -n theappname -v2 cmd build

Then you have 1 or 2 args: the command is always the first arg. It's optional argument is always the second arg.

Everything else is options, in no particular order.

S.Lott