@@ 9,10 9,10 @@ GOPT_A = [
]
-def cmd1():
+def cmd1(fn, **opts):
return 1
-def cmd2():
+def cmd2(**opts):
return 2
def cmd3():
@@ 112,7 112,7 @@ class TestCliCommands(unittest.TestCase)
@cmds.add('frob')
def frob(test):
return test
- @cmds.add('blipp', opts=[('check', 'c', None, 'be careful')])
+ @cmds.add(opts=[('check', 'c', None, 'be careful')])
def blipp(also):
return also + 1
@@ 125,6 125,25 @@ class TestCliCommands(unittest.TestCase)
self.assertEqual(cmd.target, blipp)
self.assertTrue(opts['check'])
+ def test_launching_command(self):
+ arguments = 'foo test.txt'.split()
+ result = commander.launch(GOPT_A, CMDTABLE_A, arguments)
+ self.assertEqual(result, 1)
+ arguments = 'bar'.split()
+ result = commander.launch(GOPT_A, CMDTABLE_A, arguments)
+ self.assertEqual(result, 2)
+
+ def test_help_wanted(self):
+ arguments = '-h foo'.split()
+ self.assertRaises(commander.HelpWanted,
+ commander.launch, GOPT_A, CMDTABLE_A, arguments)
+ arguments = 'foo -h'.split()
+ self.assertRaises(commander.HelpWanted,
+ commander.launch, GOPT_A, CMDTABLE_A, arguments)
+ arguments = 'help'.split()
+ self.assertRaises(commander.HelpWanted,
+ commander.launch, GOPT_A, CMDTABLE_A, arguments)
+
if __name__ == '__main__':
unittest.main()
@@ 18,6 18,7 @@ XXX
"""
from vanity import cli
+import sys
class InvalidCommand(cli.CliError):
@@ 33,7 34,15 @@ class AmbiguousCommand(cli.CliError):
self.matches = matches
-def launch(globalopts, cmdtable, arguments):
+class HelpWanted(cli.CliError):
+ """The user has requested help"""
+ def __init__(self, cmd, opts, args):
+ self.cmd = cmd
+ self.opts = opts
+ self.args = args
+
+
+def launch(globalopts, cmdtable, arguments, autohelp=True):
"""Launch a subcommand based on the given arguments, return the
result of the launched function.
@@ 41,7 50,19 @@ def launch(globalopts, cmdtable, argumen
* ``cmdtable`` - a commands table
* ``arguments`` - the command line arguments
"""
- pass
+ # inject help objects (if requested)
+ cmdtable = CommandTable(cmdtable)
+ globalopts = cli.OptionTable(globalopts)
+ if autohelp:
+ cmdtable._table[HELP.name] = HELP
+ globalopts._table[HELPOPT.name] = HELPOPT
+ # parse cli
+ cmd, opts, args = parse(globalopts, cmdtable, arguments)
+ # if help requested: raise HelpWanted
+ if cmd == HELP or opts.get('help'):
+ raise HelpWanted(cmd, opts, args)
+ # fire off the command
+ return cmd(opts, args)
def parse(globalopts, cmdtable, arguments):
@@ 166,100 187,25 @@ class CommandTable(object):
* ``opts`` - an options table; see vanity.cli for details
* ``help`` - a short command help string
"""
- if not name:
- name = func.__name__
if not opts:
opts = []
if not help:
help = '[OPTIONS] [ARGS]'
def _wrap(func):
- cmd = Command(name, func, aliases, opts, help)
+ if name:
+ _name = name
+ else:
+ _name = func.__name__
+ cmd = Command(_name, func, aliases, opts, help)
self._table[cmd.name] = cmd
return func
return _wrap
-'''
-
-
-def splitidents(idents):
- """Return a ident string as a list of idents.
- """
- return str(idents).split()
-
-class CommandTable(object):
- """Processes a table of commands and the global options.
- """
- def __init__(self, globalopts, commands):
- self._global = OptionTable(globalopts)
- self._table = {}
- for command in commands:
- self._addcommand(command)
-
- def _addcommand(self, command):
- func, idents, opts, desc = command
- for ident in splitidents(idents):
- self._table[ident] = (
- func,
- idents,
- OptionTable(opts),
- desc)
-
- def labels(self):
- return self._table.keys()
-
-
- def firstlabels(self):
- seen = []
- for key in self.labels():
- f, idents, opts, desc = self._table[key]
- idents = splitidents(idents)
- if idents[0] not in seen:
- seen.append(idents[0])
- return seen
-
+HELP = Command('help', None, None, [], 'display command help')
+HELPOPT = cli.Option('help', 'h', None, 'display command help')
- def opts(self):
- """Return the global options table
- """
- return self._global
-
- def find(self, label):
- """Given a command name or partial command name,
- return the closest full command name.
- If there are no matches a InvalidCommand exception is
- raised. If there are too many matches an AmbiguousCommand
- exception is raised.
- """
- matches = []
- for key in self._table.keys():
- if key.startswith(label):
- matches.append(key)
- if len(matches) == 1:
- return matches[0]
- if not matches:
- raise InvalidCommand(label)
- if label in self._table.keys():
- #exact match
- return label
- raise AmbiguousCommand(label, matches)
-
- def lookup(self, label):
- """Return the table entry given a full or partial
- command name.
- """
- key = self.find(label)
- return self._table[key]
-
- def get(self, label):
- """For a full or partial command name, return the
- function, it's identifiers, an options table containing
- both command and global options and the command
- description.
- """
- (func, id, options, desc) = self.lookup(label)
- options = self._global + options
- return (func, id, options, desc)
+'''
def parsecommand(opttable, cmdtable, arguments, getopts=None):