@@ -3,16 +3,15 @@ use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
3use helix_core::Position;
3use helix_core::Position;
4use helix_view::Editor;
4use helix_view::Editor;
5use helix_view::Theme;
5use helix_view::Theme;
6−use std::borrow::Cow;
6+use std::{borrow::Cow, ops::RangeFrom};
7−use std::string::String;
9pub struct Prompt {
8pub struct Prompt {
10 prompt: String,
9 prompt: String,
11 pub line: String,
10 pub line: String,
12 cursor: usize,
11 cursor: usize,
13− completion: Vec<Cow<'static, str>>,
12+ completion: Vec<(RangeFrom<usize>, Cow<'static, str>)>,
14 completion_selection_index: Option<usize>,
13 completion_selection_index: Option<usize>,
15− completion_fn: Box<dyn FnMut(&str) -> Vec<Cow<'static, str>>>,
14+ completion_fn: Box<dyn FnMut(&str) -> Vec<(RangeFrom<usize>, Cow<'static, str>)>>,
16 callback_fn: Box<dyn FnMut(&mut Editor, &str, PromptEvent)>,
15 callback_fn: Box<dyn FnMut(&mut Editor, &str, PromptEvent)>,
@@ -29,7 +28,7 @@ pub enum PromptEvent {
29impl Prompt {
28impl Prompt {
30 pub fn new(
29 pub fn new(
31 prompt: String,
30 prompt: String,
32− mut completion_fn: impl FnMut(&str) -> Vec<Cow<'static, str>> + 'static,
31+ mut completion_fn: impl FnMut(&str) -> Vec<(RangeFrom<usize>, Cow<'static, str>)> + 'static,
33 callback_fn: impl FnMut(&mut Editor, &str, PromptEvent) + 'static,
32 callback_fn: impl FnMut(&mut Editor, &str, PromptEvent) + 'static,
34 ) -> Prompt {
33 ) -> Prompt {
@@ -85,15 +84,9 @@ impl Prompt {
85 self.completion_selection_index.map(|i| i + 1).unwrap_or(0) % self.completion.len();
84 self.completion_selection_index.map(|i| i + 1).unwrap_or(0) % self.completion.len();
86 self.completion_selection_index = Some(index);
85 self.completion_selection_index = Some(index);
88− let item = &self.completion[index];
87+ let (range, item) = &self.completion[index];
90− // replace the last arg
91− if let Some(pos) = self.line.rfind(' ') {
92− self.line.replace_range(pos + 1.., item);
89+ self.line.replace_range(range.clone(), item);
94− // need toowned_clone_into nightly feature to reuse allocation
95− self.line = item.to_string();
98 self.move_end();
91 self.move_end();
99 // TODO: recalculate completion when completion item is accepted, (Enter)
92 // TODO: recalculate completion when completion item is accepted, (Enter)
@@ -135,7 +128,7 @@ impl Prompt {
135 Rect::new(0, area.height - col_height - 2, area.width, col_height),
128 Rect::new(0, area.height - col_height - 2, area.width, col_height),
136 theme.get("ui.statusline"),
129 theme.get("ui.statusline"),
138− for (i, command) in self.completion.iter().enumerate() {
131+ for (i, (_range, completion)) in self.completion.iter().enumerate() {
139 let color = if self.completion_selection_index.is_some()
132 let color = if self.completion_selection_index.is_some()
140 && i == self.completion_selection_index.unwrap()
133 && i == self.completion_selection_index.unwrap()
@@ -146,7 +139,7 @@ impl Prompt {
146 surface.set_stringn(
139 surface.set_stringn(
147 1 + col * BASE_WIDTH,
140 1 + col * BASE_WIDTH,
148 area.height - col_height - 2 + row,
141 area.height - col_height - 2 + row,
149− &command,
142+ &completion,
150 BASE_WIDTH as usize - 1,
143 BASE_WIDTH as usize - 1,