@@ -200,7 +200,7 @@ def rl_get_point() -> int: # pragma: no cover
200
200
201
201
202
202
def rl_get_prompt () -> str : # pragma: no cover
203
- """Gets Readline's current prompt"""
203
+ """Get Readline's prompt"""
204
204
if rl_type == RlType .GNU :
205
205
encoded_prompt = ctypes .c_char_p .in_dll (readline_lib , "rl_prompt" ).value
206
206
if encoded_prompt is None :
@@ -221,6 +221,24 @@ def rl_get_prompt() -> str: # pragma: no cover
221
221
return rl_unescape_prompt (prompt )
222
222
223
223
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
+
224
242
def rl_set_prompt (prompt : str ) -> None : # pragma: no cover
225
243
"""
226
244
Sets Readline's prompt
@@ -237,7 +255,8 @@ def rl_set_prompt(prompt: str) -> None: # pragma: no cover
237
255
238
256
239
257
def 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
241
260
242
261
:param prompt: original prompt
243
262
:return: prompt safe to pass to GNU Readline
@@ -276,3 +295,32 @@ def rl_unescape_prompt(prompt: str) -> str:
276
295
prompt = prompt .replace (escape_start , "" ).replace (escape_end , "" )
277
296
278
297
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