]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-102130: Support tab completion in cmd for Libedit. (GH-107748)
authorConstantin Hong <hongconstantin@gmail.com>
Tue, 5 Dec 2023 07:24:56 +0000 (16:24 +0900)
committerGitHub <noreply@github.com>
Tue, 5 Dec 2023 07:24:56 +0000 (08:24 +0100)
---

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Doc/library/cmd.rst
Lib/cmd.py
Lib/test/test_cmd.py
Misc/ACKS
Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst [new file with mode: 0644]

index fd5df96dfd0b3d692ddcadc3262fc79783425f54..1318ffe5a48d53de010cc92b39ae4c1adc590f97 100644 (file)
@@ -26,6 +26,13 @@ interface.
    key; it defaults to :kbd:`Tab`. If *completekey* is not :const:`None` and
    :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
    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
@@ -35,6 +42,9 @@ interface.
    :attr:`use_rawinput` attribute to ``False``, otherwise *stdin* will be
    ignored.
 
+   .. versionchanged:: 3.13
+      ``completekey='tab'`` is replaced by ``'^I'`` for ``editline``.
+
 
 .. _cmd-objects:
 
index e933b8dbc1470a8f51022e57475ea635407878a5..2e358d6cd5a02de775c1cbe58e2f6f7d6a6cdfe1 100644 (file)
@@ -108,7 +108,15 @@ class Cmd:
                 import readline
                 self.old_completer = readline.get_completer()
                 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:
                 pass
         try:
index 951336fa08542d22b5890a586707df2c9f7ef84f..46ec82b704963da65caa9d43fe09c8a399747963 100644 (file)
@@ -9,7 +9,10 @@ import sys
 import doctest
 import unittest
 import io
+import textwrap
 from test import support
+from test.support.import_helper import import_module
+from test.support.pty_helper import run_pty
 
 class samplecmdclass(cmd.Cmd):
     """
@@ -259,6 +262,33 @@ class CmdPrintExceptionClass(cmd.Cmd):
     def default(self, line):
         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):
     tests.addTest(doctest.DocTestSuite())
     return tests
index 1c67d96ed3a528d4be162d5f1efe0e8dbac9d6b5..12335c911ae42a536f37d6e182b3a25aa86c3cb7 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -788,6 +788,7 @@ Thomas Holmes
 Craig Holmquist
 Philip Homburg
 Naofumi Honda
+Constantin Hong
 Weipeng Hong
 Jeffrey Honig
 Rob Hooft
diff --git a/Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst b/Misc/NEWS.d/next/Library/2023-08-07-21-11-24.gh-issue-102130._UyI5i.rst
new file mode 100644 (file)
index 0000000..f582ad5
--- /dev/null
@@ -0,0 +1 @@
+Support tab completion in :mod:`cmd` for ``editline``.