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

Don't slice line in DefaultCompleter #695

Merged
merged 10 commits into from
Jan 11, 2024
3 changes: 2 additions & 1 deletion src/completion/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ impl Span {
}
}

/// A trait that defines how to convert a line and position to a list of potential completions in that position.
/// A trait that defines how to convert some text and a position to a list of potential completions in that position.
/// The text could be a part of the whole line, and the position is the index of the end of the text in the original line.
pub trait Completer: Send {
/// the action that will take the line and position and convert it to a vector of completions, which include the
/// span to replace and the contents of that replacement
Expand Down
5 changes: 4 additions & 1 deletion src/completion/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ impl Completer for DefaultCompleter {
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
let mut span_line_whitespaces = 0;
let mut completions = vec![];
// Trimming in case someone passes in text containing stuff after the cursor, if
// `only_buffer_difference` is false
let line = if line.len() > pos { &line[..pos] } else { line };
if !line.is_empty() {
let mut split = line[0..pos].split(' ').rev();
let mut split = line.split(' ').rev();
let mut span_line: String = String::new();
for _ in 0..split.clone().count() {
if let Some(s) = split.next() {
Expand Down
4 changes: 2 additions & 2 deletions src/completion/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@

fn create_suggestion(&self, line: &str, pos: usize, value: &str) -> Suggestion {
let span = Span {
start: pos,
end: pos + line.len(),
start: pos - line.len(),
end: pos,

Check warning on line 56 in src/completion/history.rs

View check run for this annotation

Codecov / codecov/patch

src/completion/history.rs#L55-L56

Added lines #L55 - L56 were not covered by tests
};

Suggestion {
Expand Down
2 changes: 1 addition & 1 deletion src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@
self.get_history_session_id(),
)))
.unwrap_or_else(|_| Vec::new())
.get(0)
.first()

Check warning on line 1541 in src/engine.rs

View check run for this annotation

Codecov / codecov/patch

src/engine.rs#L1541

Added line #L1541 was not covered by tests
.and_then(|history| history.command_line.split_whitespace().next_back())
.map(|token| (parsed.remainder.len(), indicator.len(), token.to_string())),
});
Expand Down
19 changes: 13 additions & 6 deletions src/menu/columnar_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,13 +526,16 @@

/// Updates menu values
fn update_values(&mut self, editor: &mut Editor, completer: &mut dyn Completer) {
if self.only_buffer_difference {
self.values = if self.only_buffer_difference {
if let Some(old_string) = &self.input {
let (start, input) = string_difference(editor.get_buffer(), old_string);
if !input.is_empty() {
self.values = completer.complete(input, start);
self.reset_position();
completer.complete(input, start + input.len())

Check warning on line 533 in src/menu/columnar_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/columnar_menu.rs#L533

Added line #L533 was not covered by tests
} else {
completer.complete("", editor.insertion_point())

Check warning on line 535 in src/menu/columnar_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/columnar_menu.rs#L535

Added line #L535 was not covered by tests
}
} else {
completer.complete("", editor.insertion_point())

Check warning on line 538 in src/menu/columnar_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/columnar_menu.rs#L538

Added line #L538 was not covered by tests
}
} else {
// If there is a new line character in the line buffer, the completer
Expand All @@ -541,9 +544,13 @@
// Also, by replacing the new line character with a space, the insert
// position is maintain in the line buffer.
let trimmed_buffer = editor.get_buffer().replace('\n', " ");
self.values = completer.complete(trimmed_buffer.as_str(), editor.insertion_point());
self.reset_position();
}
completer.complete(
&trimmed_buffer[..editor.insertion_point()],
editor.insertion_point(),
)
};

self.reset_position();
}

/// The working details for the menu changes based on the size of the lines
Expand Down
15 changes: 9 additions & 6 deletions src/menu/list_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,20 +395,23 @@
/// Collecting the value from the completer to be shown in the menu
fn update_values(&mut self, editor: &mut Editor, completer: &mut dyn Completer) {
let line_buffer = editor.line_buffer();
let (start, input) = if self.only_buffer_difference {
let (pos, input) = if self.only_buffer_difference {

Check warning on line 398 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L398

Added line #L398 was not covered by tests
match &self.input {
Some(old_string) => {
let (start, input) = string_difference(line_buffer.get_buffer(), old_string);
if input.is_empty() {
(line_buffer.insertion_point(), "")
} else {
(start, input)
(start + input.len(), input)

Check warning on line 405 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L405

Added line #L405 was not covered by tests
}
}
None => (line_buffer.insertion_point(), ""),
}
} else {
(line_buffer.insertion_point(), line_buffer.get_buffer())
(
line_buffer.insertion_point(),
&line_buffer.get_buffer()[..line_buffer.insertion_point()],
)

Check warning on line 414 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L411-L414

Added lines #L411 - L414 were not covered by tests
};

let parsed = parse_selection_char(input, SELECTION_CHAR);
Expand All @@ -421,7 +424,7 @@
}

self.values = if parsed.remainder.is_empty() {
self.query_size = Some(completer.total_completions(parsed.remainder, start));
self.query_size = Some(completer.total_completions(parsed.remainder, pos));

Check warning on line 427 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L427

Added line #L427 was not covered by tests

let skip = self.pages.iter().take(self.page).sum::<Page>().size;
let take = self
Expand All @@ -430,10 +433,10 @@
.map(|page| page.size)
.unwrap_or(self.page_size);

completer.partial_complete(input, start, skip, take)
completer.partial_complete(input, pos, skip, take)

Check warning on line 436 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L436

Added line #L436 was not covered by tests
} else {
self.query_size = None;
completer.complete(input, start)
completer.complete(input, pos)

Check warning on line 439 in src/menu/list_menu.rs

View check run for this annotation

Codecov / codecov/patch

src/menu/list_menu.rs#L439

Added line #L439 was not covered by tests
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/menu/menu_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ pub fn string_difference<'a>(new_string: &'a str, old_string: &str) -> (usize, &
false
}
} else {
*c == old_chars[old_char_index].1
old_char_index == new_char_index && *c == old_chars[old_char_index].1
};

if equal {
Expand Down Expand Up @@ -479,6 +479,15 @@ mod tests {
assert_eq!(res, (6, "she"));
}

#[test]
fn string_difference_with_repeat() {
let new_string = "ee";
let old_string = "e";

let res = string_difference(new_string, old_string);
assert_eq!(res, (1, "e"));
}

#[test]
fn find_common_string_with_ansi() {
use crate::Span;
Expand Down