.. -*- encoding: utf-8 -*-
.. -*- restructuredtext -*-


fancycompleter: colorful Python TAB completion
===============================================

What is is?
-----------

``fancycompleter`` is a module to improve your experience in Python by adding
TAB completion to the interactive prompt.  It is an extension of the stdlib's
rlcompleter_ module.

Its best feature is that the completions are displayed in different colors,
depending on their type:

.. image:: http://bitbucket.org/antocuni/fancycompleter/raw/5bf506e05ce7/screenshot.png

In the image above, strings are shown in green, functions in blue, integers
and boolean in yellows, ``None`` in gray, types and classes in
fuchsia. Everything else is plain white.

Other features
--------------

* To save space on screen, ``fancycompleter`` only shows the characters "after
  the dot".  By contrast, in the example above ``rlcompleter`` shows
  everything prepended by ``sys.``.

* If we press ``<TAB>`` at the beginning of the line, a real tab character is
  inserted, instead of trying to complete.  This is useful when typing
  function bodies or multi-line statements at the prompt.

* Unlike ``rlcompleter``, ``fancycompleter`` **does** complete expressions
  containing dictionary or list indexing.  For example,
  ``mydict['foo'].<TAB>`` works (assuming that ``mydict`` is a dictionary and
  that it contains the key ``'foo'``, of course :-)).

* Starting from Python 2.6, is the completed name is a callable,
  ``rlcompleter`` automatically adds an open parenthesis ``(``.  This is
  annoying in case we do not want to really call it, so ``fancycompleter``
  disable this behaviour.

Installation
------------

First, install the module with ``pip`` or ``easy_install``::

    $ pip install fancycompleter

Then, at the Python interactive prompt::

    >>> import fancycompleter
    >>> fancycompleter.interact()
    >>>

If you want to enable it automatically, you can those lines to your startup
file (identified by the `PYTHONSTARTUP`_ environment variable).

**Note**: depending on your particular system, ``interact`` might need to play
dirty tricks in order to display colors, although everything should "just
works™".  In particular, the call to ``interact`` should be the last line in
the startup file, else the next lines might not be executed. See section `What
is really going on?`_ for details.

How do I get colors?
---------------------

If you are using PyPy_, you can stop reading now, as ``fancycompleter`` will
work out of the box.

By default, in CPython line input and TAB completion are handled by `GNU
readline`_ (at least on Linux).  However, ``readline`` explicitly strips
escape sequences from the completions, so completions with colors are not
displayed correctly.

There are two ways to solve it:

  * (suggested) don't use ``readline`` at all and rely on pyrepl_

  * use a patched version of ``readline`` to allow colors

By default, ``fancycompleter`` tries to use ``pyrepl`` if it finds it.
However, to get colors you need a very recent version: at the moment of
writing the latest official release is 0.8.1, but it's not recent enough, so
you need to install it from the `SVN repository`_.

I really want to use readline
------------------------------

This method is not really recommended, but if you really want, you can use use
a patched readline: you can find the patches in the ``misc/`` directory:

  * for `readline-5.2`_

  * for `readline-6.0`_

You can also try one of the following precompiled versions, which has been
tested on Ubuntu 10.10: remember to put them in a place where the linker can
find them, e.g. by setting ``LD_LIBRARY_PATH``:

  * readline-6.0 for `32-bit`_

  * readline-6.0 for `64-bit`_

Once it is installed, you should double-check that you can find it, e.g. by
running ``ldd`` on Python's ``readline.so`` module::

    $ ldd /usr/lib/python2.6/lib-dynload/readline.so | grep readline
            libreadline.so.6 => /home/antocuni/local/32/lib/libreadline.so.6 (0x00ee7000)

Finally, you need to force ``fancycompleter`` to use colors, since by default,
it uses colors only with ``pyrepl``: you can do it by placing a custom config
file in ``~/.fancycompleterrc.py``.  An example config file is `here`_ (remind
that you need to put a dot in front of the filename!).

.. _`readline-5.2`: http://bitbucket.org/antocuni/fancycompleter/src/tip/misc/readline-escape-5.2.patch
.. _`readline-6.0`: http://bitbucket.org/antocuni/fancycompleter/src/tip/misc/readline-escape-6.0.patch
.. _`32-bit`: http://bitbucket.org/antocuni/fancycompleter/src/tip/misc/libreadline.so.6-32bit
.. _`64-bit`: http://bitbucket.org/antocuni/fancycompleter/src/tip/misc/libreadline.so.6-64bit
.. _here: http://bitbucket.org/antocuni/fancycompleter/src/tip/misc/fancycompleterrc.py


Customization
--------------

To customize the configuration of fancycompleter, you need to put a
file named ``.fancycompleterrc.py`` in your home directory.  The file must
contain a class named ``Config`` inheriting from ``DefaultConfig`` and
overridding the desired values.


What is really going on?
-------------------------

The default and preferred way to get colors is to use ``pyrepl``.  However,
there is no way to tell CPython to use ``pyrepl`` instead of the built-in
readline at the interactive prompt: this means that even if we install our
completer inside pyrepl's readline library, the interactive prompt won't see
it.

The issue is simply solved by avoiding to use the built-in prompt: instead, we
use a pure Python replacement based on `code.InteractiveConsole`_.  This
brings us also some niceties, such as the ability to do multi-line editing of
the history.

The console is automatically run by ``fancycompleter.interact()``, followed by
``sys.exit()``: this way, if we execute it from the script in
``PYTHONSTARTUP``, the interpreter exits as soon as we finish the use the
prompt (e.g. by pressing CTRL-D, or by calling ``quit()``).  This way, we
avoid to enter the built-in prompt and we get a behaviour which closely
resembles the default one.  This is why in this configuration lines after
``fancycompleter.interact()`` might not be run.

Note that if we are using ``readline`` instead of ``pyrepl``, the trick is not
needed and thus ``interact()`` will simply returns, letting the built-in
prompt to show up.  The same is true if we are running PyPy, as its built-in
prompt is based on pyrepl anyway.


.. _rlcompleter: http://docs.python.org/library/rlcompleter.html
.. _PYTHONSTARTUP: http://docs.python.org/using/cmdline.html#envvar-PYTHONSTARTUP
.. _PyPy: http://pypy.org
.. _`GNU readline`: http://tiswww.case.edu/php/chet/readline/rltop.html
.. _pyrepl: http://codespeak.net/pyrepl/
.. _`SVN repository`: http://codespeak.net/svn/pyrepl/trunk/pyrepl/
.. _`code.InteractiveConsole`: http://docs.python.org/library/code.html#code.InteractiveConsole
