Files
whipper-gui/etc/bash_completion.d/bash-compgen.in
2013-02-03 14:29:42 +01:00

212 lines
6.2 KiB
Python
Executable File

#!@PYTHON@
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
# generate bash completion for all commands
# first argument should be program name
# second argument should be the main Command entry class's fully qualified name
import sys
def funcName(cmd):
"""
Generate a name for the given command by walking up the ancestry
and seperating with underscore.
"""
l = [cmd.name]
while cmd.parentCommand:
cmd = cmd.parentCommand
l.append(cmd.name)
l.reverse()
return "_%s_complete_" % cmd.name + "_".join(l)
def generateOneCommand(cmd):
function = funcName(cmd)
commandList = cmd.subCommands.keys()
commandList.sort()
commands = '"' + " ".join(commandList) + '"'
# poking into private instance variables for optparse.Option is nasty,
# but I see no alternative
optionBooleanList = []
optionValueList = []
optionList = []
for option in cmd.parser.option_list:
optionList.extend(option._short_opts + option._long_opts)
if not option.nargs:
optionBooleanList.extend(option._short_opts + option._long_opts)
else:
optionValueList.extend(option._short_opts + option._long_opts)
optionList.sort()
options = '"' + " ".join(optionList) + '"'
optionsBoolean = '"' + " ".join(optionBooleanList) + '"'
optionsValue = '"' + " ".join(optionValueList) + '"'
name = cmd.name
return """
%(function)s()
{
options=%(options)s
optionsboolean=%(optionsBoolean)s
optionsvalue=%(optionsValue)s
commands=%(commands)s
completed=false
debug "function %(function)s"
debug "args '$@'"
debug "ARG1 '$1'"
debug "ARG2 '$2'"
shift
debug "after shift: args '$@'"
debug "ARG1 '$1'"
debug "ARG2 '$2'"
while [[ "$completed" == "false" ]]
do
if [[ "$1" == -* ]]
then
# handle as argument
debug "handling argument $#"
# found will be set to true when the current argument fully matches
# an option, causing us to swallow it
found=false
# first check for boolean options
for option in $optionsboolean
do
debug "matching option $option to args $1"
if [[ "$option" == "$1" ]]
then
debug "found full boolean option $option, eating"
found=true
shift
fi
done
# then check for valued options
if [[ "$found" == false ]]
then
for option in $optionsvalue
do
debug "matching option $option to args $1"
if [[ "$option" == "$1" ]]
then
found=true
if [[ $# -eq 1 ]]
then
# a valued option with no value
# we can't complete this since we don't know what
# values the option takes
completed=true
COMPREPLY=()
else
# eat option and its value
shift 2
fi
fi
done
fi
if [[ "$found" == false ]]
then
debug "completing argument"
COMPREPLY=( $( compgen -W "$options" -- $1 ) )
debug "COMPREPLY ${COMPREPLY[*]}"
completed=true
fi
else
# handle as command
debug "handle as command"
found=false
if [[ $# -eq 0 ]]; then
# completing this command
COMPREPLY=( $( compgen -W "$commands" -- $1 ) )
debug "command, COMPREPLY ${COMPREPLY[*]}"
completed=true
else
for command in $commands
do
debug "matching arg $1 against command $command"
if [[ "$command" == "$1" ]]
then
debug "found full command, delegating"
# completing a subcommand, delegate
debug "delegate, $# args, 1 is $1"
%(function)s_$1 $@
debug "delegated, COMPREPLY ${COMPREPLY[*]}"
found=true
fi
done
# if not found, we must still be wanting to complete the
# current partial command
if [[ "$found" == false ]]
then
COMPREPLY=( $( compgen -W "$commands" -- $1 ) )
completed=true
fi
fi
fi
debug "function %(function)s: COMPREPLY ${COMPREPLY[*]}"
done
}
""" % locals()
def generateSubCommands(cmd):
snippets = []
if cmd.subCommands:
for subCommand in cmd.subCommands.values():
snippets.extend(generateSubCommands(subCommand))
snippets.append(generateOneCommand(cmd))
return snippets
def start():
if len(sys.argv) != 3:
sys.stderr.write('Usage: %s [program-name] [entry-class]\n')
sys.exit(1)
name = sys.argv[1]
entry = sys.argv[2]
parts = entry.split('.')
if len(parts) <= 1:
sys.stderr.write(
'The entry class should be a module-qualified Class.\n')
sys.exit(1)
module = ".".join(parts[:-1])
command = "from %s import %s as EntryClass" % (module, parts[-1])
exec command
entry = EntryClass()
print """#-*- mode: shell-script;-*-
# Programmed completion for bash to use %s
""" % name
print "\n".join(generateSubCommands(entry))
print """
# helper debug function
debug()
{
if [[ ! -z "$DEBUG" ]]
then
echo $@
fi
}
# main entry point
# dispatches to a command-specific function, passing in the rest of the
# command line as arguments, starting with the command name being called
_%(name)s()
{
COMPREPLY=()
# pass as a list, not as a single string
_%(name)s_complete_%(name)s ${COMP_WORDS[*]}
}
complete -F _%(name)s -o default %(name)s
""" % locals()
start()