summaryrefslogtreecommitdiff
path: root/cmd2.py
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2018-04-28 01:11:43 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2018-04-28 01:11:43 -0400
commite906a0530f3e1cd898bdd6fa00904dd51fe8e144 (patch)
tree25cb5594e6f9405c120fc7ef16f73d637cfeac7d /cmd2.py
parent09e0fc0b37d0a16c845c18f9118dbb38250c2b5a (diff)
downloadcmd2-git-e906a0530f3e1cd898bdd6fa00904dd51fe8e144.tar.gz
Fixed issue where completion display function was overwritten when a submenu quits.
Fixed issue where submenus did not pass up all completion parameters to complete().
Diffstat (limited to 'cmd2.py')
-rwxr-xr-xcmd2.py67
1 files changed, 35 insertions, 32 deletions
diff --git a/cmd2.py b/cmd2.py
index 4c91a6a5..82f79ce2 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -164,10 +164,6 @@ elif 'gnureadline' in sys.modules or 'readline' in sys.modules:
import ctypes
readline_lib = ctypes.CDLL(readline.__file__)
- # Save address that rl_basic_quote_characters is pointing to since we need to override and restore it
- rl_basic_quote_characters = ctypes.c_char_p.in_dll(readline_lib, "rl_basic_quote_characters")
- orig_rl_basic_quote_characters_addr = ctypes.cast(rl_basic_quote_characters, ctypes.c_void_p).value
-
# BrokenPipeError and FileNotFoundError exist only in Python 3. Use IOError for Python 2.
if six.PY3:
@@ -889,11 +885,22 @@ class AddSubmenu(object):
try:
# copy over any shared attributes
self._copy_in_shared_attrs(_self)
+
+ # Reset the submenu's tab completion parameters
+ submenu.allow_appended_space = True
+ submenu.allow_closing_quote = True
+ submenu.display_matches = []
+
return _complete_from_cmd(submenu, text, line, begidx, endidx)
finally:
# copy back original attributes
self._copy_out_shared_attrs(_self, original_attributes)
+ # Pass the submenu's tab completion parameters back up to the menu that called complete()
+ _self.allow_appended_space = submenu.allow_appended_space
+ _self.allow_closing_quote = submenu.allow_closing_quote
+ _self.display_matches = copy.copy(submenu.display_matches)
+
original_do_help = cmd_obj.do_help
original_complete_help = cmd_obj.complete_help
@@ -1324,6 +1331,11 @@ class Cmd(cmd.Cmd):
self.allow_closing_quote = True
self.display_matches = []
+ if rl_type == RlType.GNU:
+ readline.set_completion_display_matches_hook(self._display_matches_gnu_readline)
+ elif rl_type == RlType.PYREADLINE:
+ readline.rl.mode._display_completions = self._display_matches_pyreadline
+
def tokens_for_completion(self, line, begidx, endidx):
"""
Used by tab completion functions to get all tokens through the one being completed
@@ -2699,38 +2711,33 @@ class Cmd(cmd.Cmd):
"""
# An almost perfect copy from Cmd; however, the pseudo_raw_input portion
# has been split out so that it can be called separately
- if self.use_rawinput and self.completekey:
+ if self.use_rawinput and self.completekey and rl_type != RlType.NONE:
# Set up readline for our tab completion needs
if rl_type == RlType.GNU:
- readline.set_completion_display_matches_hook(self._display_matches_gnu_readline)
-
# 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.
- rl_basic_quote_characters.value = None
+ basic_quote_characters = ctypes.c_char_p.in_dll(readline_lib, "rl_basic_quote_characters")
+ old_basic_quote_characters = ctypes.cast(basic_quote_characters, ctypes.c_void_p).value
+ basic_quote_characters.value = None
- elif rl_type == RlType.PYREADLINE:
- readline.rl.mode._display_completions = self._display_matches_pyreadline
+ old_completer = readline.get_completer()
+ old_delims = readline.get_completer_delims()
+ readline.set_completer(self.complete)
- try:
- self.old_completer = readline.get_completer()
- self.old_delims = readline.get_completer_delims()
- readline.set_completer(self.complete)
+ # Break words on whitespace and quotes when tab completing
+ completer_delims = " \t\n" + ''.join(QUOTES)
- # Break words on whitespace and quotes when tab completing
- completer_delims = " \t\n" + ''.join(QUOTES)
+ if self.allow_redirection:
+ # If redirection is allowed, then break words on those characters too
+ completer_delims += ''.join(REDIRECTION_CHARS)
- if self.allow_redirection:
- # If redirection is allowed, then break words on those characters too
- completer_delims += ''.join(REDIRECTION_CHARS)
+ readline.set_completer_delims(completer_delims)
- readline.set_completer_delims(completer_delims)
+ # Enable tab completion
+ readline.parse_and_bind(self.completekey + ": complete")
- # Enable tab completion
- readline.parse_and_bind(self.completekey + ": complete")
- except NameError:
- pass
stop = None
try:
while not stop:
@@ -2754,19 +2761,15 @@ class Cmd(cmd.Cmd):
# Run the command along with all associated pre and post hooks
stop = self.onecmd_plus_hooks(line)
finally:
- if self.use_rawinput and self.completekey:
+ if self.use_rawinput and self.completekey and rl_type != RlType.NONE:
# Restore what we changed in readline
- try:
- readline.set_completer(self.old_completer)
- readline.set_completer_delims(self.old_delims)
- except NameError:
- pass
+ readline.set_completer(old_completer)
+ readline.set_completer_delims(old_delims)
if rl_type == RlType.GNU:
readline.set_completion_display_matches_hook(None)
- rl_basic_quote_characters.value = orig_rl_basic_quote_characters_addr
-
+ basic_quote_characters.value = old_basic_quote_characters
elif rl_type == RlType.PYREADLINE:
readline.rl.mode._display_completions = orig_pyreadline_display