From 51adba6ee0478e6f6db64aa706fcc770b623a2a5 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Fri, 10 Jan 2025 17:59:22 +0100 Subject: [PATCH] Restore autosuggestion after corrected typo Backspace signals that the user is not happy with the commandline, and by extension the autosuggestion. For this reason, backspace suppresses autosuggestions until the next text insertion. However if I 1. type something that has an autosuggestion 2. type *one* wrong letter (removing the autosuggestion) 3. type backspace backspace does not visibly suppress any autosuggestion but rhater signal that the user wants to go back to the previous state of the commandline, which does have an autosuggestion. Enable this scenario by caching the autosuggestion when it's invalidated. On certain edits that make the cached autosuggestion valid again, restore it from the cache. Currently, only do this up to a single backspace. Could extend that in future. This implementation is really bad.. but it's a start. Weirdly, it does not restore the cache on undo; but that's inconsequential because undo doesn't suppress autosuggestion as of today. Closes #3549 --- src/reader.rs | 33 +++++++++++++++++++++++---- tests/checks/tmux-autosuggestion.fish | 7 ++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index bb0a4263c..a3b6512fa 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -490,6 +490,8 @@ pub struct ReaderData { rendered_layout: LayoutData, /// The current autosuggestion. autosuggestion: Autosuggestion, + /// A previously valid autosuggestion. + saved_autosuggestion: Option, /// Current pager. pager: Pager, /// The output of the pager. @@ -1155,6 +1157,7 @@ impl ReaderData { command_line_has_transient_edit: false, rendered_layout: Default::default(), autosuggestion: Default::default(), + saved_autosuggestion: Default::default(), pager: Default::default(), current_page_rendering: Default::default(), suppress_autosuggestion: Default::default(), @@ -1248,7 +1251,9 @@ impl ReaderData { // Update the gen count. GENERATION.fetch_add(1, Ordering::Relaxed); if !keep_autosuggestion { - self.autosuggestion.clear(); + if !self.autosuggestion.is_empty() { + self.saved_autosuggestion = Some(std::mem::take(&mut self.autosuggestion)); + } } } EditableLineTag::SearchField => { @@ -1771,7 +1776,27 @@ impl ReaderData { } fn push_edit_internal(&mut self, elt: EditableLineTag, edit: Edit, allow_coalesce: bool) { - let preserves_autosuggestion = self.try_apply_edit_to_autosuggestion(elt, &edit); + let mut preserves_autosuggestion = self.try_apply_edit_to_autosuggestion(elt, &edit); + if elt == EditableLineTag::Commandline { + let saved_autosuggestion = self.saved_autosuggestion.take(); + if (self.autosuggestion.is_empty() + || !preserves_autosuggestion + || self.suppress_autosuggestion) + && saved_autosuggestion + .as_ref() + .is_some_and(|saved_autosuggestion| { + self.conf.autosuggest_ok + && self.history_search.is_at_end() + && edit.replacement.is_empty() + && edit.range.start == saved_autosuggestion.search_string_range.end + && edit.range.len() == 1 + }) + { + self.autosuggestion = saved_autosuggestion.unwrap(); + self.suppress_autosuggestion = false; + preserves_autosuggestion = true; + } + } self.edit_line_mut(elt).push_edit(edit, allow_coalesce); self.command_line_changed(elt, preserves_autosuggestion); } @@ -1860,9 +1885,9 @@ impl ReaderData { break; } } + self.suppress_autosuggestion = true; self.erase_substring(elt, pos..pos_end); self.update_buff_pos(elt, None); - self.suppress_autosuggestion = true; } } @@ -2800,10 +2825,10 @@ impl<'a> Reader<'a> { }; let begin = el.position() + bias - self.rls().yank_len; let end = el.position() + bias; + self.suppress_autosuggestion = true; self.replace_substring(elt, begin..end, yank_str); self.update_buff_pos(elt, None); self.rls_mut().yank_len = new_yank_len; - self.suppress_autosuggestion = true; } } rl::BackwardDeleteChar => { diff --git a/tests/checks/tmux-autosuggestion.fish b/tests/checks/tmux-autosuggestion.fish index fc536bb5f..f46a7ba8a 100644 --- a/tests/checks/tmux-autosuggestion.fish +++ b/tests/checks/tmux-autosuggestion.fish @@ -23,3 +23,10 @@ isolated-tmux send-keys C-u 'complete nofilecomp -f' Enter C-l 'nofilecomp ./CO' tmux-sleep isolated-tmux capture-pane -p # CHECK: prompt 2> : ./COMPL + +isolated-tmux send-keys C-u C-k C-l ': ./CO' +tmux-sleep +isolated-tmux send-keys A C-h +tmux-sleep +isolated-tmux capture-pane -p +# CHECK: prompt 2> : ./COMPL