summaryrefslogtreecommitdiff
path: root/cmd2
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2022-02-17 10:12:01 -0500
committerKevin Van Brunt <kmvanbrunt@gmail.com>2022-02-17 11:13:34 -0500
commit07f059c17b4cb6577fbc7a2ce42d7c5bf98a83c8 (patch)
tree0dfa541765f0844da16471936d753a138687ddb4 /cmd2
parentf217861feae45a0a1abb56436e68c5dd859d64c0 (diff)
downloadcmd2-git-07f059c17b4cb6577fbc7a2ce42d7c5bf98a83c8.tar.gz
Improved some readline-related comments
Diffstat (limited to 'cmd2')
-rw-r--r--cmd2/cmd2.py7
-rw-r--r--cmd2/rl_utils.py26
2 files changed, 25 insertions, 8 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 88e2492c..7fc2d4a3 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -3066,9 +3066,10 @@ class Cmd(cmd.Cmd):
# Set up readline for our tab completion needs
if rl_type == RlType.GNU:
- # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
- # We don't need to worry about setting rl_completion_suppress_quote since we never declared
- # rl_completer_quote_characters.
+ # GNU readline automatically adds a closing quote if the text being completed has an opening quote.
+ # We don't want this behavior since cmd2 only adds a closing quote when self.allow_closing_quote is True.
+ # To fix this behavior, set readline's rl_basic_quote_characters to NULL. We don't need to worry about setting
+ # rl_completion_suppress_quote since we never declared rl_completer_quote_characters.
readline_settings.basic_quotes = cast(bytes, ctypes.cast(rl_basic_quote_characters, ctypes.c_void_p).value)
rl_basic_quote_characters.value = None
diff --git a/cmd2/rl_utils.py b/cmd2/rl_utils.py
index d2a7c54b..cb73e836 100644
--- a/cmd2/rl_utils.py
+++ b/cmd2/rl_utils.py
@@ -10,13 +10,29 @@ from typing import (
Union,
)
-# Prefer statically linked gnureadline if available (for macOS compatibility due to issues with libedit)
+#########################################################################################################################
+# NOTE ON LIBEDIT:
+#
+# On Linux/Mac, the underlying readline API may be implemented by libedit instead of GNU readline.
+# We don't support libedit because it doesn't implement all the readline features cmd2 needs.
+#
+# For example:
+# cmd2 sets a custom display function using Python's readline.set_completion_display_matches_hook() to
+# support many of its advanced tab completion features (e.g. tab completion tables, displaying path basenames,
+# colored results, etc.). This function "sets or clears the rl_completion_display_matches_hook callback in the
+# underlying library". libedit has never implemented rl_completion_display_matches_hook. It merely sets it to NULL
+# and never references it.
+#
+# The workaround for Python environments using libedit is to install the gnureadline Python library.
+#########################################################################################################################
+
+# Prefer statically linked gnureadline if available due to issues with libedit
try:
# noinspection PyPackageRequirements
import gnureadline as readline # type: ignore[import]
except ImportError:
- # Try to import readline, but allow failure for convenience in Windows unit testing
- # Note: If this actually fails, you should install readline on Linux or Mac or pyreadline on Windows
+ # Try to import readline, but allow failure for convenience in Windows unit testing.
+ # Note: If this actually fails, you should install gnureadline on Linux/Mac or pyreadline on Windows.
try:
# noinspection PyUnresolvedReferences
import readline # type: ignore[no-redef]
@@ -125,7 +141,7 @@ if 'pyreadline' in sys.modules or 'pyreadline3' in sys.modules:
readline.remove_history_item = pyreadline_remove_history_item
elif 'gnureadline' in sys.modules or 'readline' in sys.modules:
- # We don't support libedit
+ # We don't support libedit. See top of this file for why.
if 'libedit' not in readline.__doc__:
try:
# Load the readline lib so we can access members of it
@@ -146,7 +162,7 @@ if rl_type == RlType.NONE: # pragma: no cover
if not _rl_warn_reason:
_rl_warn_reason = (
"no supported version of readline was found. To resolve this, install\n"
- "pyreadline on Windows or gnureadline on Mac."
+ "pyreadline on Windows or gnureadline on Linux/Mac."
)
rl_warning = "Readline features including tab completion have been disabled because\n" + _rl_warn_reason + '\n\n'
else: