mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 16:33:37 +01:00
Fixes Issue 7648 which crashes nushell and happens when an alias name is shorter than the alias command and the alias command is an external command. (#7779)
This commit is contained in:
parent
f823c7cb5d
commit
8acced56b2
@ -164,7 +164,7 @@ impl Completer for CommandCompletion {
|
|||||||
.flattened
|
.flattened
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.skip_while(|x| x.0.end > pos)
|
.skip_while(|x| x.0.end + offset > pos)
|
||||||
.take_while(|x| {
|
.take_while(|x| {
|
||||||
matches!(
|
matches!(
|
||||||
x.1,
|
x.1,
|
||||||
|
@ -111,11 +111,18 @@ impl NuCompleter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn completion_helper(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
|
fn completion_helper(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
|
||||||
|
// pos: is the position of the cursor in the shell input.
|
||||||
|
// e.g. lets say you have an alias -> `alias ll = ls -l` and you type in the shell:
|
||||||
|
// > ll -a | c
|
||||||
|
// and your cursor is right after `c` then `pos` = 9
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
||||||
let offset = working_set.next_span_start();
|
let mut offset = working_set.next_span_start();
|
||||||
let (mut new_line, alias_offset) = try_find_alias(line.as_bytes(), &working_set);
|
let (mut new_line, alias_offset) = try_find_alias(line.as_bytes(), &working_set);
|
||||||
let initial_line = line.to_string();
|
// new_line: vector containing all alias "translations" so if it was `ll` now is `ls -l`.
|
||||||
let alias_total_offset: usize = alias_offset.iter().sum();
|
// alias_offset:vector the offset between the name and the alias)
|
||||||
|
let initial_line = line.to_string(); // Entire line in the shell input.
|
||||||
|
let alias_total_offset: usize = alias_offset.iter().sum(); // the sum of all alias offsets.
|
||||||
new_line.insert(alias_total_offset + pos, b'a');
|
new_line.insert(alias_total_offset + pos, b'a');
|
||||||
let pos = offset + pos;
|
let pos = offset + pos;
|
||||||
let config = self.engine_state.get_config();
|
let config = self.engine_state.get_config();
|
||||||
@ -156,14 +163,22 @@ impl NuCompleter {
|
|||||||
most_left_variable(flat_idx, &working_set, flattened.clone());
|
most_left_variable(flat_idx, &working_set, flattened.clone());
|
||||||
|
|
||||||
// Create a new span
|
// Create a new span
|
||||||
let new_span = if flat_idx == 0 {
|
// if flat_idx == 0
|
||||||
Span::new(flat.0.start, flat.0.end - 1 - span_offset)
|
let mut span_start = flat.0.start;
|
||||||
} else {
|
let mut span_end = flat.0.end - 1 - span_offset;
|
||||||
Span::new(
|
|
||||||
flat.0.start - span_offset,
|
if flat_idx != 0 {
|
||||||
flat.0.end - 1 - span_offset,
|
span_start = flat.0.start - span_offset;
|
||||||
)
|
span_end = flat.0.end - 1 - span_offset;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if span_end < span_start {
|
||||||
|
span_start = flat.0.start;
|
||||||
|
span_end = flat.0.end - 1;
|
||||||
|
offset += span_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_span = Span::new(span_start, span_end);
|
||||||
|
|
||||||
// Parses the prefix. Completion should look up to the cursor position, not after.
|
// Parses the prefix. Completion should look up to the cursor position, not after.
|
||||||
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
||||||
@ -178,6 +193,10 @@ impl NuCompleter {
|
|||||||
most_left_var.unwrap_or((vec![], vec![])),
|
most_left_var.unwrap_or((vec![], vec![])),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if offset > new_span.start {
|
||||||
|
offset -= span_offset;
|
||||||
|
}
|
||||||
|
|
||||||
return self.process_completion(
|
return self.process_completion(
|
||||||
&mut completer,
|
&mut completer,
|
||||||
&working_set,
|
&working_set,
|
||||||
|
@ -815,3 +815,22 @@ fn extern_complete_flags(mut extern_completer: NuCompleter) {
|
|||||||
let expected: Vec<String> = vec!["--foo".into(), "-b".into(), "-f".into()];
|
let expected: Vec<String> = vec!["--foo".into(), "-b".into(), "-f".into()];
|
||||||
match_suggestions(expected, suggestions);
|
match_suggestions(expected, suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn alias_offset_bug_7748() {
|
||||||
|
let (dir, _, mut engine, mut stack) = new_engine();
|
||||||
|
|
||||||
|
// Create an alias
|
||||||
|
let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#;
|
||||||
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok());
|
||||||
|
|
||||||
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
||||||
|
|
||||||
|
// Issue #7748
|
||||||
|
// Nushell crashes when an alias name is shorter than the alias command
|
||||||
|
// and the alias command is a external command
|
||||||
|
// This happens because of offset is not correct.
|
||||||
|
// This crashes before PR #7779
|
||||||
|
let _suggestions = completer.complete("e", 1);
|
||||||
|
//println!(" --------- suggestions: {:?}", suggestions);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user