Commit 1a6cb30a authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #5845: Enable tab-completion in the interactive interpreter by default,...

Issue #5845: Enable tab-completion in the interactive interpreter by default, thanks to a new sys.__interactivehook__.

(original patch by Éric Araujo)
parent 4c14b5de
...@@ -190,28 +190,32 @@ Example ...@@ -190,28 +190,32 @@ Example
The following example demonstrates how to use the :mod:`readline` module's The following example demonstrates how to use the :mod:`readline` module's
history reading and writing functions to automatically load and save a history history reading and writing functions to automatically load and save a history
file named :file:`.pyhist` from the user's home directory. The code below would file named :file:`.python_history` from the user's home directory. The code
normally be executed automatically during interactive sessions from the user's below would normally be executed automatically during interactive sessions
:envvar:`PYTHONSTARTUP` file. :: from the user's :envvar:`PYTHONSTARTUP` file. ::
import atexit
import os import os
import readline import readline
histfile = os.path.join(os.path.expanduser("~"), ".pyhist")
histfile = os.path.join(os.path.expanduser("~"), ".python_history")
try: try:
readline.read_history_file(histfile) readline.read_history_file(histfile)
except FileNotFoundError: except FileNotFoundError:
pass pass
import atexit
atexit.register(readline.write_history_file, histfile) atexit.register(readline.write_history_file, histfile)
del os, histfile
This code is actually automatically run when Python is run in
:ref:`interactive mode <tut-interactive>` (see :ref:`rlcompleter-config`).
The following example extends the :class:`code.InteractiveConsole` class to The following example extends the :class:`code.InteractiveConsole` class to
support history save/restore. :: support history save/restore. ::
import code
import readline
import atexit import atexit
import code
import os import os
import readline
class HistoryConsole(code.InteractiveConsole): class HistoryConsole(code.InteractiveConsole):
def __init__(self, locals=None, filename="<console>", def __init__(self, locals=None, filename="<console>",
......
...@@ -27,18 +27,10 @@ Example:: ...@@ -27,18 +27,10 @@ Example::
readline.__name__ readline.parse_and_bind( readline.__name__ readline.parse_and_bind(
>>> readline. >>> readline.
The :mod:`rlcompleter` module is designed for use with Python's interactive The :mod:`rlcompleter` module is designed for use with Python's
mode. A user can add the following lines to his or her initialization file :ref:`interactive mode <tut-interactive>`. Unless Python is run with the
(identified by the :envvar:`PYTHONSTARTUP` environment variable) to get :option:`-S` option, the module is automatically imported and configured
automatic :kbd:`Tab` completion:: (see :ref:`rlcompleter-config`).
try:
import readline
except ImportError:
print("Module readline not available.")
else:
import rlcompleter
readline.parse_and_bind("tab: complete")
On platforms without :mod:`readline`, the :class:`Completer` class defined by On platforms without :mod:`readline`, the :class:`Completer` class defined by
this module can still be used for custom purposes. this module can still be used for custom purposes.
......
...@@ -111,6 +111,23 @@ empty, and the path manipulations are skipped; however the import of ...@@ -111,6 +111,23 @@ empty, and the path manipulations are skipped; however the import of
:mod:`sitecustomize` and :mod:`usercustomize` is still attempted. :mod:`sitecustomize` and :mod:`usercustomize` is still attempted.
.. _rlcompleter-config:
Readline configuration
----------------------
On systems that support :mod:`readline`, this module will also import and
configure the :mod:`rlcompleter` module, if Python is started in
:ref:`interactive mode <tut-interactive>` and without the :option:`-S` option.
The default behavior is enable tab-completion and to use
:file:`~/.python_history` as the history save file. To disable it, override
the :data:`sys.__interactivehook__` attribute in your :mod:`sitecustomize`
or :mod:`usercustomize` module or your :envvar:`PYTHONSTARTUP` file.
Module contents
---------------
.. data:: PREFIXES .. data:: PREFIXES
A list of prefixes for site-packages directories. A list of prefixes for site-packages directories.
...@@ -153,8 +170,7 @@ empty, and the path manipulations are skipped; however the import of ...@@ -153,8 +170,7 @@ empty, and the path manipulations are skipped; however the import of
Adds all the standard site-specific directories to the module search Adds all the standard site-specific directories to the module search
path. This function is called automatically when this module is imported, path. This function is called automatically when this module is imported,
unless the :program:`python` interpreter was started with the :option:`-S` unless the Python interpreter was started with the :option:`-S` flag.
flag.
.. versionchanged:: 3.3 .. versionchanged:: 3.3
This function used to be called unconditionnally. This function used to be called unconditionnally.
......
...@@ -679,6 +679,16 @@ always available. ...@@ -679,6 +679,16 @@ always available.
.. versionadded:: 3.1 .. versionadded:: 3.1
.. data:: __interactivehook__
When present, this function is automatically called (with no arguments)
when the interpreter is launched in :ref:`interactive mode <tut-interactive>`.
This is done after the :envvar:`PYTHONSTARTUP` file is read, so that you
can set this hook there.
.. versionadded:: 3.4
.. function:: intern(string) .. function:: intern(string)
Enter *string* in the table of "interned" strings and return the interned string Enter *string* in the table of "interned" strings and return the interned string
......
...@@ -7,140 +7,27 @@ Interactive Input Editing and History Substitution ...@@ -7,140 +7,27 @@ Interactive Input Editing and History Substitution
Some versions of the Python interpreter support editing of the current input Some versions of the Python interpreter support editing of the current input
line and history substitution, similar to facilities found in the Korn shell and line and history substitution, similar to facilities found in the Korn shell and
the GNU Bash shell. This is implemented using the `GNU Readline`_ library, the GNU Bash shell. This is implemented using the `GNU Readline`_ library,
which supports Emacs-style and vi-style editing. This library has its own which supports various styles of editing. This library has its own
documentation which I won't duplicate here; however, the basics are easily documentation which we won't duplicate here.
explained. The interactive editing and history described here are optionally
available in the Unix and Cygwin versions of the interpreter.
This chapter does *not* document the editing facilities of Mark Hammond's
PythonWin package or the Tk-based environment, IDLE, distributed with Python.
The command line history recall which operates within DOS boxes on NT and some
other DOS and Windows flavors is yet another beast.
.. _tut-lineediting:
Line Editing
============
If supported, input line editing is active whenever the interpreter prints a
primary or secondary prompt. The current line can be edited using the
conventional Emacs control characters. The most important of these are:
:kbd:`C-A` (Control-A) moves the cursor to the beginning of the line, :kbd:`C-E`
to the end, :kbd:`C-B` moves it one position to the left, :kbd:`C-F` to the
right. Backspace erases the character to the left of the cursor, :kbd:`C-D` the
character to its right. :kbd:`C-K` kills (erases) the rest of the line to the
right of the cursor, :kbd:`C-Y` yanks back the last killed string.
:kbd:`C-underscore` undoes the last change you made; it can be repeated for
cumulative effect.
.. _tut-history:
History Substitution
====================
History substitution works as follows. All non-empty input lines issued are
saved in a history buffer, and when a new prompt is given you are positioned on
a new line at the bottom of this buffer. :kbd:`C-P` moves one line up (back) in
the history buffer, :kbd:`C-N` moves one down. Any line in the history buffer
can be edited; an asterisk appears in front of the prompt to mark a line as
modified. Pressing the :kbd:`Return` key passes the current line to the
interpreter. :kbd:`C-R` starts an incremental reverse search; :kbd:`C-S` starts
a forward search.
.. _tut-keybindings: .. _tut-keybindings:
Key Bindings Tab Completion and History Editing
============ ==================================
The key bindings and some other parameters of the Readline library can be
customized by placing commands in an initialization file called
:file:`~/.inputrc`. Key bindings have the form ::
key-name: function-name
or ::
"string": function-name
and options can be set with ::
set option-name value
For example::
# I prefer vi-style editing:
set editing-mode vi
# Edit using a single line:
set horizontal-scroll-mode On
# Rebind some keys: Completion of variable and module names is
Meta-h: backward-kill-word :ref:`automatically enabled <rlcompleter-config>` at interpreter startup so
"\C-u": universal-argument that the :kbd:`Tab` key invokes the completion function; it looks at
"\C-x\C-r": re-read-init-file Python statement names, the current local variables, and the available
module names. For dotted expressions such as ``string.a``, it will evaluate
Note that the default binding for :kbd:`Tab` in Python is to insert a :kbd:`Tab` the expression up to the final ``'.'`` and then suggest completions from
character instead of Readline's default filename completion function. If you the attributes of the resulting object. Note that this may execute
insist, you can override this by putting :: application-defined code if an object with a :meth:`__getattr__` method
is part of the expression. The default configuration also saves your
Tab: complete history into a file named :file:`.python_history` in your user directory.
The history will be available again during the next interactive interpreter
in your :file:`~/.inputrc`. (Of course, this makes it harder to type indented session.
continuation lines if you're accustomed to using :kbd:`Tab` for that purpose.)
.. index::
module: rlcompleter
module: readline
Automatic completion of variable and module names is optionally available. To
enable it in the interpreter's interactive mode, add the following to your
startup file: [#]_ ::
import rlcompleter, readline
readline.parse_and_bind('tab: complete')
This binds the :kbd:`Tab` key to the completion function, so hitting the
:kbd:`Tab` key twice suggests completions; it looks at Python statement names,
the current local variables, and the available module names. For dotted
expressions such as ``string.a``, it will evaluate the expression up to the
final ``'.'`` and then suggest completions from the attributes of the resulting
object. Note that this may execute application-defined code if an object with a
:meth:`__getattr__` method is part of the expression.
A more capable startup file might look like this example. Note that this
deletes the names it creates once they are no longer needed; this is done since
the startup file is executed in the same namespace as the interactive commands,
and removing the names avoids creating side effects in the interactive
environment. You may find it convenient to keep some of the imported modules,
such as :mod:`os`, which turn out to be needed in most sessions with the
interpreter. ::
# Add auto-completion and a stored history file of commands to your Python
# interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
# bound to the Esc key by default (you can change it - see readline docs).
#
# Store the file in ~/.pystartup, and set an environment variable to point
# to it: "export PYTHONSTARTUP=~/.pystartup" in bash.
import atexit
import os
import readline
import rlcompleter
historyPath = os.path.expanduser("~/.pyhistory")
def save_history(historyPath=historyPath):
import readline
readline.write_history_file(historyPath)
if os.path.exists(historyPath):
readline.read_history_file(historyPath)
atexit.register(save_history)
del os, atexit, readline, rlcompleter, save_history, historyPath
.. _tut-commentary: .. _tut-commentary:
...@@ -162,14 +49,6 @@ into other applications. Another similar enhanced interactive environment is ...@@ -162,14 +49,6 @@ into other applications. Another similar enhanced interactive environment is
bpython_. bpython_.
.. rubric:: Footnotes
.. [#] Python will execute the contents of a file identified by the
:envvar:`PYTHONSTARTUP` environment variable when you start an interactive
interpreter. To customize Python even for non-interactive mode, see
:ref:`tut-customize`.
.. _GNU Readline: http://tiswww.case.edu/php/chet/readline/rltop.html .. _GNU Readline: http://tiswww.case.edu/php/chet/readline/rltop.html
.. _IPython: http://ipython.scipy.org/ .. _IPython: http://ipython.scipy.org/
.. _bpython: http://www.bpython-interpreter.org/ .. _bpython: http://www.bpython-interpreter.org/
...@@ -147,7 +147,12 @@ source. ...@@ -147,7 +147,12 @@ source.
If no interface option is given, :option:`-i` is implied, ``sys.argv[0]`` is If no interface option is given, :option:`-i` is implied, ``sys.argv[0]`` is
an empty string (``""``) and the current directory will be added to the an empty string (``""``) and the current directory will be added to the
start of :data:`sys.path`. start of :data:`sys.path`. Also, tab-completion and history editing is
automatically enabled, if available on your platform (see
:ref:`rlcompleter-config`).
.. versionchanged:: 3.4
Automatic enabling of tab-completion and history editing.
.. seealso:: :ref:`tut-invoking` .. seealso:: :ref:`tut-invoking`
...@@ -438,7 +443,7 @@ conflict. ...@@ -438,7 +443,7 @@ conflict.
is executed in the same namespace where interactive commands are executed so is executed in the same namespace where interactive commands are executed so
that objects defined or imported in it can be used without qualification in that objects defined or imported in it can be used without qualification in
the interactive session. You can also change the prompts :data:`sys.ps1` and the interactive session. You can also change the prompts :data:`sys.ps1` and
:data:`sys.ps2` in this file. :data:`sys.ps2` and the hook :data:`sys.__interactivehook__` in this file.
.. envvar:: PYTHONY2K .. envvar:: PYTHONY2K
......
...@@ -58,11 +58,14 @@ Note that bletch is omitted because it doesn't exist; bar precedes foo ...@@ -58,11 +58,14 @@ Note that bletch is omitted because it doesn't exist; bar precedes foo
because bar.pth comes alphabetically before foo.pth; and spam is because bar.pth comes alphabetically before foo.pth; and spam is
omitted because it is not mentioned in either path configuration file. omitted because it is not mentioned in either path configuration file.
After these path manipulations, an attempt is made to import a module The readline module is also automatically configured to enable
completion for systems that support it. This can be overriden in
sitecustomize, usercustomize or PYTHONSTARTUP.
After these operations, an attempt is made to import a module
named sitecustomize, which can perform arbitrary additional named sitecustomize, which can perform arbitrary additional
site-specific customizations. If this import fails with an site-specific customizations. If this import fails with an
ImportError exception, it is silently ignored. ImportError exception, it is silently ignored.
""" """
import sys import sys
...@@ -452,6 +455,40 @@ class _Helper(object): ...@@ -452,6 +455,40 @@ class _Helper(object):
def sethelper(): def sethelper():
builtins.help = _Helper() builtins.help = _Helper()
def enablerlcompleter():
"""Enable default readline configuration on interactive prompts, by
registering a sys.__interactivehook__.
If the readline module can be imported, the hook will set the Tab key
as completion key and register ~/.python_history as history file.
This can be overriden in the sitecustomize or usercustomize module,
or in a PYTHONSTARTUP file.
"""
def register_readline():
import atexit
try:
import readline
import rlcompleter
except ImportError:
return
# Reading the initialization (config) file may not be enough to set a
# completion key, so we set one first and then read the file
if 'libedit' in getattr(readline, '__doc__', ''):
readline.parse_and_bind('bind ^I rl_complete')
else:
readline.parse_and_bind('tab: complete')
readline.read_init_file()
history = os.path.join(os.path.expanduser('~'), '.python_history')
try:
readline.read_history_file(history)
except IOError:
pass
atexit.register(readline.write_history_file, history)
sys.__interactivehook__ = register_readline
def aliasmbcs(): def aliasmbcs():
"""On Windows, some default encodings are not provided by Python, """On Windows, some default encodings are not provided by Python,
while they are always available as "mbcs" in each locale. Make while they are always available as "mbcs" in each locale. Make
...@@ -571,6 +608,7 @@ def main(): ...@@ -571,6 +608,7 @@ def main():
setquit() setquit()
setcopyright() setcopyright()
sethelper() sethelper()
enablerlcompleter()
aliasmbcs() aliasmbcs()
execsitecustomize() execsitecustomize()
if ENABLE_USER_SITE: if ENABLE_USER_SITE:
......
...@@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1? ...@@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #5845: Enable tab-completion in the interactive interpreter by
default, thanks to a new sys.__interactivehook__.
- Issue #17115,17116: Module initialization now includes setting __package__ and - Issue #17115,17116: Module initialization now includes setting __package__ and
__loader__ attributes to None. __loader__ attributes to None.
...@@ -63,8 +66,8 @@ Core and Builtins ...@@ -63,8 +66,8 @@ Core and Builtins
Library Library
------- -------
- Issue #15902: Fix imp.load_module() accepting None as a file when loading an - Issue #15902: Fix imp.load_module() accepting None as a file when loading an
extension module. extension module.
- Issue #13721: SSLSocket.getpeercert() and SSLSocket.do_handshake() now - Issue #13721: SSLSocket.getpeercert() and SSLSocket.do_handshake() now
raise an OSError with ENOTCONN, instead of an AttributeError, when the raise an OSError with ENOTCONN, instead of an AttributeError, when the
...@@ -5001,6 +5004,9 @@ Library ...@@ -5001,6 +5004,9 @@ Library
- Issue #11635: Don't use polling in worker threads and processes launched by - Issue #11635: Don't use polling in worker threads and processes launched by
concurrent.futures. concurrent.futures.
- Issue #5845: Automatically read readline configuration to enable completion
in interactive mode.
- Issue #6811: Allow importlib to change a code object's co_filename attribute - Issue #6811: Allow importlib to change a code object's co_filename attribute
to match the path to where the source code currently is, not where the code to match the path to where the source code currently is, not where the code
object originally came from. object originally came from.
......
...@@ -160,6 +160,32 @@ static void RunStartupFile(PyCompilerFlags *cf) ...@@ -160,6 +160,32 @@ static void RunStartupFile(PyCompilerFlags *cf)
} }
} }
static void RunInteractiveHook(void)
{
PyObject *sys, *hook, *result;
sys = PyImport_ImportModule("sys");
if (sys == NULL)
goto error;
hook = PyObject_GetAttrString(sys, "__interactivehook__");
Py_DECREF(sys);
if (hook == NULL)
PyErr_Clear();
else {
result = PyObject_CallObject(hook, NULL);
Py_DECREF(hook);
if (result == NULL)
goto error;
else
Py_DECREF(result);
}
return;
error:
PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
PyErr_Print();
PyErr_Clear();
}
static int RunModule(wchar_t *modname, int set_argv0) static int RunModule(wchar_t *modname, int set_argv0)
{ {
...@@ -690,6 +716,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -690,6 +716,7 @@ Py_Main(int argc, wchar_t **argv)
if (filename == NULL && stdin_is_interactive) { if (filename == NULL && stdin_is_interactive) {
Py_InspectFlag = 0; /* do exit on SystemExit */ Py_InspectFlag = 0; /* do exit on SystemExit */
RunStartupFile(&cf); RunStartupFile(&cf);
RunInteractiveHook();
} }
/* XXX */ /* XXX */
...@@ -755,6 +782,7 @@ Py_Main(int argc, wchar_t **argv) ...@@ -755,6 +782,7 @@ Py_Main(int argc, wchar_t **argv)
if (Py_InspectFlag && stdin_is_interactive && if (Py_InspectFlag && stdin_is_interactive &&
(filename != NULL || command != NULL || module != NULL)) { (filename != NULL || command != NULL || module != NULL)) {
Py_InspectFlag = 0; Py_InspectFlag = 0;
RunInteractiveHook();
/* XXX */ /* XXX */
sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0; sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment