reader: repaint commands to not disable "last_cmd"-based UI states (pager etc.)

"commandline -f repaint" might be triggered for various reasons;
since this sets "last_cmd", it will reset some UI states, notably
pager selection:

1. press tab
2. trigger repaint
3. press tab

The repaint prevents us from selecting the first candidate.

Work around this by ignoring repaint events for the last_cmd logic.

Fixes #12683
This commit is contained in:
Johannes Altmanninger
2026-04-28 14:19:13 +08:00
parent c91bfba08c
commit f2b0706494
3 changed files with 26 additions and 2 deletions

View File

@@ -1154,9 +1154,9 @@ pub fn reader_execute_readline_cmd(parser: &Parser, ch: CharEvent) {
if matches!(
readline_cmd_evt.cmd,
ReadlineCmd::ClearScreenAndRepaint
| ReadlineCmd::ForceRepaint
| ReadlineCmd::RepaintMode
| ReadlineCmd::Repaint
| ReadlineCmd::ForceRepaint
) {
data.queued_repaint = true;
}
@@ -2847,7 +2847,9 @@ fn handle_char_event(&mut self, injected_event: Option<CharEvent>) -> ControlFlo
self.command_line_transient_edit = None;
}
self.rls_mut().last_cmd = Some(readline_cmd);
if !command_only_affects_rendering(readline_cmd) {
self.rls_mut().last_cmd = Some(readline_cmd);
}
}
CharEvent::Command(command) => {
self.run_input_command_scripts(&command);
@@ -6291,6 +6293,15 @@ fn command_ends_history_search(c: ReadlineCmd) -> bool {
)
}
fn command_only_affects_rendering(c: ReadlineCmd) -> bool {
#[allow(non_camel_case_types)]
type rl = ReadlineCmd;
matches!(
c,
rl::ClearScreenAndRepaint | rl::ForceRepaint | rl::RepaintMode | rl::Repaint
)
}
/// Return true if we believe ourselves to be orphaned. loop_count is how many times we've tried to
/// stop ourselves via SIGGTIN.
fn check_for_orphaned_process(loop_count: usize, shell_pgid: libc::pid_t) -> bool {