diff --git a/crates/nu-cli/src/completions/completer.rs b/crates/nu-cli/src/completions/completer.rs index 5aadca2ca..eea962cfd 100644 --- a/crates/nu-cli/src/completions/completer.rs +++ b/crates/nu-cli/src/completions/completer.rs @@ -123,7 +123,8 @@ impl NuCompleter { let offset = working_set.next_span_start(); let (mut new_line, alias_offset) = try_find_alias(line.as_bytes(), &working_set); let initial_line = line.to_string(); - new_line.push(b'a'); + let alias_total_offset: usize = alias_offset.iter().sum(); + new_line.insert(alias_total_offset + pos, b'a'); let pos = offset + pos; let config = self.engine_state.get_config(); @@ -169,9 +170,10 @@ impl NuCompleter { } }; - // Parses the prefix + // 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(); - prefix.remove(pos - (flat.0.start - span_offset)); + let index = pos - (flat.0.start - span_offset); + prefix.drain(index..); // Variables completion if prefix.starts_with(b"$") || most_left_var.is_some() { diff --git a/crates/nu-cli/tests/completions.rs b/crates/nu-cli/tests/completions.rs index 372315960..2ecf053ac 100644 --- a/crates/nu-cli/tests/completions.rs +++ b/crates/nu-cli/tests/completions.rs @@ -63,7 +63,7 @@ fn variables_single_dash_argument_with_flagcompletion(mut completer: NuCompleter #[rstest] fn variables_command_with_commandcompletion(mut completer_strings: NuCompleter) { - let suggestions = completer_strings.complete("my-command ", 9); + let suggestions = completer_strings.complete("my-c ", 4); let expected: Vec = vec!["my-command".into()]; match_suggestions(expected, suggestions); } @@ -672,3 +672,63 @@ fn unknown_command_completion() { match_suggestions(expected_paths, suggestions) } + +#[rstest] +fn flagcompletion_triggers_after_cursor(mut completer: NuCompleter) { + let suggestions = completer.complete("tst -h", 5); + let expected: Vec = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()]; + match_suggestions(expected, suggestions); +} + +#[rstest] +fn customcompletion_triggers_after_cursor(mut completer_strings: NuCompleter) { + let suggestions = completer_strings.complete("my-command c", 11); + let expected: Vec = vec!["cat".into(), "dog".into(), "eel".into()]; + match_suggestions(expected, suggestions); +} + +#[rstest] +fn customcompletion_triggers_after_cursor_piped(mut completer_strings: NuCompleter) { + let suggestions = completer_strings.complete("my-command c | ls", 11); + let expected: Vec = vec!["cat".into(), "dog".into(), "eel".into()]; + match_suggestions(expected, suggestions); +} + +#[rstest] +fn flagcompletion_triggers_after_cursor_piped(mut completer: NuCompleter) { + let suggestions = completer.complete("tst -h | ls", 5); + let expected: Vec = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()]; + match_suggestions(expected, suggestions); +} + +#[test] +fn filecompletions_triggers_after_cursor() { + let (_, _, engine, stack) = new_engine(); + + let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); + + let suggestions = completer.complete("cp test_c", 3); + + #[cfg(windows)] + let expected_paths: Vec = vec![ + "nushell".to_string(), + "test_a\\".to_string(), + "test_b\\".to_string(), + "another\\".to_string(), + "custom_completion.nu".to_string(), + ".hidden_file".to_string(), + ".hidden_folder\\".to_string(), + ]; + #[cfg(not(windows))] + let expected_paths: Vec = vec![ + "nushell".to_string(), + "test_a/".to_string(), + "test_b/".to_string(), + "another/".to_string(), + "custom_completion.nu".to_string(), + ".hidden_file".to_string(), + ".hidden_folder/".to_string(), + ]; + + match_suggestions(expected_paths, suggestions); +}