v1.2

Atom Twitter Authors

A series of articles about upcoming releases of the Django web framework.

Improved Bash Completion

Arthur Koziel March 2nd 2010

Django 1.2 comes with an improved Bash completion script that enables tab completion for custom management commands and command options.

The main problem with the old Bash completion script was that the completions were hardcoded. This meant that only built-in management commands (like runserver or dumpdata) could be tab completed. Developers, however, commonly extend Django through custom management commands, which made the Bash completion script inconsistent. Tab completion worked for built-in management commands, but not for custom ones.

The Bash completion script in Django 1.2 changes that. Instead of a hardcoded list of completions, the Bash script was modified to call a Python function in Django. This function dynamically generates a list of possible completions based on the actual project settings. It will take into account the custom management commands from applications listed in the INSTALLED_APPS setting.

Installation

To get Django's Bash completion working, you'll first have to install the bash-completion package. It's a set of functions that enhances Bash's, otherwise very basic, programmable completion. You can install the package manually (check the "Installation" section of the projects README file) or through a package manager that is available on your operating system. MacPorts and all major Linux distributions have it available in their package repositories (it is usually called "bash-completion"). Ubuntu already ships with the package pre-installed.

Next up, you'll have to source the django_bash_completion file. It can be found in the extras directory of an SVN checkout.

source /path/to/django_bash_completion

If you installed Django through pip or easy_install, the extras directory will not be available. In that case, you'll need to manually download the file.

The script can be sourced automatically at every login by writing the command in the ~/.bash_profile file.

Usage

Once installed, Bash will generate completions for the django-admin.py, django-admin and manage.py commands. To trigger the completion you'll have to press the tab key twice after the respective command. For django-admin.py, the output should look like this:

$ django-admin.py <TAB><TAB>
cleanup           inspectdb         sqlall            startapp
compilemessages   loaddata          sqlclear          startproject
createcachetable  makemessages      sqlcustom         syncdb
dbshell           reset             sqlflush          test
diffsettings      runfcgi           sqlindexes        testserver
dumpdata          runserver         sqlinitialdata    validate
flush             shell             sqlreset
help              sql               sqlsequencereset

The same applies to the manage.py command of a project. Note that the manage.py file must be executable for this to work. If this isn't the case, you can run chmod u+x manage.py to make it executable.

$ ./manage.py <TAB><TAB>
changepassword    flush             shell             sqlreset
cleanup           help              sql               sqlsequencereset
compilemessages   inspectdb         sqlall            startapp
createcachetable  loaddata          sqlclear          syncdb
createsuperuser   makemessages      sqlcustom         test
dbshell           reset             sqlflush          testserver
diffsettings      runfcgi           sqlindexes        validate
dumpdata          runserver         sqlinitialdata

As you might've noticed, there's a small difference between the generated completions. The manage.py completion will take your project settings into account. In the above example, the changepassword and createsuperuser commands were added because of the installed django.contrib.auth application.

Another example is the django-extensions application, which adds some useful commands to your Django project. Once you've installed it and added 'django_extensions' to your INSTALLED_APPS setting, the Bash completion will include the new commands:

$ ./manage.py <TAB><TAB>
changepassword          help                    shell_plus
clean_pyc               inspectdb               show_urls
cleanup                 loaddata                sql
compile_pyc             mail_debug              sqlall
compilemessages         makemessages            sqlclear
create_app              passwd                  sqlcustom
create_command          print_user_for_session  sqldiff
create_jobs             reset                   sqlflush
createcachetable        reset_db                sqlindexes
createsuperuser         runfcgi                 sqlinitialdata
dbshell                 runjob                  sqlreset
describe_form           runjobs                 sqlsequencereset
diffsettings            runprofileserver        startapp
dumpdata                runscript               sync_media_s3
dumpscript              runserver               syncdata
export_emails           runserver_plus          syncdb
flush                   set_fake_emails         test
generate_secret_key     set_fake_passwords      testserver
graph_models            shell                   validate

Something that wasn't possible with the old completion script is option completion. You can press the tab key twice after a command to view all of it's options. For the runserver command, the output should look like this:

$ ./manage.py runserver <TAB><TAB>
--adminmedia=  --noreload     --settings=    --verbosity=
--help         --pythonpath=  --traceback

The equal sign after an option name indicates that a value must be specified.

When using the option completion you'll probably notice that a space character will be added after each completed word. This can be a little annoying for options that require a value, as you'll always have to press the backspace key to set the cursor to the correct position. Sadly, there's no solution for this. A Bash completion script is initialized with an option that either outputs a space character after each completed word, or doesn't. There's no backward compatible solution to change the option after the script was sourced. Even with the option disabled, you'd have to manually enter a space character after each completed word. Bash 4.0 fixed this by introducing a new 'compopt' builtin that allows completion functions to modify completion options dynamically. But since some operating systems ship with an old Bash version (yes, I'm looking at you Apple) this feature couldn't be used.

Tip: Enable single-tab completion

If you have the Readline library installed, you can tell Bash to display the list of possible completions by pressing the tab key once instead of twice. This makes the tab completion even more pleasant to use. To change it, write the following in your ~/.inputrc:

# enable single tab completion
set show-all-if-ambiguous on

End

I hope this article has helped you to set up and understand the Bash completion script for Django 1.2. Hopefully it'll save you some keystrokes in the future.