mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-01 13:01:21 -03:00
Refactor autosuggestion saving lifecycle a bit
This commit is contained in:
@@ -251,10 +251,7 @@ pub fn reader_push<'a>(parser: &'a Parser, history_name: &wstr, conf: ReaderConf
|
||||
let data = ReaderData::new(hist, conf);
|
||||
reader_data_stack().push(data);
|
||||
let data = current_data().unwrap();
|
||||
data.command_line_changed(
|
||||
EditableLineTag::Commandline,
|
||||
/*keep_autosuggestion=*/ false,
|
||||
);
|
||||
data.command_line_changed(EditableLineTag::Commandline, AutosuggestionUpdate::Remove);
|
||||
if reader_data_stack().len() == 1 {
|
||||
reader_interactive_init(parser);
|
||||
}
|
||||
@@ -1246,15 +1243,29 @@ fn rls_mut(&mut self) -> &mut ReadlineLoopState {
|
||||
}
|
||||
|
||||
/// Do what we need to do whenever our command line changes.
|
||||
fn command_line_changed(&mut self, elt: EditableLineTag, keep_autosuggestion: bool) {
|
||||
fn command_line_changed(
|
||||
&mut self,
|
||||
elt: EditableLineTag,
|
||||
autosuggestion_update: AutosuggestionUpdate,
|
||||
) {
|
||||
assert_is_main_thread();
|
||||
match elt {
|
||||
EditableLineTag::Commandline => {
|
||||
// Update the gen count.
|
||||
GENERATION.fetch_add(1, Ordering::Relaxed);
|
||||
if !keep_autosuggestion {
|
||||
if !self.autosuggestion.is_empty() {
|
||||
self.saved_autosuggestion = Some(std::mem::take(&mut self.autosuggestion));
|
||||
let saved_autosuggestion = self.saved_autosuggestion.take();
|
||||
use AutosuggestionUpdate::*;
|
||||
match autosuggestion_update {
|
||||
Preserve => (),
|
||||
Remove => {
|
||||
if !self.autosuggestion.is_empty() {
|
||||
self.saved_autosuggestion =
|
||||
Some(std::mem::take(&mut self.autosuggestion))
|
||||
}
|
||||
}
|
||||
Restore => {
|
||||
self.autosuggestion = saved_autosuggestion.unwrap();
|
||||
self.suppress_autosuggestion = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1655,6 +1666,12 @@ fn paint_layout(&mut self, reason: &wstr, is_final_rendering: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
enum AutosuggestionUpdate {
|
||||
Preserve,
|
||||
Remove,
|
||||
Restore,
|
||||
}
|
||||
|
||||
impl ReaderData {
|
||||
/// Internal helper function for handling killing parts of text.
|
||||
fn kill(&mut self, elt: EditableLineTag, range: Range<usize>, mode: Kill, newv: bool) {
|
||||
@@ -1743,13 +1760,10 @@ fn set_command_line_and_position(
|
||||
self.update_buff_pos(elt, Some(pos));
|
||||
}
|
||||
|
||||
fn try_apply_edit_to_autosuggestion(&mut self, elt: EditableLineTag, edit: &Edit) -> bool {
|
||||
if elt != EditableLineTag::Commandline {
|
||||
return false;
|
||||
}
|
||||
fn try_apply_edit_to_autosuggestion(&mut self, edit: &Edit) -> bool {
|
||||
let autosuggestion = &self.autosuggestion;
|
||||
if autosuggestion.is_empty() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if our autosuggestion still applies; if so, don't recompute it.
|
||||
@@ -1788,39 +1802,37 @@ fn try_apply_edit_to_autosuggestion(&mut self, elt: EditableLineTag, edit: &Edit
|
||||
}
|
||||
|
||||
fn push_edit_internal(&mut self, elt: EditableLineTag, edit: Edit, allow_coalesce: bool) {
|
||||
let mut preserves_autosuggestion = self.try_apply_edit_to_autosuggestion(elt, &edit);
|
||||
let mut autosuggestion_update = AutosuggestionUpdate::Remove;
|
||||
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
|
||||
})
|
||||
let preserves_autosuggestion = self.try_apply_edit_to_autosuggestion(&edit);
|
||||
if preserves_autosuggestion {
|
||||
autosuggestion_update = AutosuggestionUpdate::Preserve
|
||||
} else if self
|
||||
.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.is_empty()
|
||||
})
|
||||
{
|
||||
self.autosuggestion = saved_autosuggestion.unwrap();
|
||||
self.suppress_autosuggestion = false;
|
||||
preserves_autosuggestion = true;
|
||||
autosuggestion_update = AutosuggestionUpdate::Restore;
|
||||
}
|
||||
}
|
||||
self.edit_line_mut(elt).push_edit(edit, allow_coalesce);
|
||||
self.command_line_changed(elt, preserves_autosuggestion);
|
||||
self.command_line_changed(elt, autosuggestion_update);
|
||||
}
|
||||
|
||||
fn undo(&mut self, elt: EditableLineTag) -> bool {
|
||||
let ok = self.edit_line_mut(elt).undo();
|
||||
self.command_line_changed(elt, /*keep_autosuggestion=*/ false);
|
||||
self.command_line_changed(elt, AutosuggestionUpdate::Remove);
|
||||
ok
|
||||
}
|
||||
fn redo(&mut self, elt: EditableLineTag) -> bool {
|
||||
let ok = self.edit_line_mut(elt).redo();
|
||||
self.command_line_changed(elt, /*keep_autosuggestion=*/ false);
|
||||
self.command_line_changed(elt, AutosuggestionUpdate::Remove);
|
||||
ok
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user