diff -r b758351d191f -r cc9b7e14412b web/lib/django/core/management/__init__.py --- a/web/lib/django/core/management/__init__.py Wed May 19 17:43:59 2010 +0200 +++ b/web/lib/django/core/management/__init__.py Tue May 25 02:43:45 2010 +0200 @@ -152,7 +152,7 @@ else: klass = load_command_class(app_name, name) except KeyError: - raise CommandError, "Unknown command: %r" % name + raise CommandError("Unknown command: %r" % name) # Grab out a list of defaults from the options. optparse does this for us # when the script runs from the command line, but since call_command can @@ -261,6 +261,82 @@ sys.exit(1) return klass + def autocomplete(self): + """ + Output completion suggestions for BASH. + + The output of this function is passed to BASH's `COMREPLY` variable and + treated as completion suggestions. `COMREPLY` expects a space + separated string as the result. + + The `COMP_WORDS` and `COMP_CWORD` BASH environment variables are used + to get information about the cli input. Please refer to the BASH + man-page for more information about this variables. + + Subcommand options are saved as pairs. A pair consists of + the long option string (e.g. '--exclude') and a boolean + value indicating if the option requires arguments. When printing to + stdout, a equal sign is appended to options which require arguments. + + Note: If debugging this function, it is recommended to write the debug + output in a separate file. Otherwise the debug output will be treated + and formatted as potential completion suggestions. + """ + # Don't complete if user hasn't sourced bash_completion file. + if not os.environ.has_key('DJANGO_AUTO_COMPLETE'): + return + + cwords = os.environ['COMP_WORDS'].split()[1:] + cword = int(os.environ['COMP_CWORD']) + + try: + curr = cwords[cword-1] + except IndexError: + curr = '' + + subcommands = get_commands().keys() + ['help'] + options = [('--help', None)] + + # subcommand + if cword == 1: + print ' '.join(sorted(filter(lambda x: x.startswith(curr), subcommands))) + # subcommand options + # special case: the 'help' subcommand has no options + elif cwords[0] in subcommands and cwords[0] != 'help': + subcommand_cls = self.fetch_command(cwords[0]) + # special case: 'runfcgi' stores additional options as + # 'key=value' pairs + if cwords[0] == 'runfcgi': + from django.core.servers.fastcgi import FASTCGI_OPTIONS + options += [(k, 1) for k in FASTCGI_OPTIONS] + # special case: add the names of installed apps to options + elif cwords[0] in ('dumpdata', 'reset', 'sql', 'sqlall', + 'sqlclear', 'sqlcustom', 'sqlindexes', + 'sqlreset', 'sqlsequencereset', 'test'): + try: + from django.conf import settings + # Get the last part of the dotted path as the app name. + options += [(a.split('.')[-1], 0) for a in settings.INSTALLED_APPS] + except ImportError: + # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The + # user will find out once they execute the command. + pass + options += [(s_opt.get_opt_string(), s_opt.nargs) for s_opt in + subcommand_cls.option_list] + # filter out previously specified options from available options + prev_opts = [x.split('=')[0] for x in cwords[1:cword-1]] + options = filter(lambda (x, v): x not in prev_opts, options) + + # filter options by current input + options = sorted([(k, v) for k, v in options if k.startswith(curr)]) + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1]: + opt_label += '=' + print opt_label + sys.exit(1) + def execute(self): """ Given the command-line arguments, this figures out which subcommand is @@ -272,6 +348,7 @@ parser = LaxOptionParser(usage="%prog subcommand [options] [args]", version=get_version(), option_list=BaseCommand.option_list) + self.autocomplete() try: options, args = parser.parse_args(self.argv) handle_default_options(options) @@ -281,8 +358,7 @@ try: subcommand = self.argv[1] except IndexError: - sys.stderr.write("Type '%s help' for usage.\n" % self.prog_name) - sys.exit(1) + subcommand = 'help' # Display help if no arguments were given. if subcommand == 'help': if len(args) > 2: