Command completion simplified and working for list, dummies for other cmds.
authorW. Trevor King <wking@drexel.edu>
Thu, 27 Nov 2008 15:16:18 +0000 (10:16 -0500)
committerW. Trevor King <wking@drexel.edu>
Thu, 27 Nov 2008 15:16:18 +0000 (10:16 -0500)
All the other commands currently use default_complete(), which has no
effect other than catching the --complete option and effectively
aborting execution.

This closes 8e1bbda4-35b6-4579-849d-117b1596ee99

19 files changed:
.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/values
README.dev
becommands/assign.py
becommands/close.py
becommands/comment.py
becommands/diff.py
becommands/help.py
becommands/list.py
becommands/merge.py
becommands/new.py
becommands/open.py
becommands/remove.py
becommands/set.py
becommands/set_root.py
becommands/severity.py
becommands/show.py
becommands/status.py
becommands/target.py
libbe/cmdutil.py

index 162978549d34e0f4ff2e02f458f4382457c94306..f88ca6c05dcfa6d536e041b7b0ba0193cf77cb42 100644 (file)
@@ -15,7 +15,7 @@ severity=serious
 
 
 
-status=open
+status=fixed
 
 
 
index 4cbf554b3ea7146dbe69bd99a854702b4a38829c..837fac1c586df46ea219057323295716c0de60c0 100644 (file)
@@ -14,6 +14,10 @@ provide the following elements:
     The entry function for your plugin.  args is everything from
     sys.argv after the name of your plugin (e.g. for the command
     `be open abc', args=['abc']).
+
+    Note: be supports command-completion.  To avoid raising errors you
+    need to deal with possible '--complete' options and arguments.
+    See the 'Command completion' section below for more information.
   help()
      Return the string to be output by `be help <yourplugin>',
      `be <yourplugin> --help', etc.
@@ -27,8 +31,39 @@ consistent interface
 
 Again, you can just browse around in becommands to get a feel for things.
 
+Testing
+-------
+
 Run any doctests in your plugin with
   be$ python test.py <yourplugin>
 for example
   be$ python test.py merge
 
+
+Command completion
+------------------
+
+BE implements a general framework to make it easy to support command
+completion for arbitrary plugins.  In order to support this system,
+all becommands should properly handle the '--complete' commandline
+argument, returning a list of possible completions.  For example
+  $ be --commands
+      lists options accepted by be and the names of all available becommands.
+  $ be list --commands
+      lists options accepted by becommand/list
+  $ be list --status --commands
+      lists arguments accepted by the becommand/list --status option
+  $ be show -- --commands
+      lists possible vals for the first positional argument of becommand/show
+This is a lot of information, but command-line completion is really
+convenient for the user.  See becommand/list.py and becommand/show.py
+for example implementations.  The basic idea is to raise
+  cmdutil.GetCompletions(['list','of','possible','completions'])
+once you've determined what that list should be.
+
+However, command completion is not critcal.  The first priority is to
+implement the target functionality, with fancy shell sugar coming
+later.  In recognition of this, cmdutil provides the default_complete
+function which ensures that if '--complete' is any one of the
+arguments, options, or option-arguments, GetCompletions will be raised
+with and empty list.
index b00c5c23b4ea48e0bc6b0c45007781711a950bd8..98693509dc36c31cddbfe3a527ad754e1a83f8e0 100644 (file)
@@ -41,7 +41,9 @@ def execute(args, test=False):
     >>> bd.bug_from_shortname("a").assigned is None
     True
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     assert(len(args) in (0, 1, 2))
     if len(args) == 0:
         raise cmdutil.UsageError("Please specify a bug id.")
index d1253973d972258c0bac1b8ade08bc55a9b5fbd8..37fa032e57a3851eb03c4b3c8dfab4793e237eee 100644 (file)
@@ -31,7 +31,9 @@ def execute(args, test=False):
     >>> print bd.bug_from_shortname("a").status
     closed
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) == 0:
         raise cmdutil.UsageError("Please specify a bug id.")
     if len(args) > 1:
index 4470f75b4ad8e54c14409de4b0db0fab328d79da..5eac102f37ae3777a9fe45641fa1038200b1487c 100644 (file)
@@ -55,7 +55,9 @@ def execute(args, test=False):
     I like cheese
     <BLANKLINE>
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) == 0:
         raise cmdutil.UsageError("Please specify a bug or comment id.")
     if len(args) > 2:
index 169691341eddd93dc8158953fe816062cea3fe0a..c090fa886b15ad84e78ab8c9333cdcf563e434e2 100644 (file)
@@ -39,7 +39,9 @@ def execute(args, test=False):
       status: open -> closed
     <BLANKLINE>
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) == 0:
         revision = None
     if len(args) == 1:
index 1c99af57737faf3366528fb4b4127abd132c7373..e228eed4b29c9b719fe294c57bd3961911094a86 100644 (file)
@@ -26,11 +26,14 @@ def execute(args):
     <BLANKLINE>
     Options:
       -h, --help  Print a help message
+      --complete  Print a list of available completions
     <BLANKLINE>
     Print help for specified command or list of all commands.
     <BLANKLINE>
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) > 1:
         raise cmdutil.UsageError("Too many arguments.")
     if len(args) == 0:
index 25e72d3911e9097fc62bc28050918ae9bde09159..ff340e3ed2c7d18387cb17d31bfb928e8d69525b 100644 (file)
@@ -34,16 +34,7 @@ def execute(args, test=False):
     """
     parser = get_parser()
     options, args = parser.parse_args(args)
-    
-    for option in [o.dest for o in parser.option_list if o.dest != None]:
-        value = getattr(options, option)
-        if value == "--complete":
-            if option == "status":
-                raise cmdutil.GetCompletions(status_values)
-            raise cmdutil.GetCompletions()
-    if "--complete" in args:
-        raise cmdutil.GetCompletions() # no completions for arguments yet
-    
+    complete(options, args, parser)    
     if len(args) > 0:
         raise cmdutil.UsageError("Too many arguments.")
     
@@ -203,3 +194,14 @@ The boolean options are ignored if the matching string option is used.
 
 def help():
     return get_parser().help_str() + longhelp
+
+def complete(options, args, parser):
+    for option, value in cmdutil.option_value_pairs(options, parser):
+        if value == "--complete":
+            if option == "status":
+                raise cmdutil.GetCompletions(status_values)
+            elif option == "severity":
+                raise cmdutil.GetCompletions(severity_values)
+            raise cmdutil.GetCompletions()
+    if "--complete" in args:
+        raise cmdutil.GetCompletions() # no positional arguments for list
index d1829d66c67fa17dc142b63b0b561c8aac4d7d32..583bd285fd00b4c06e56bffac4270233f0472884 100644 (file)
@@ -120,7 +120,9 @@ def execute(args, test=False):
     >>> print b.status
     closed
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) < 2:
         raise cmdutil.UsageError("Please specify two bug ids.")
     if len(args) > 2:
index bc17f83b24a9154ebd06a3286d964fc0d8f7acf9..58fabbc9cb4f86f8c4860f49f7b509ba8cad5f52 100644 (file)
@@ -38,7 +38,9 @@ def execute(args, test=False):
     >>> bug.target == None
     True
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) != 1:
         raise cmdutil.UsageError("Please supply a summary message")
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 9a9667d6f6dda4144237041f244e32eca9703ab1..41db5e9ba8939a20f4c504506cfc08128ca3b48e 100644 (file)
@@ -30,7 +30,9 @@ def execute(args, test=False):
     >>> print bd.bug_from_shortname("b").status
     open
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) == 0:
         raise cmdutil.UsageError, "Please specify a bug id."
     if len(args) > 1:
index 386d9d41320970c023a32abc516ce2a7e2aa6968..cd877c559a26b035ea11bc22e7df3a857cdd1931 100644 (file)
@@ -35,7 +35,9 @@ def execute(args, test=False):
     ...     print "Bug not found"
     Bug not found
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) != 1:
         raise cmdutil.UsageError, "Please specify a bug id."
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 39042624ef3a119b826898e4b98f230902cb0490..aef5eb33aca40d9c46c695978c0bdb268c706cdd 100644 (file)
@@ -32,7 +32,9 @@ def execute(args, test=False):
     >>> execute(["target"], test=True)
     None
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) > 2:
         raise cmdutil.UsageError, "Too many arguments"
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 11f38b9e97b32b49f20e58bd457755ddbc6a3a9e..3749e287b5f4f6b203e3f45a8b18d2a54929dfa6 100644 (file)
@@ -55,7 +55,9 @@ def execute(args, test=False):
     UserError: No such directory: /highly-unlikely-to-exist
     >>> os.chdir('/')
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) > 1:
         raise cmdutil.UsageError
     if len(args) == 1:
index 3c856de54d96825b5b987af42923483025f3946f..29a55453d4b8b4437f4943d7d0fc48f7de546a6a 100644 (file)
@@ -33,7 +33,9 @@ def execute(args, test=False):
     Traceback (most recent call last):
     UserError: Invalid severity level: none
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) not in (1,2):
         raise cmdutil.UsageError
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index c58e6bb551a966daeecccc73c5ddb405e369c6aa..3c00712c3c4e19256ba353c456a9a7c9ac5d8449 100644 (file)
@@ -35,7 +35,9 @@ def execute(args, test=False):
     Bug A
     <BLANKLINE>
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) == 0:
         raise cmdutil.UsageError
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 73d43f85dacc2fd4a0918108eca336da9bbc227f..4ac71701c07c1210b042697daeb9bd74fd856b4a 100644 (file)
@@ -33,7 +33,9 @@ def execute(args, test=False):
     Traceback (most recent call last):
     UserError: Invalid status: none
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) not in (1,2):
         raise cmdutil.UsageError
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 4371ef0d6bf6d5f7519012fc8335450bc2103410..497ebf02b8a216c9f3a688ff671d0637b35fd75e 100644 (file)
@@ -32,7 +32,9 @@ def execute(args, test=False):
     >>> execute(["a"], test=True)
     No target assigned.
     """
-    options, args = get_parser().parse_args(args)
+    parser = get_parser()
+    options, args = parser.parse_args(args)
+    cmdutil.default_complete(options, args, parser)
     if len(args) not in (1, 2):
         raise cmdutil.UsageError
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
index 2bfe6d4d2fcc0b4b4b94b9ab8d4f04f7baed09a8..7f6e5ac6a3bef174b2b4abfaf3b9d5b4600d98bf 100644 (file)
@@ -86,7 +86,7 @@ def help(cmd=None):
             ret.append("be %s%*s    %s" % (name, numExtraSpaces, "", desc))
         return "\n".join(ret)
 
-def options(cmd):
+def completions(cmd):
     parser = get_command(cmd).get_parser()
     longopts = []
     for opt in parser.option_list:
@@ -97,7 +97,7 @@ def raise_get_help(option, opt, value, parser):
     raise GetHelp
 
 def raise_get_completions(option, opt, value, parser):
-    raise GetCompletions(options(sys.argv[1]))
+    raise GetCompletions(completions(sys.argv[1]))
 
 class CmdOptionParser(optparse.OptionParser):
     def __init__(self, usage):
@@ -121,6 +121,26 @@ class CmdOptionParser(optparse.OptionParser):
         self.print_help(f)
         return f.getvalue()
 
+def option_value_pairs(options, parser):
+    """
+    Iterate through OptionParser (option, value) pairs.
+    """
+    for option in [o.dest for o in parser.option_list if o.dest != None]:
+        value = getattr(options, option)
+        yield (option, value)
+
+def default_complete(options, args, parser):
+    """
+    A dud complete implementation for becommands to that the
+    --complete argument doesn't cause any problems.  Use this
+    until you've set up a command-specific complete function.
+    """
+    for option,value in option_value_pairs(options, parser):
+        if value == "--complete":
+            raise cmdutil.GetCompletions()
+    if "--complete" in args:
+        raise cmdutil.GetCompletions()
+
 def underlined(instring):
     """Produces a version of a string that is underlined with '='