Skip to content

gh-102130: Support a tab completion for Libedit in cmd, site, and pdb. #107738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Doc/library/cmd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ command interpreters. These are often useful for test harnesses, administrative
tools, and prototypes that will later be wrapped in a more sophisticated
interface.

.. class:: Cmd(completekey='tab', stdin=None, stdout=None)
.. class:: Cmd(completekey=r'"\t"', stdin=None, stdout=None)

A :class:`Cmd` instance or subclass instance is a line-oriented interpreter
framework. There is no good reason to instantiate :class:`Cmd` itself; rather,
it's useful as a superclass of an interpreter class you define yourself in order
to inherit :class:`Cmd`'s methods and encapsulate action methods.

The optional argument *completekey* is the :mod:`readline` name of a completion
key; it defaults to :kbd:`Tab`. If *completekey* is not :const:`None` and
key; it defaults to "\\t"(:kbd:`tab`). If *completekey* is not :const:`None` and
:mod:`readline` is available, command completion is done automatically.

The optional arguments *stdin* and *stdout* specify the input and output file
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/pdb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ The ``run*`` functions and :func:`set_trace` are aliases for instantiating the
:class:`Pdb` class and calling the method of the same name. If you want to
access further features, you have to do this yourself:

.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \
.. class:: Pdb(completekey=r'"\t"', stdin=None, stdout=None, skip=None, \
nosigint=False, readrc=True)

:class:`Pdb` is the debugger class.
Expand Down
36 changes: 33 additions & 3 deletions Doc/library/readline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ made using this module affect the behaviour of both the interpreter's
interactive prompt and the prompts offered by the built-in :func:`input`
function.

Compatible keybindings
----------------------

To support compatible keybindings between GNU readline and Libedit, use the
following backslashed escape sequences or octal escape sequences in quotes. ::

\a bell
\b backspace
\f form feed
\n newline
\r carriage return
\t horizontal tab
\v vertical tab
\nnn octal escape sequences

Readline keybindings may be configured via an initialization file, typically
``.inputrc`` in your home directory. See `Readline Init File
<https://tiswww.cwru.edu/php/chet/readline/rluserman.html#Readline-Init-File>`_
Expand All @@ -39,10 +54,10 @@ Readline library in general.
If you use *editline*/``libedit`` readline emulation on macOS, the
initialization file located in your home directory is named
``.editrc``. For example, the following content in ``~/.editrc`` will
turn ON *vi* keybindings and TAB completion::
turn ON *vi* keybindings and "\\t"(:kbd:`tab`) completion::

python:bind -v
python:bind ^I rl_complete
python:bind "\t" rl_complete


Init file
Expand All @@ -56,6 +71,16 @@ The following functions relate to the init file and user configuration:
Execute the init line provided in the *string* argument. This calls
:c:func:`rl_parse_and_bind` in the underlying library.

.. note::
The syntax and command of *string* argument may be different depends on the readline library.

For GNU readline::

readline.parse_and_bind(r'"\t": complete')

For Libedit::

readline.parse_and_bind(r'bind "\t" rl_complete')

.. function:: read_init_file([filename])

Expand Down Expand Up @@ -348,7 +373,12 @@ support history save/restore. ::
self.init_history(histfile)

def init_history(self, histfile):
readline.parse_and_bind("tab: complete")

readline_doc = getattr(readline, '__doc__', '')
if readline_doc is not None and 'libedit' in readline_doc:
readline.parse_and_bind(r'bind "\t" rl_complete')
else:
readline.parse_and_bind(r'"\t": complete')
if hasattr(readline, "read_history_file"):
try:
readline.read_history_file(histfile)
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/rlcompleter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Example::

>>> import rlcompleter
>>> import readline
>>> readline.parse_and_bind("tab: complete")
>>> readline.parse_and_bind(r'"\t": complete')
>>> readline. <TAB PRESSED>
readline.__doc__ readline.get_line_buffer( readline.read_init_file(
readline.__file__ readline.insert_text( readline.set_completer(
Expand Down
8 changes: 6 additions & 2 deletions Lib/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Cmd:
nohelp = "*** No help on %s"
use_rawinput = 1

def __init__(self, completekey='tab', stdin=None, stdout=None):
def __init__(self, completekey='"\t"', stdin=None, stdout=None):
"""Instantiate a line-oriented interpreter framework.

The optional argument 'completekey' is the readline name of a
Expand Down Expand Up @@ -108,7 +108,11 @@ def cmdloop(self, intro=None):
import readline
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey+": complete")
readline_doc = getattr(readline, '__doc__', '')
if readline_doc is not None and 'libedit' in readline_doc:
readline.parse_and_bind("bind "+self.completekey+" rl_complete")
else:
readline.parse_and_bind(self.completekey+": complete")
except ImportError:
pass
try:
Expand Down
2 changes: 1 addition & 1 deletion Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):

_previous_sigint_handler = None

def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
def __init__(self, completekey=r'"\t"', stdin=None, stdout=None, skip=None,
nosigint=False, readrc=True):
bdb.Bdb.__init__(self, skip=skip)
cmd.Cmd.__init__(self, completekey, stdin, stdout)
Expand Down
4 changes: 2 additions & 2 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,9 +446,9 @@ def register_readline():
# completion key, so we set one first and then read the file.
readline_doc = getattr(readline, '__doc__', '')
if readline_doc is not None and 'libedit' in readline_doc:
readline.parse_and_bind('bind ^I rl_complete')
readline.parse_and_bind(r'bind "\t" rl_complete')
else:
readline.parse_and_bind('tab: complete')
readline.parse_and_bind(r'"\t": complete')

try:
readline.read_init_file()
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ Thomas Holmes
Craig Holmquist
Philip Homburg
Naofumi Honda
Constantin Hong
Weipeng Hong
Jeffrey Honig
Rob Hooft
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support a tab completion for Libedit in :mod:`cmd `, :mod:`site`, and :mod:`pdb`.