Basic bash completion is now supported.
authorW. Trevor King <wking@drexel.edu>
Thu, 27 Nov 2008 14:26:52 +0000 (09:26 -0500)
committerW. Trevor King <wking@drexel.edu>
Thu, 27 Nov 2008 14:26:52 +0000 (09:26 -0500)
I'm still working on a clean implementation though...

.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/body [new file with mode: 0644]
.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/values [new file with mode: 0644]
.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/body [new file with mode: 0644]
.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/values [new file with mode: 0644]
.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/values [new file with mode: 0644]
be
becommands/list.py
completion/be.bash [new file with mode: 0644]
libbe/cmdutil.py

diff --git a/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/body b/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/body
new file mode 100644 (file)
index 0000000..8d1ec26
--- /dev/null
@@ -0,0 +1 @@
+A rough implemention is now sketched out in becommands/list.py
diff --git a/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/values b/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/4d642e39-a8f3-41d8-93da-bea7e05ef9a6/values
new file mode 100644 (file)
index 0000000..39df7ff
--- /dev/null
@@ -0,0 +1,21 @@
+
+
+
+Content-type=text/plain
+
+
+
+
+
+
+Date=Thu, 27 Nov 2008 14:26:18 +0000
+
+
+
+
+
+
+From=W. Trevor King <wking@drexel.edu>
+
+
+
diff --git a/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/body b/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/body
new file mode 100644 (file)
index 0000000..bb443b8
--- /dev/null
@@ -0,0 +1,15 @@
+For example:
+  $ be list --status --options
+    File "/home/wking/bin/be", line 35, in <module>
+      sys.exit(cmdutil.execute(sys.argv[1], sys.argv[2:]))
+    File "/home/wking/lib/python2.5/site-packages/libbe/cmdutil.py", line 67, in execute
+      get_command(cmd).execute([a.decode(enc) for a in args])
+    File "/home/wking/lib/python2.5/site-packages/becommands/list.py", line 36, in execute
+      raise Exception, "parsed options"
+  Exception: parsed options
+
+The reason for this is that --status takes an argument, so 'be list'
+thinks it should list all the bugs with status == "--options".
+Ideally what should happen is that an argument-taking option would
+check for argument --options, and if so, would raise an exception
+returning a list of appropriate completions *for that argument*.
diff --git a/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/values b/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/comments/bf0c3752-6338-4919-93ba-4c9252945fb1/values
new file mode 100644 (file)
index 0000000..ea73789
--- /dev/null
@@ -0,0 +1,21 @@
+
+
+
+Content-type=text/plain
+
+
+
+
+
+
+Date=Thu, 27 Nov 2008 13:43:47 +0000
+
+
+
+
+
+
+From=W. Trevor King <wking@drexel.edu>
+
+
+
diff --git a/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/values b/.be/bugs/8e1bbda4-35b6-4579-849d-117b1596ee99/values
new file mode 100644 (file)
index 0000000..1629785
--- /dev/null
@@ -0,0 +1,35 @@
+
+
+
+creator=W. Trevor King <wking@drexel.edu>
+
+
+
+
+
+
+severity=serious
+
+
+
+
+
+
+status=open
+
+
+
+
+
+
+summary=be <cmmd> <argopt> --options doesn't raise GetOptions
+
+
+
+
+
+
+time=Thu, 27 Nov 2008 13:39:25 +0000
+
+
+
diff --git a/be b/be
index 2e038a5b6b038346215d5feb285215c17c4a3ec4..ab6ddeb944b3463d299c8b96e72374becf9d205e 100755 (executable)
--- a/be
+++ b/be
@@ -27,6 +27,8 @@ if len(sys.argv) == 1 or sys.argv[1] in ('--help', '-h'):
 elif sys.argv[1] == '--commands':
     for command, module in cmdutil.iter_commands():
         print command
+elif sys.argv[1] == '--options':
+    print '\n'.join(cmdutil.options())
 else:
     try:
         try:
@@ -36,6 +38,9 @@ else:
         except cmdutil.GetHelp:
             print cmdutil.help(sys.argv[1])
             sys.exit(0)
+        except cmdutil.GetCompletions, e:
+            print '\n'.join(e.completions)
+            sys.exit(0)
         except cmdutil.UsageError, e:
             print "Invalid usage:", e
             print "\nArgs:", sys.argv[1:]
