From 23e518223da68e002c63b57371c557230d286146 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 12 Oct 2026 21:21:49 +0000 Subject: [PATCH] Handle Ctrl-Z in incremental history search through the key binding The incremental history search had its own handling of Ctrl-Z with `raise( SIGSTOP )`, bypassing the key binding. When an application rebinds Ctrl-Z to disable suspending (e.g. when the line editor runs inside a server process serving a pseudoterminal), the search still stopped the process. Now Ctrl-Z leaves the search and is passed to the main loop, like other editing keys, so that it goes through the key binding. Co-Authored-By: Claude Opus 5.5 --- src/replxx_impl.cxx | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/replxx_impl.cxx b/src/replxx_impl.cxx index aac468b..dce9d1a 100644 --- a/src/replxx_impl.cxx +++ b/src/replxx_impl.cxx @@ -2471,7 +2471,10 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::incremental_history_search( char32_t s case Replxx::KEY::meta( '<' ): // start of history case Replxx::KEY::PAGE_UP: case Replxx::KEY::meta( '>' ): // end of history - case Replxx::KEY::PAGE_DOWN: { + case Replxx::KEY::PAGE_DOWN: + // ctrl-Z, job control: leave the search and let the main loop handle the key, + // so that it goes through the key binding (which may disable suspending). + case Replxx::KEY::control('Z'): { keepLooping = false; } break; @@ -2505,21 +2508,6 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::incremental_history_search( char32_t s } } break; -// job control is its own thing -#ifndef _WIN32 - case Replxx::KEY::control('Z'): { // ctrl-Z, job control - /* IOModeGuard scope */ { - IOModeGuard ioModeGuard( _terminal ); - // Returning to Linux (whatever) shell, leave raw mode - // Break out in mid-line - // Back from Linux shell, re-enter raw mode - raise( SIGSTOP ); - } - dynamic_refresh( dp, dp, activeHistoryLine.get(), activeHistoryLine.length(), historyLinePosition ); - continue; - } break; -#endif - // these characters assign the search string, and hence the selected input line case Replxx::KEY::BACKSPACE: { // backspace/ctrl-H, delete char to left of cursor if ( dp._searchText.length() > 0 ) {