]> granicus.if.org Git - python/commitdiff
Issue #5845: Enable tab-completion in the interactive interpreter by default, thanks...
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 4 May 2013 18:08:35 +0000 (20:08 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 4 May 2013 18:08:35 +0000 (20:08 +0200)
(original patch by Éric Araujo)

Doc/library/readline.rst
Doc/library/rlcompleter.rst
Doc/library/site.rst
Doc/library/sys.rst
Doc/tutorial/interactive.rst
Doc/using/cmdline.rst
Lib/site.py
Misc/NEWS
Modules/main.c

index 11346190c2a6ebeb2456523228ac922511b06323..692310b941dcaf815c7953510fd8bac0ec8c5181 100644 (file)
@@ -190,28 +190,32 @@ Example
 
 The following example demonstrates how to use the :mod:`readline` module's
 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
-normally be executed automatically during interactive sessions from the user's
-:envvar:`PYTHONSTARTUP` file. ::
+file named :file:`.python_history` from the user's home directory.  The code
+below would normally be executed automatically during interactive sessions
+from the user's :envvar:`PYTHONSTARTUP` file. ::
 
+   import atexit
    import os
    import readline
-   histfile = os.path.join(os.path.expanduser("~"), ".pyhist")
+
+   histfile = os.path.join(os.path.expanduser("~"), ".python_history")
    try:
        readline.read_history_file(histfile)
    except FileNotFoundError:
        pass
-   import atexit
+
    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
 support history save/restore. ::
 
-   import code
-   import readline
    import atexit
+   import code
    import os
+   import readline
 
    class HistoryConsole(code.InteractiveConsole):
        def __init__(self, locals=None, filename="<console>",
index 633088d897645f34bf1ccf48618c8e827a52fe07..9ed01c71468a5c80506987842c6e7d333f778e9f 100644 (file)
@@ -27,18 +27,10 @@ Example::
    readline.__name__         readline.parse_and_bind(
    >>> readline.
 
-The :mod:`rlcompleter` module is designed for use with Python's interactive
-mode.  A user can add the following lines to his or her initialization file
-(identified by the :envvar:`PYTHONSTARTUP` environment variable) to get
-automatic :kbd:`Tab` completion::
-
-   try:
-       import readline
-   except ImportError:
-       print("Module readline not available.")
-   else:
-       import rlcompleter
-       readline.parse_and_bind("tab: complete")
+The :mod:`rlcompleter` module is designed for use with Python's
+:ref:`interactive mode <tut-interactive>`.  Unless Python is run with the
+:option:`-S` option, the module is automatically imported and configured
+(see :ref:`rlcompleter-config`).
 
 On platforms without :mod:`readline`, the :class:`Completer` class defined by
 this module can still be used for custom purposes.
index 36b80c379cf7a575a96e229d08cefb84a3f1b8df..2175c3e2e74e569df3bd95ef2675dcd9eb2efbf6 100644 (file)
@@ -111,6 +111,23 @@ empty, and the path manipulations are skipped; however the import of
 :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
 
    A list of prefixes for site-packages directories.
@@ -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
    path.  This function is called automatically when this module is imported,
-   unless the :program:`python` interpreter was started with the :option:`-S`
-   flag.
+   unless the Python interpreter was started with the :option:`-S` flag.
 
    .. versionchanged:: 3.3
       This function used to be called unconditionnally.
index 5f8399f45d0cc2e74de2cc0fa1e48f57658bdbd3..a405a3065112331427f23015c3c07f6971fc46b4 100644 (file)
@@ -679,6 +679,16 @@ always available.
    .. 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)
 
    Enter *string* in the table of "interned" strings and return the interned string
index 36acb06d291f5faffb597c19cad9f3492a3cfec9..abf30f020dea0060e6fa5a4a7d31ae36e3351732 100644 (file)
@@ -7,140 +7,27 @@ Interactive Input Editing and History Substitution
 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
 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
-documentation which I won't duplicate here; however, the basics are easily
-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.
+which supports various styles of editing.  This library has its own
+documentation which we won't duplicate here.
 
 
 .. _tut-keybindings:
 
-Key Bindings
-============
-
-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
+Tab Completion and History Editing
+==================================
 
-   # Rebind some keys:
-   Meta-h: backward-kill-word
-   "\C-u": universal-argument
-   "\C-x\C-r": re-read-init-file
-
-Note that the default binding for :kbd:`Tab` in Python is to insert a :kbd:`Tab`
-character instead of Readline's default filename completion function.  If you
-insist, you can override this by putting ::
-
-   Tab: complete
-
-in your :file:`~/.inputrc`.  (Of course, this makes it harder to type indented
-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
+Completion of variable and module names is
+:ref:`automatically enabled <rlcompleter-config>` at interpreter startup so
+that the :kbd:`Tab` key invokes the completion function; 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.  The default configuration also saves your
+history into a file named :file:`.python_history` in your user directory.
+The history will be available again during the next interactive interpreter
+session.
 
 
 .. _tut-commentary:
@@ -162,14 +49,6 @@ into other applications.  Another similar enhanced interactive environment is
 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
 .. _IPython: http://ipython.scipy.org/
 .. _bpython: http://www.bpython-interpreter.org/
index 185852a84b014336e018dad506b25070d634c92c..fa01ea1e13c34d55aff7fd9f93b99c748437c115 100644 (file)
@@ -147,7 +147,12 @@ source.
 
 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
-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`
 
@@ -438,7 +443,7 @@ conflict.
    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
    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
index 9b1d5bb8ba793eba8230ed49404ca84ccb482b61..f13d4b4e4a616700086b34d731a93ba51803df20 100644 (file)
@@ -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
 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
 site-specific customizations.  If this import fails with an
 ImportError exception, it is silently ignored.
-
 """
 
 import sys
@@ -452,6 +455,40 @@ class _Helper(object):
 def sethelper():
     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():
     """On Windows, some default encodings are not provided by Python,
     while they are always available as "mbcs" in each locale. Make
@@ -571,6 +608,7 @@ def main():
     setquit()
     setcopyright()
     sethelper()
+    enablerlcompleter()
     aliasmbcs()
     execsitecustomize()
     if ENABLE_USER_SITE:
index 8d4c276b8adfdf16e4dae077a0e70427426f39c6..ec5ff6cfb785422b0813c11fc593a748030bdaff 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
 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
   __loader__ attributes to None.
 
@@ -63,8 +66,8 @@ Core and Builtins
 Library
 -------
 
- - Issue #15902: Fix imp.load_module() accepting None as a file when loading an
-   extension module.
+- Issue #15902: Fix imp.load_module() accepting None as a file when loading an
+  extension module.
 
 - Issue #13721: SSLSocket.getpeercert() and SSLSocket.do_handshake() now
   raise an OSError with ENOTCONN, instead of an AttributeError, when the
@@ -5001,6 +5004,9 @@ Library
 - Issue #11635: Don't use polling in worker threads and processes launched by
   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
   to match the path to where the source code currently is, not where the code
   object originally came from.
index 1d6c09a269533004dc0fb47d946233273f9d29df..2daefb871c343527a9e5a912ebf8994ad7973df5 100644 (file)
@@ -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)
 {
@@ -690,6 +716,7 @@ Py_Main(int argc, wchar_t **argv)
         if (filename == NULL && stdin_is_interactive) {
             Py_InspectFlag = 0; /* do exit on SystemExit */
             RunStartupFile(&cf);
+            RunInteractiveHook();
         }
         /* XXX */
 
@@ -755,6 +782,7 @@ Py_Main(int argc, wchar_t **argv)
     if (Py_InspectFlag && stdin_is_interactive &&
         (filename != NULL || command != NULL || module != NULL)) {
         Py_InspectFlag = 0;
+        RunInteractiveHook();
         /* XXX */
         sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
     }