Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #10752. Added more advanced bash completion. Thanks, Arthur Koz…

…iel.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11526 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 677ddcbb04b85541f7b39b95541f5b46817ea510 1 parent a53601c
@jkocherhans jkocherhans authored
View
1  AUTHORS
@@ -241,6 +241,7 @@ answer newbie questions, and generally made Django that much better:
Igor Kolar <ike@email.si>
Gasper Koren
Martin Kosír <martin@martinkosir.net>
+ Arthur Koziel <http://arthurkoziel.com>
Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/>
krzysiek.pawlik@silvermedia.pl
View
77 django/core/management/__init__.py
@@ -261,6 +261,82 @@ def fetch_command(self, subcommand):
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(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 = [(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 @@ def execute(self):
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)
View
134 extras/django_bash_completion
@@ -31,136 +31,10 @@
#
# To uninstall, just remove the line from your .bash_profile and .bashrc.
-# Enable extended pattern matching operators.
-shopt -s extglob
-
_django_completion()
{
- local cur prev opts actions action_shell_opts action_runfcgi_opts
- COMPREPLY=()
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
-
- # Standalone options
- opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version --locale --domain"
- # Actions
- actions="createcachetable createsuperuser compilemessages \
- dbshell diffsettings dumpdata flush inspectdb loaddata \
- makemessages reset runfcgi runserver shell sql sqlall sqlclear \
- sqlcustom sqlflush sqlindexes sqlreset sqlsequencereset startapp \
- startproject syncdb test validate"
- # Action's options
- action_shell_opts="--plain"
- action_runfcgi_opts="host port socket method maxspare minspare maxchildren daemonize pidfile workdir"
-
- if [[ # django-admin.py, django-admin, ./manage, manage.py
- ( ${COMP_CWORD} -eq 1 &&
- ( ${COMP_WORDS[0]} == django-admin.py ||
- ${COMP_WORDS[0]} == django-admin ||
- ${COMP_WORDS[0]} == ./manage.py ||
- ${COMP_WORDS[0]} == manage.py ) )
- ||
- # python manage.py, /some/path/python manage.py (if manage.py exists)
- ( ${COMP_CWORD} -eq 2 &&
- ( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
- ( $( basename -- ${COMP_WORDS[1]} ) == manage.py) &&
- ( -r ${COMP_WORDS[1]} ) )
- ||
- ( ${COMP_CWORD} -eq 2 &&
- ( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
- ( $( basename -- ${COMP_WORDS[1]} ) == django-admin.py) &&
- ( -r ${COMP_WORDS[1]} ) )
- ||
- ( ${COMP_CWORD} -eq 2 &&
- ( $( basename -- ${COMP_WORDS[0]} ) == python?([1-9]\.[0-9]) ) &&
- ( $( basename -- ${COMP_WORDS[1]} ) == django-admin) &&
- ( -r ${COMP_WORDS[1]} ) ) ]] ; then
-
- case ${cur} in
- -*)
- COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
- action=$COMPREPLY
- return 0
- ;;
- *)
- COMPREPLY=( $(compgen -W "${actions}" -- ${cur}) )
- action=$COMPREPLY
- return 0
- ;;
- esac
- else
- case ${prev} in
- dumpdata|reset| \
- sql|sqlall|sqlclear|sqlcustom|sqlindexes| \
- sqlreset|sqlsequencereset|test)
- # App completion
- settings=""
- # If settings.py in the PWD, use that
- if [ -e settings.py ] ; then
- settings="$PWD/settings.py"
- else
- # Use the ENV variable if it is set
- if [ $DJANGO_SETTINGS_MODULE ] ; then
- settings=$DJANGO_SETTINGS_MODULE
- fi
- fi
- # Couldn't find settings so return nothing
- if [ -z $settings ] ; then
- COMPREPLY=()
- # Otherwise inspect settings.py file
- else
- apps=`sed -n "/INSTALLED_APPS = (/,/)/p" $settings | \
- grep -v "django.contrib" |
- sed -n "s/^[ ]*'\(.*\.\)*\(.*\)'.*$/\2 /pg" | \
- tr -d "\n"`
- COMPREPLY=( $(compgen -W "${apps}" -- ${cur}) )
- fi
- return 0
- ;;
-
- createcachetable|cleanup|compilemessages|dbshell| \
- diffsettings|inspectdb|makemessages| \
- runserver|startapp|startproject|syncdb| \
- validate)
- COMPREPLY=()
- return 0
- ;;
- shell)
- COMPREPLY=( $(compgen -W "$action_shell_opts" -- ${cur}) )
- return 0
- ;;
- runfcgi)
- COMPREPLY=( $(compgen -W "$action_runfcgi_opts" -- ${cur}) )
- return 0
- ;;
- host*|port*|socket*|method*|maxspare*|minspare*|maxchildren*|daemonize*|pidfile*|workdir*)
- if [ "$action" == "runfcgi" ] ; then
- COMPREPLY=( $(compgen -W "$action_runfcgi_opts" -- ${cur}) )
- return 0
- fi
- return 0
- ;;
- *)
- #COMPREPLY=( $(compgen -W "auth core" -- ${cur}) )
- COMPREPLY=()
- return 0
- ;;
- esac
- fi
+ COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \
+ COMP_CWORD=$COMP_CWORD \
+ DJANGO_AUTO_COMPLETE=1 $1 ) )
}
-
-complete -F _django_completion django-admin.py manage.py django-admin
-
-# Support for multiple interpreters.
-unset pythons
-if command -v whereis &>/dev/null; then
- python_interpreters=$(whereis python | cut -d " " -f 2-)
- for python in $python_interpreters; do
- pythons="${pythons} $(basename -- $python)"
- done
- pythons=$(echo $pythons | tr " " "\n" | sort -u | tr "\n" " ")
-else
- pythons=python
-fi
-
-complete -F _django_completion -o default $pythons
+complete -F _django_completion -o default django-admin.py manage.py

0 comments on commit 677ddcb

Please sign in to comment.
Something went wrong with that request. Please try again.