@@ -200,7 +200,7 @@ def rl_get_point() -> int: # pragma: no cover
200200
201201
202202def rl_get_prompt () -> str : # pragma: no cover
203- """Gets Readline's current prompt"""
203+ """Get Readline's prompt"""
204204 if rl_type == RlType .GNU :
205205 encoded_prompt = ctypes .c_char_p .in_dll (readline_lib , "rl_prompt" ).value
206206 if encoded_prompt is None :
@@ -221,6 +221,24 @@ def rl_get_prompt() -> str: # pragma: no cover
221221 return rl_unescape_prompt (prompt )
222222
223223
224+ def rl_get_display_prompt () -> str : # pragma: no cover
225+ """
226+ Get Readline's currently displayed prompt.
227+
228+ In GNU Readline, the displayed prompt sometimes differs from the prompt.
229+ This occurs in functions that use the prompt string as a message area, such as incremental search.
230+ """
231+ if rl_type == RlType .GNU :
232+ encoded_prompt = ctypes .c_char_p .in_dll (readline_lib , "rl_display_prompt" ).value
233+ if encoded_prompt is None :
234+ prompt = ''
235+ else :
236+ prompt = encoded_prompt .decode (encoding = 'utf-8' )
237+ return rl_unescape_prompt (prompt )
238+ else :
239+ return rl_get_prompt ()
240+
241+
224242def rl_set_prompt (prompt : str ) -> None : # pragma: no cover
225243 """
226244 Sets Readline's prompt
@@ -237,7 +255,8 @@ def rl_set_prompt(prompt: str) -> None: # pragma: no cover
237255
238256
239257def rl_escape_prompt (prompt : str ) -> str :
240- """Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes
258+ """
259+ Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes
241260
242261 :param prompt: original prompt
243262 :return: prompt safe to pass to GNU Readline
@@ -276,3 +295,32 @@ def rl_unescape_prompt(prompt: str) -> str:
276295 prompt = prompt .replace (escape_start , "" ).replace (escape_end , "" )
277296
278297 return prompt
298+
299+
300+ def rl_in_search_mode () -> bool :
301+ """Check if readline is doing either an incremental (e.g. Ctrl-r) or non-incremental (e.g. Esc-p) search"""
302+ if rl_type == RlType .GNU :
303+ # GNU Readline defines constants that we can use to determine if in search mode.
304+ # RL_STATE_ISEARCH 0x0000080
305+ # RL_STATE_NSEARCH 0x0000100
306+ IN_SEARCH_MODE = 0x0000180
307+
308+ readline_state = ctypes .c_int .in_dll (readline_lib , "rl_readline_state" ).value
309+ return bool (IN_SEARCH_MODE & readline_state )
310+ elif rl_type == RlType .PYREADLINE :
311+ from pyreadline3 .modes .emacs import ( # type: ignore[import]
312+ EmacsMode ,
313+ )
314+
315+ # These search modes only apply to Emacs mode, which is the default.
316+ if not isinstance (readline .rl .mode , EmacsMode ):
317+ return False
318+
319+ # While in search mode, the current keyevent function is set one of the following.
320+ search_funcs = (
321+ readline .rl .mode ._process_incremental_search_keyevent ,
322+ readline .rl .mode ._process_non_incremental_search_keyevent ,
323+ )
324+ return readline .rl .mode .process_keyevent_queue [- 1 ] in search_funcs
325+ else :
326+ return False
0 commit comments