Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Recalculate completion when going through prompt history #3193

Merged
merged 5 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions helix-term/src/commands/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ pub fn dap_edit_condition(cx: &mut Context) {
None => return,
};
let callback = Box::pin(async move {
let call: Callback = Box::new(move |_editor, compositor| {
let call: Callback = Box::new(move |editor, compositor| {
let mut prompt = Prompt::new(
"condition:".into(),
None,
Expand All @@ -605,7 +605,7 @@ pub fn dap_edit_condition(cx: &mut Context) {
},
);
if let Some(condition) = breakpoint.condition {
prompt.insert_str(&condition)
prompt.insert_str(&condition, editor)
}
compositor.push(Box::new(prompt));
});
Expand All @@ -622,7 +622,7 @@ pub fn dap_edit_log(cx: &mut Context) {
None => return,
};
let callback = Box::pin(async move {
let call: Callback = Box::new(move |_editor, compositor| {
let call: Callback = Box::new(move |editor, compositor| {
let mut prompt = Prompt::new(
"log-message:".into(),
None,
Expand All @@ -646,7 +646,7 @@ pub fn dap_edit_log(cx: &mut Context) {
},
);
if let Some(log_message) = breakpoint.log_message {
prompt.insert_str(&log_message);
prompt.insert_str(&log_message, editor);
}
compositor.push(Box::new(prompt));
});
Expand Down
19 changes: 6 additions & 13 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ pub fn prompt(
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
) {
show_prompt(
cx,
Prompt::new(prompt, history_register, completion_fn, callback_fn),
);
let mut prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn);
// Calculate the initial completion
prompt.recalculate_completion(cx.editor);
cx.push_layer(Box::new(prompt));
}

pub fn prompt_with_input(
Expand All @@ -49,15 +49,8 @@ pub fn prompt_with_input(
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
) {
show_prompt(
cx,
Prompt::new(prompt, history_register, completion_fn, callback_fn).with_line(input),
);
}

fn show_prompt(cx: &mut crate::commands::Context, mut prompt: Prompt) {
// Calculate initial completion
prompt.recalculate_completion(cx.editor);
let prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn)
.with_line(input, cx.editor);
cx.push_layer(Box::new(prompt));
}

Expand Down
4 changes: 2 additions & 2 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,12 @@ impl<T: Item> Picker<T> {
.map(|(index, _score)| &self.options[*index])
}

pub fn save_filter(&mut self, cx: &Context) {
pub fn save_filter(&mut self, cx: &mut Context) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't need &mut?

self.filters.clear();
self.filters
.extend(self.matches.iter().map(|(index, _)| *index));
self.filters.sort_unstable(); // used for binary search later
self.prompt.clear(cx);
self.prompt.clear(cx.editor);
}

pub fn toggle_preview(&mut self) {
Expand Down
73 changes: 43 additions & 30 deletions helix-term/src/ui/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ impl Prompt {
}
}

pub fn with_line(mut self, line: String) -> Self {
pub fn with_line(mut self, line: String, editor: &Editor) -> Self {
let cursor = line.len();
self.line = line;
self.cursor = cursor;
self.exit_selection();
self.recalculate_completion(editor);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reasonable approach here would be to clear the completion list instead of recalculating it, since this function is likely to be used initializing a new prompt and the consumer might not want completions to be calculated instantly.

self
}

Expand Down Expand Up @@ -213,13 +215,15 @@ impl Prompt {
if let Ok(Some(pos)) = cursor.next_boundary(&self.line, 0) {
self.cursor = pos;
}
self.recalculate_completion(cx.editor);
self.exit_selection();
self.recalculate_completion(cx.editor);
}

pub fn insert_str(&mut self, s: &str) {
pub fn insert_str(&mut self, s: &str, editor: &Editor) {
self.line.insert_str(self.cursor, s);
self.cursor += s.len();
self.exit_selection();
self.recalculate_completion(editor);
}

pub fn move_cursor(&mut self, movement: Movement) {
Expand All @@ -235,65 +239,72 @@ impl Prompt {
self.cursor = self.line.len();
}

pub fn delete_char_backwards(&mut self, cx: &Context) {
pub fn delete_char_backwards(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::BackwardChar(1));
self.line.replace_range(pos..self.cursor, "");
self.cursor = pos;

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn delete_char_forwards(&mut self, cx: &Context) {
pub fn delete_char_forwards(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::ForwardChar(1));
self.line.replace_range(self.cursor..pos, "");

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn delete_word_backwards(&mut self, cx: &Context) {
pub fn delete_word_backwards(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::BackwardWord(1));
self.line.replace_range(pos..self.cursor, "");
self.cursor = pos;

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn delete_word_forwards(&mut self, cx: &Context) {
pub fn delete_word_forwards(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::ForwardWord(1));
self.line.replace_range(self.cursor..pos, "");

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn kill_to_start_of_line(&mut self, cx: &Context) {
pub fn kill_to_start_of_line(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::StartOfLine);
self.line.replace_range(pos..self.cursor, "");
self.cursor = pos;

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn kill_to_end_of_line(&mut self, cx: &Context) {
pub fn kill_to_end_of_line(&mut self, editor: &Editor) {
let pos = self.eval_movement(Movement::EndOfLine);
self.line.replace_range(self.cursor..pos, "");

self.exit_selection();
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
}

pub fn clear(&mut self, cx: &Context) {
pub fn clear(&mut self, editor: &Editor) {
self.line.clear();
self.cursor = 0;
self.recalculate_completion(cx.editor);
self.recalculate_completion(editor);
self.exit_selection();
}

pub fn change_history(&mut self, register: &[String], direction: CompletionDirection) {
pub fn change_history(
&mut self,
cx: &mut Context,
register: char,
direction: CompletionDirection,
) {
let register = cx.editor.registers.get_mut(register).read();

if register.is_empty() {
return;
}
Expand All @@ -313,6 +324,8 @@ impl Prompt {
self.history_pos = Some(index);

self.move_end();
self.exit_selection();
self.recalculate_completion(cx.editor);
}

pub fn change_completion_selection(&mut self, direction: CompletionDirection) {
Expand Down Expand Up @@ -490,16 +503,18 @@ impl Component for Prompt {
ctrl!('f') | key!(Right) => self.move_cursor(Movement::ForwardChar(1)),
ctrl!('e') | key!(End) => self.move_end(),
ctrl!('a') | key!(Home) => self.move_start(),
ctrl!('w') | alt!(Backspace) | ctrl!(Backspace) => self.delete_word_backwards(cx),
alt!('d') | alt!(Delete) | ctrl!(Delete) => self.delete_word_forwards(cx),
ctrl!('k') => self.kill_to_end_of_line(cx),
ctrl!('u') => self.kill_to_start_of_line(cx),
ctrl!('w') | alt!(Backspace) | ctrl!(Backspace) => {
self.delete_word_backwards(cx.editor)
}
alt!('d') | alt!(Delete) | ctrl!(Delete) => self.delete_word_forwards(cx.editor),
ctrl!('k') => self.kill_to_end_of_line(cx.editor),
ctrl!('u') => self.kill_to_start_of_line(cx.editor),
ctrl!('h') | key!(Backspace) => {
self.delete_char_backwards(cx);
self.delete_char_backwards(cx.editor);
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
}
ctrl!('d') | key!(Delete) => {
self.delete_char_forwards(cx);
self.delete_char_forwards(cx.editor);
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
}
ctrl!('s') => {
Expand All @@ -516,7 +531,7 @@ impl Component for Prompt {
);
let line = text.slice(range.from()..range.to()).to_string();
if !line.is_empty() {
self.insert_str(line.as_str());
self.insert_str(line.as_str(), cx.editor);
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
}
}
Expand Down Expand Up @@ -548,15 +563,13 @@ impl Component for Prompt {
}
ctrl!('p') | key!(Up) => {
if let Some(register) = self.history_register {
let register = cx.editor.registers.get_mut(register);
self.change_history(register.read(), CompletionDirection::Backward);
self.change_history(cx, register, CompletionDirection::Backward);
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
}
}
ctrl!('n') | key!(Down) => {
if let Some(register) = self.history_register {
let register = cx.editor.registers.get_mut(register);
self.change_history(register.read(), CompletionDirection::Forward);
self.change_history(cx, register, CompletionDirection::Forward);
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
}
}
Expand Down Expand Up @@ -597,8 +610,8 @@ impl Component for Prompt {
.read(c)
.and_then(|r| r.first())
.map_or("", |r| r.as_str()),
context.editor,
);
prompt.recalculate_completion(context.editor);
}));
(self.callback_fn)(cx, &self.line, PromptEvent::Update);
return EventResult::Consumed(None);
Expand Down
1 change: 1 addition & 0 deletions helix-term/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ mod test {
mod auto_pairs;
mod commands;
mod movement;
mod prompt;
mod write;
}
18 changes: 18 additions & 0 deletions helix-term/tests/test/prompt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use super::*;

use helix_term::application::Application;

#[tokio::test]
async fn test_history_completion() -> anyhow::Result<()> {
test_key_sequence(
&mut Application::new(Args::default(), Config::default())?,
Some(":asdf<ret>:theme d<C-n><tab>"),
Some(&|app| {
assert!(!app.editor.is_err());
}),
false,
)
.await?;

Ok(())
}