Merge remote branch 'devel-2.1'
[ganeti-local] / autotools / build-bash-completion
index cb738cd..79258c2 100755 (executable)
 # 02110-1301, USA.
 
 
-import optparse
+"""Script to generate bash_completion script for Ganeti.
+
+"""
+
+# pylint: disable-msg=C0103
+# [C0103] Invalid name build-bash-completion
+
 import os
-import sys
 import re
 from cStringIO import StringIO
 
@@ -236,10 +241,20 @@ def WritePreamble(sw):
     sw.DecIndent()
   sw.Write("}")
 
+  # Params: <compgen options>
+  # Result variable: $COMPREPLY
+  sw.Write("_ganeti_compgen() {")
+  sw.IncIndent()
+  try:
+    sw.Write("""COMPREPLY=( $(compgen "$@") )""")
+    sw.Write("_ganeti_dbglog COMPREPLY=\"${COMPREPLY[@]}\"")
+  finally:
+    sw.DecIndent()
+  sw.Write("}")
+
 
 def WriteCompReply(sw, args, cur="\"$cur\""):
-  sw.Write("""COMPREPLY=( $(compgen %s -- %s) )""", args, cur)
-  sw.Write("_ganeti_dbglog COMPREPLY=\"${COMPREPLY[@]}\"")
+  sw.Write("_ganeti_compgen %s -- %s", args, cur)
   sw.Write("return")
 
 
@@ -253,6 +268,8 @@ class CompletionWriter:
     self.args = args
 
     for opt in opts:
+      # While documented, these variables aren't seen as public attributes by
+      # pylint. pylint: disable-msg=W0212
       opt.all_names = sorted(opt._short_opts + opt._long_opts)
 
   def _FindFirstArgument(self, sw):
@@ -295,6 +312,10 @@ class CompletionWriter:
       # Only static choices implemented so far (e.g. no node list)
       suggest = getattr(opt, "completion_suggest", None)
 
+      # our custom option type
+      if opt.type == "bool":
+        suggest = ["yes", "no"]
+
       if not suggest:
         suggest = opt.choices
 
@@ -441,6 +462,8 @@ class CompletionWriter:
           choices = "$(_ganeti_nodes)"
         elif isinstance(arg, cli.ArgJobId):
           choices = "$(_ganeti_jobs)"
+        elif isinstance(arg, cli.ArgOs):
+          choices = "$(_ganeti_os)"
         elif isinstance(arg, cli.ArgFile):
           choices = ""
           compgenargs.append("-f")
@@ -455,11 +478,11 @@ class CompletionWriter:
 
         if arg.min == 1 and arg.max == 1:
           cmpcode = """"$arg_idx" == %d""" % (last_arg_end)
+        elif arg.max is None:
+          cmpcode = """"$arg_idx" -ge %d""" % (last_arg_end)
         elif arg.min <= arg.max:
           cmpcode = (""""$arg_idx" -ge %d && "$arg_idx" -lt %d""" %
                      (last_arg_end, last_arg_end + arg.max))
-        elif arg.max is None:
-          cmpcode = """"$arg_idx" -ge %d""" % (last_arg_end)
         else:
           raise Exception("Unable to generate argument position condition")
 
@@ -477,7 +500,8 @@ class CompletionWriter:
             if choices:
               sw.Write("""choices="$choices "%s""", choices)
             if compgenargs:
-              sw.Write("compgenargs=%s", utils.ShellQuote(" ".join(compgenargs)))
+              sw.Write("compgenargs=%s",
+                       utils.ShellQuote(" ".join(compgenargs)))
           finally:
             sw.DecIndent()
 
@@ -580,7 +604,7 @@ def GetCommands(filename, module):
   """
   try:
     commands = getattr(module, "commands")
-  except AttributeError, err:
+  except AttributeError:
     raise Exception("Script %s doesn't have 'commands' attribute" %
                     filename)
 
@@ -591,6 +615,8 @@ def GetCommands(filename, module):
   for (_, _, optdef, _, _) in commands.itervalues():
     if help_option not in optdef:
       optdef.append(help_option)
+    if cli.DEBUG_OPT not in optdef:
+      optdef.append(cli.DEBUG_OPT)
 
   # Use aliases
   aliases = getattr(module, "aliases", {})