index 5c0d326ed4835c99f2c124e6d06cc1c39736ee14..7c51f11d88ca7bed4e2dc5564889dfb01ef60e72 100644 (file)
@@ -32,9 +32,21 @@ def execute(args, test=False):
     a:om: Bug A
     b:cm: Bug B
     """
-    options, args = get_parser().parse_args(args)
+    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 == "--options":
+            if option == "status":
+                raise cmdutil.GetCompletions(status_values)
+            raise cmdutil.GetCompletions()
+    if "--options" in args:
+        raise cmdutil.GetCompletions() # no completions for arguments yet
+    
     if len(args) > 0:
         raise cmdutil.UsageError("Too many arguments.")
+    
     bd = bugdir.BugDir(from_disk=True, manipulate_encodings=not test)
     bd.load_all_bugs()
     # select status
diff --git a/completion/be.bash b/completion/be.bash
new file mode 100644 (file)
index 0000000..8789352
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Bash completion script for be (Bugs Everywhere)
+#
+# System wide installation:
+#   Copy this file to /etc/bash_completion/be
+# Per-user installation:
+#   Copy this file to ~/.be-completion.sh and source it in your .bashrc:
+#     source ~/.be-completion.sh
+# 
+# For a good intro to Bash completion, see Steve Kemp's article
+#   "An introduction to bash completion: part 2"
+#   http://www.debian-administration.org/articles/317
+
+# Support commands of the form:
+#   be <command> [<long option>] [<long option>] ...
+# Requires:
+#   be --commands
+#       to print a list of available commands
+#   be command [<option> ...] --options
+#       to print a list of available long options
+_be()
+{
+    local cur prev opts
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+    
+    if [ $COMP_CWORD -eq 1 ]; then
+       # no command yet, show all commands
+       COMPREPLY=( $( compgen -W "$(be --commands)" -- $cur ) )
+    else
+       # remove the first word (should be "be") for security reasons
+       unset COMP_WORDS[0]
+       # remove the current word and all later words, because they
+       # are not needed for completion.
+       for i in `seq $COMP_CWORD ${#COMP_WORDS[@]}`; do
+           unset COMP_WORDS[$i];
+       done
+       COMPREPLY=( $( compgen -W "$(be "${COMP_WORDS[@]}" --options)" -- $cur ) )
+    fi
+}
+
+complete -F _be be
index 1a321e9970b40eca201beee1dc56351e6189be40..aad6bbe7f9e812671a467607c987b6fe5b431f7e 100644 (file)
@@ -18,6 +18,7 @@ import optparse
 import os
 from textwrap import TextWrapper
 from StringIO import StringIO
+import sys
 import doctest
 
 import bugdir
@@ -34,12 +35,17 @@ class UserErrorWrap(UserError):
         UserError.__init__(self, str(exception))
         self.exception = exception
 
-class GetHelp(Exception):
+class UsageError(Exception):
     pass
 
-class UsageError(Exception):
+class GetHelp(Exception):
     pass
 
+class GetCompletions(Exception):
+    def __init__(self, completions=[]):
+        msg = "Get allowed completions"
+        Exception.__init__(self, msg)
+        self.completions = completions
 
 def iter_commands():
     for name, module in plugin.iter_plugins("becommands"):
@@ -80,15 +86,32 @@ def help(cmd=None):
             ret.append("be %s%*s    %s" % (name, numExtraSpaces, "", desc))
         return "\n".join(ret)
 
+def options(cmd=None):
+    if cmd != None:
+        parser = get_command(cmd).get_parser()
+        longopts = []
+        for opt in parser.option_list:
+            longopts.append(opt.get_opt_string())
+        return longopts
+    else:
+        # These probably shouldn't be hardcoded...
+        return ["--help","--commands","--options"]
+
 def raise_get_help(option, opt, value, parser):
     raise GetHelp
-        
+
+def raise_get_completions(option, opt, value, parser):
+    raise GetCompletions(options(sys.argv[1]))
+
 class CmdOptionParser(optparse.OptionParser):
     def __init__(self, usage):
         optparse.OptionParser.__init__(self, usage)
         self.remove_option("-h")
         self.add_option("-h", "--help", action="callback", 
                         callback=raise_get_help, help="Print a help message")
+        self.add_option("--options", action="callback",
+                        callback=raise_get_completions,
+                        help="Print a list of available long options")
 
     def error(self, message):
         raise UsageError(message)