mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
gh-102130: Support tab completion in cmd for Libedit. (GH-107748)
--- Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
This commit is contained in:
parent
dc824c5dc1
commit
aa5bee30ab
5 changed files with 51 additions and 1 deletions
|
@ -26,6 +26,13 @@ interface.
|
||||||
key; it defaults to :kbd:`Tab`. If *completekey* is not :const:`None` and
|
key; it defaults to :kbd:`Tab`. If *completekey* is not :const:`None` and
|
||||||
:mod:`readline` is available, command completion is done automatically.
|
:mod:`readline` is available, command completion is done automatically.
|
||||||
|
|
||||||
|
The default, ``'tab'``, is treated specially, so that it refers to the
|
||||||
|
:kbd:`Tab` key on every :data:`readline.backend`.
|
||||||
|
Specifically, if :data:`readline.backend` is ``editline``,
|
||||||
|
``Cmd`` will use ``'^I'`` instead of ``'tab'``.
|
||||||
|
Note that other values are not treated this way, and might only work
|
||||||
|
with a specific backend.
|
||||||
|
|
||||||
The optional arguments *stdin* and *stdout* specify the input and output file
|
The optional arguments *stdin* and *stdout* specify the input and output file
|
||||||
objects that the Cmd instance or subclass instance will use for input and
|
objects that the Cmd instance or subclass instance will use for input and
|
||||||
output. If not specified, they will default to :data:`sys.stdin` and
|
output. If not specified, they will default to :data:`sys.stdin` and
|
||||||
|
@ -35,6 +42,9 @@ interface.
|
||||||
:attr:`use_rawinput` attribute to ``False``, otherwise *stdin* will be
|
:attr:`use_rawinput` attribute to ``False``, otherwise *stdin* will be
|
||||||
ignored.
|
ignored.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.13
|
||||||
|
``completekey='tab'`` is replaced by ``'^I'`` for ``editline``.
|
||||||
|
|
||||||
|
|
||||||
.. _cmd-objects:
|
.. _cmd-objects:
|
||||||
|
|
||||||
|
|
10
Lib/cmd.py
10
Lib/cmd.py
|
@ -108,7 +108,15 @@ class Cmd:
|
||||||
import readline
|
import readline
|
||||||
self.old_completer = readline.get_completer()
|
self.old_completer = readline.get_completer()
|
||||||
readline.set_completer(self.complete)
|
readline.set_completer(self.complete)
|
||||||
readline.parse_and_bind(self.completekey+": complete")
|
if readline.backend == "editline":
|
||||||
|
if self.completekey == 'tab':
|
||||||
|
# libedit uses "^I" instead of "tab"
|
||||||
|
command_string = "bind ^I rl_complete"
|
||||||
|
else:
|
||||||
|
command_string = f"bind {self.completekey} rl_complete"
|
||||||
|
else:
|
||||||
|
command_string = f"{self.completekey}: complete"
|
||||||
|
readline.parse_and_bind(command_string)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -9,7 +9,10 @@ import sys
|
||||||
import doctest
|
import doctest
|
||||||
import unittest
|
import unittest
|
||||||
import io
|
import io
|
||||||
|
import textwrap
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support.import_helper import import_module
|
||||||
|
from test.support.pty_helper import run_pty
|
||||||
|
|
||||||
class samplecmdclass(cmd.Cmd):
|
class samplecmdclass(cmd.Cmd):
|
||||||
"""
|
"""
|
||||||
|
@ -259,6 +262,33 @@ class CmdPrintExceptionClass(cmd.Cmd):
|
||||||
def default(self, line):
|
def default(self, line):
|
||||||
print(sys.exc_info()[:2])
|
print(sys.exc_info()[:2])
|
||||||
|
|
||||||
|
|
||||||
|
@support.requires_subprocess()
|
||||||
|
class CmdTestReadline(unittest.TestCase):
|
||||||
|
def setUpClass():
|
||||||
|
# Ensure that the readline module is loaded
|
||||||
|
# If this fails, the test is skipped because SkipTest will be raised
|
||||||
|
readline = import_module('readline')
|
||||||
|
|
||||||
|
def test_basic_completion(self):
|
||||||
|
script = textwrap.dedent("""
|
||||||
|
import cmd
|
||||||
|
class simplecmd(cmd.Cmd):
|
||||||
|
def do_tab_completion_test(self, args):
|
||||||
|
print('tab completion success')
|
||||||
|
return True
|
||||||
|
|
||||||
|
simplecmd().cmdloop()
|
||||||
|
""")
|
||||||
|
|
||||||
|
# 't' and complete 'ab_completion_test' to 'tab_completion_test'
|
||||||
|
input = b"t\t\n"
|
||||||
|
|
||||||
|
output = run_pty(script, input)
|
||||||
|
|
||||||
|
self.assertIn(b'ab_completion_test', output)
|
||||||
|
self.assertIn(b'tab completion success', output)
|
||||||
|
|
||||||
def load_tests(loader, tests, pattern):
|
def load_tests(loader, tests, pattern):
|
||||||
tests.addTest(doctest.DocTestSuite())
|
tests.addTest(doctest.DocTestSuite())
|
||||||
return tests
|
return tests
|
||||||
|
|
|
@ -788,6 +788,7 @@ Thomas Holmes
|
||||||
Craig Holmquist
|
Craig Holmquist
|
||||||
Philip Homburg
|
Philip Homburg
|
||||||
Naofumi Honda
|
Naofumi Honda
|
||||||
|
Constantin Hong
|
||||||
Weipeng Hong
|
Weipeng Hong
|
||||||
Jeffrey Honig
|
Jeffrey Honig
|
||||||
Rob Hooft
|
Rob Hooft
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Support tab completion in :mod:`cmd` for ``editline``.
|
Loading…
Add table
Add a link
Reference in a new issue