Basile Henry 1 month ago committed by GitHub
commit 3607921e12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -31,6 +31,7 @@ pub struct Prompt {
selection: Option<usize>,
history_register: Option<char>,
history_pos: Option<usize>,
history_substring: Option<String>,
completion_fn: CompletionFn,
callback_fn: CallbackFn,
pub doc_fn: DocFn,
@ -83,6 +84,7 @@ impl Prompt {
selection: None,
history_register,
history_pos: None,
history_substring: None,
completion_fn: Box::new(completion_fn),
callback_fn: Box::new(callback_fn),
doc_fn: Box::new(|_| None),
@ -96,6 +98,7 @@ impl Prompt {
self.line = line;
self.cursor = cursor;
self.recalculate_completion(editor);
self.reset_history();
self
}
@ -232,12 +235,14 @@ impl Prompt {
self.cursor = pos;
}
self.recalculate_completion(cx.editor);
self.reset_history();
}
pub fn insert_str(&mut self, s: &str, editor: &Editor) {
self.line.insert_str(self.cursor, s);
self.cursor += s.len();
self.recalculate_completion(editor);
self.reset_history();
}
pub fn move_cursor(&mut self, movement: Movement) {
@ -259,6 +264,7 @@ impl Prompt {
self.cursor = pos;
self.recalculate_completion(editor);
self.reset_history();
}
pub fn delete_char_forwards(&mut self, editor: &Editor) {
@ -266,6 +272,7 @@ impl Prompt {
self.line.replace_range(self.cursor..pos, "");
self.recalculate_completion(editor);
self.reset_history();
}
pub fn delete_word_backwards(&mut self, editor: &Editor) {
@ -274,6 +281,7 @@ impl Prompt {
self.cursor = pos;
self.recalculate_completion(editor);
self.reset_history();
}
pub fn delete_word_forwards(&mut self, editor: &Editor) {
@ -281,6 +289,7 @@ impl Prompt {
self.line.replace_range(self.cursor..pos, "");
self.recalculate_completion(editor);
self.reset_history();
}
pub fn kill_to_start_of_line(&mut self, editor: &Editor) {
@ -289,6 +298,7 @@ impl Prompt {
self.cursor = pos;
self.recalculate_completion(editor);
self.reset_history();
}
pub fn kill_to_end_of_line(&mut self, editor: &Editor) {
@ -296,12 +306,19 @@ impl Prompt {
self.line.replace_range(self.cursor..pos, "");
self.recalculate_completion(editor);
self.reset_history();
}
pub fn clear(&mut self, editor: &Editor) {
self.line.clear();
self.cursor = 0;
self.recalculate_completion(editor);
self.reset_history();
}
pub fn reset_history(&mut self) {
self.history_pos = None;
self.history_substring = None;
}
pub fn change_history(
@ -312,11 +329,15 @@ impl Prompt {
) {
(self.callback_fn)(cx, &self.line, PromptEvent::Abort);
let mut values = match cx.editor.registers.read(register, cx.editor) {
Some(values) if values.len() > 0 => values.rev(),
Some(values) if values.len() > 0 => values.rev().enumerate(),
_ => return,
};
let end = values.len().saturating_sub(1);
// Using `history_pos` as the trigger so that we only consider updating
// the substring to match on when entering history
if self.history_pos.is_none() && !self.line.is_empty() {
self.history_substring = Some(self.line.clone())
}
let index = match direction {
CompletionDirection::Forward => self.history_pos.map_or(0, |i| i + 1),
@ -324,18 +345,41 @@ impl Prompt {
.history_pos
.unwrap_or_else(|| values.len())
.saturating_sub(1),
}
.min(end);
};
let history_line = if let Some(substr) = self.history_substring.as_ref() {
match direction {
CompletionDirection::Forward => {
if index > 0 {
// Same as skip but without taking ownership
let _ = values.nth(index - 1);
}
values.find(|prev| prev.1.find(substr).is_some())
}
CompletionDirection::Backward => {
let r_index = values.len() - 1 - index;
if r_index > 0 {
// Same as skip but without taking ownership
let _ = values.nth_back(r_index - 1);
}
values.rfind(|prev| prev.1.find(substr).is_some())
}
}
} else {
values.nth(index)
};
self.line = values.nth(index).unwrap().to_string();
// Appease the borrow checker.
drop(values);
if let Some((index, line)) = history_line {
self.line = line.to_string();
// Appease the borrow checker.
drop(values);
self.history_pos = Some(index);
self.history_pos = Some(index);
self.move_end();
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
self.recalculate_completion(cx.editor);
self.move_end();
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
self.recalculate_completion(cx.editor);
}
}
pub fn change_completion_selection(&mut self, direction: CompletionDirection) {
@ -357,6 +401,7 @@ impl Prompt {
self.line.replace_range(range.clone(), item);
self.move_end();
self.reset_history();
}
pub fn exit_selection(&mut self) {
@ -492,6 +537,28 @@ impl Prompt {
)
.into();
text.render(line_area, surface, cx);
} else if let Some((pre, substr, post)) =
self.history_substring.as_ref().and_then(|substr| {
self.line
.split_once(substr)
.map(|(pre, post)| (pre, substr, post))
})
{
surface.set_string(line_area.x, line_area.y, pre, prompt_color);
surface.set_string(
line_area.x + pre.len() as u16,
line_area.y,
substr,
selected_color,
);
surface.set_string(
line_area.x + (pre.len() + substr.len()) as u16,
line_area.y,
post,
prompt_color,
);
} else {
surface.set_string(line_area.x, line_area.y, self.line.clone(), prompt_color);
}

@ -4,7 +4,7 @@ use super::*;
async fn test_history_completion() -> anyhow::Result<()> {
test_key_sequence(
&mut AppBuilder::new().build()?,
Some(":asdf<ret>:theme d<C-n><tab>"),
Some(":asdf<ret>:<C-n><tab>"),
Some(&|app| {
assert!(!app.editor.is_err());
}),

Loading…
Cancel
Save