From baf08e35bf6d309db9251ae90c3c9f01cd825fe0 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Tue, 17 May 2016 23:52:33 -0400 Subject: [PATCH 1/5] add workaround for ctrl-c not quitting reverse-i-search in readline shell --- xonsh/readline_shell.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/xonsh/readline_shell.py b/xonsh/readline_shell.py index e0169788c..dbd997e0f 100644 --- a/xonsh/readline_shell.py +++ b/xonsh/readline_shell.py @@ -19,14 +19,15 @@ if HAVE_PYGMENTS: import pygments from pygments.formatters.terminal256 import Terminal256Formatter -RL_COMPLETION_SUPPRESS_APPEND = RL_LIB = None +RL_COMPLETION_SUPPRESS_APPEND = RL_LIB = RL_STATE = None RL_CAN_RESIZE = False RL_DONE = None - +_RL_STATE_DONE = 0x1000000 +_RL_STATE_ISEARCH = 0x0000080 def setup_readline(): """Sets up the readline module and completion suppression, if available.""" - global RL_COMPLETION_SUPPRESS_APPEND, RL_LIB, RL_CAN_RESIZE + global RL_COMPLETION_SUPPRESS_APPEND, RL_LIB, RL_CAN_RESIZE, RL_STATE if RL_COMPLETION_SUPPRESS_APPEND is not None: return try: @@ -44,6 +45,7 @@ def setup_readline(): except ValueError: # not all versions of readline have this symbol, ie Macs sometimes RL_COMPLETION_SUPPRESS_APPEND = None + RL_STATE = ctypes.c_int.in_dll(lib, 'rl_readline_state') RL_CAN_RESIZE = hasattr(lib, 'rl_reset_screen_size') env = builtins.__xonsh_env__ # reads in history @@ -71,6 +73,20 @@ def teardown_readline(): return +def fix_readline_state_after_ctrl_c(): + """ + Fix to allow Ctrl-C to exit reverse-i-search. + + Based on code from: + http://bugs.python.org/file39467/raw_input__workaround_demo.py + """ + if RL_STATE.value & _RL_STATE_ISEARCH: + RL_STATE.value &= ~_RL_STATE_ISEARCH + + if not RL_STATE.value & _RL_STATE_DONE: + RL_STATE.value |= _RL_STATE_DONE + + def rl_completion_suppress_append(val=1): """Sets the rl_completion_suppress_append varaiable, if possible. A value of 1 (default) means to suppress, a value of 0 means to enable. @@ -263,6 +279,7 @@ class ReadlineShell(BaseShell, Cmd): self._cmdloop(intro=intro) except KeyboardInterrupt: print() # Gives a newline + fix_readline_state_after_ctrl_c() self.reset_buffer() intro = None From f24c2488a112e58710ee094a0f7bc8380d0db8a9 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Tue, 17 May 2016 23:52:39 -0400 Subject: [PATCH 2/5] update changelog --- CHANGELOG.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 847cfbbaf..b70987ea0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -35,7 +35,8 @@ Current Developments variables to control caching of scripts and interactive commands. These can also be controlled by command line options ``--no-script-cache`` and ``--cache-everything`` when starting xonsh. - +* Added a workaround to allow ctrl-c to interrupt reverse incremental search in + the readline shell **Changed:** From e28758f4a7ba19cc6bed5d7181f00c792af38e70 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 18 May 2016 00:07:18 -0400 Subject: [PATCH 3/5] fix for windows --- xonsh/readline_shell.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xonsh/readline_shell.py b/xonsh/readline_shell.py index dbd997e0f..6671d1941 100644 --- a/xonsh/readline_shell.py +++ b/xonsh/readline_shell.py @@ -45,7 +45,10 @@ def setup_readline(): except ValueError: # not all versions of readline have this symbol, ie Macs sometimes RL_COMPLETION_SUPPRESS_APPEND = None - RL_STATE = ctypes.c_int.in_dll(lib, 'rl_readline_state') + try: + RL_STATE = ctypes.c_int.in_dll(lib, 'rl_readline_state') + except: + pass RL_CAN_RESIZE = hasattr(lib, 'rl_reset_screen_size') env = builtins.__xonsh_env__ # reads in history @@ -80,9 +83,10 @@ def fix_readline_state_after_ctrl_c(): Based on code from: http://bugs.python.org/file39467/raw_input__workaround_demo.py """ + if RL_STATE is None: + return if RL_STATE.value & _RL_STATE_ISEARCH: RL_STATE.value &= ~_RL_STATE_ISEARCH - if not RL_STATE.value & _RL_STATE_DONE: RL_STATE.value |= _RL_STATE_DONE From 890470ed8d4ede0f282ff98b5feb5943dc755489 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 18 May 2016 00:33:26 -0400 Subject: [PATCH 4/5] actual fix for pyreadline --- xonsh/readline_shell.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/xonsh/readline_shell.py b/xonsh/readline_shell.py index 6671d1941..1f54e0dc2 100644 --- a/xonsh/readline_shell.py +++ b/xonsh/readline_shell.py @@ -19,6 +19,7 @@ if HAVE_PYGMENTS: import pygments from pygments.formatters.terminal256 import Terminal256Formatter +readline = None RL_COMPLETION_SUPPRESS_APPEND = RL_LIB = RL_STATE = None RL_CAN_RESIZE = False RL_DONE = None @@ -27,7 +28,7 @@ _RL_STATE_ISEARCH = 0x0000080 def setup_readline(): """Sets up the readline module and completion suppression, if available.""" - global RL_COMPLETION_SUPPRESS_APPEND, RL_LIB, RL_CAN_RESIZE, RL_STATE + global RL_COMPLETION_SUPPRESS_APPEND, RL_LIB, RL_CAN_RESIZE, RL_STATE, readline if RL_COMPLETION_SUPPRESS_APPEND is not None: return try: @@ -83,6 +84,12 @@ def fix_readline_state_after_ctrl_c(): Based on code from: http://bugs.python.org/file39467/raw_input__workaround_demo.py """ + if ON_WINDOWS: + # hack to make pyreadline mimic the desired behavior + try: + readline.rl.mode.process_keyevent_queue.pop() + except: + pass if RL_STATE is None: return if RL_STATE.value & _RL_STATE_ISEARCH: From cd8d003d6f629c5e4478e3b2fb1eb34b67f227fc Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Wed, 18 May 2016 00:44:49 -0400 Subject: [PATCH 5/5] don't let pyreadline destroy itself --- xonsh/readline_shell.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xonsh/readline_shell.py b/xonsh/readline_shell.py index 1f54e0dc2..f798a384a 100644 --- a/xonsh/readline_shell.py +++ b/xonsh/readline_shell.py @@ -87,7 +87,9 @@ def fix_readline_state_after_ctrl_c(): if ON_WINDOWS: # hack to make pyreadline mimic the desired behavior try: - readline.rl.mode.process_keyevent_queue.pop() + _q = readline.rl.mode.process_keyevent_queue + if len(_q) > 1: + _q.pop() except: pass if RL_STATE is None: