2022-08-23 16:24:24 +02:00
|
|
|
pub mod support;
|
|
|
|
|
2023-10-06 18:45:30 +02:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
2022-08-23 16:24:24 +02:00
|
|
|
use nu_cli::NuCompleter;
|
|
|
|
use nu_parser::parse;
|
|
|
|
use nu_protocol::engine::StateWorkingSet;
|
|
|
|
use reedline::{Completer, Suggestion};
|
|
|
|
use rstest::{fixture, rstest};
|
2023-10-02 19:44:51 +02:00
|
|
|
use support::{
|
|
|
|
completions_helpers::{new_partial_engine, new_quote_engine},
|
|
|
|
file, folder, match_suggestions, new_engine,
|
|
|
|
};
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
#[fixture]
|
|
|
|
fn completer() -> NuCompleter {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Add record value as example
|
|
|
|
let record = "def tst [--mod -s] {}";
|
|
|
|
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
// Instantiate a new completer
|
|
|
|
NuCompleter::new(std::sync::Arc::new(engine), stack)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[fixture]
|
|
|
|
fn completer_strings() -> NuCompleter {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Add record value as example
|
|
|
|
let record = r#"def animals [] { ["cat", "dog", "eel" ] }
|
|
|
|
def my-command [animal: string@animals] { print $animal }"#;
|
|
|
|
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
// Instantiate a new completer
|
|
|
|
NuCompleter::new(std::sync::Arc::new(engine), stack)
|
|
|
|
}
|
|
|
|
|
2022-12-21 23:33:26 +01:00
|
|
|
#[fixture]
|
|
|
|
fn extern_completer() -> NuCompleter {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Add record value as example
|
|
|
|
let record = r#"
|
|
|
|
def animals [] { [ "cat", "dog", "eel" ] }
|
|
|
|
extern spam [
|
|
|
|
animal: string@animals
|
|
|
|
--foo (-f): string@animals
|
|
|
|
-b: string@animals
|
|
|
|
]
|
|
|
|
"#;
|
|
|
|
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
// Instantiate a new completer
|
|
|
|
NuCompleter::new(std::sync::Arc::new(engine), stack)
|
|
|
|
}
|
|
|
|
|
2023-11-29 23:17:06 +01:00
|
|
|
#[fixture]
|
|
|
|
fn custom_completer() -> NuCompleter {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Add record value as example
|
|
|
|
let record = r#"
|
2024-01-17 16:40:59 +01:00
|
|
|
let external_completer = {|spans|
|
2023-11-29 23:17:06 +01:00
|
|
|
$spans
|
|
|
|
}
|
|
|
|
|
|
|
|
$env.config.completions.external = {
|
|
|
|
enable: true
|
|
|
|
max_results: 100
|
|
|
|
completer: $external_completer
|
|
|
|
}
|
|
|
|
"#;
|
|
|
|
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
// Instantiate a new completer
|
|
|
|
NuCompleter::new(std::sync::Arc::new(engine), stack)
|
|
|
|
}
|
|
|
|
|
2022-09-22 20:50:16 +02:00
|
|
|
#[test]
|
|
|
|
fn variables_dollar_sign_with_varialblecompletion() {
|
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "$ ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
2023-12-19 10:14:34 +01:00
|
|
|
assert_eq!(8, suggestions.len());
|
2022-09-22 20:50:16 +02:00
|
|
|
}
|
|
|
|
|
2022-08-23 16:24:24 +02:00
|
|
|
#[rstest]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn variables_double_dash_argument_with_flagcompletion(mut completer: NuCompleter) {
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer.complete("tst --", 6);
|
|
|
|
let expected: Vec<String> = vec!["--help".into(), "--mod".into()];
|
|
|
|
// dbg!(&expected, &suggestions);
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn variables_single_dash_argument_with_flagcompletion(mut completer: NuCompleter) {
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer.complete("tst -", 5);
|
|
|
|
let expected: Vec<String> = vec!["--help".into(), "--mod".into(), "-h".into(), "-s".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn variables_command_with_commandcompletion(mut completer_strings: NuCompleter) {
|
2022-09-29 10:43:58 +02:00
|
|
|
let suggestions = completer_strings.complete("my-c ", 4);
|
2022-08-23 16:24:24 +02:00
|
|
|
let expected: Vec<String> = vec!["my-command".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn variables_subcommands_with_customcompletion(mut completer_strings: NuCompleter) {
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer_strings.complete("my-command ", 11);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn variables_customcompletion_subcommands_with_customcompletion_2(
|
|
|
|
mut completer_strings: NuCompleter,
|
|
|
|
) {
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer_strings.complete("my-command ", 11);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn dotnu_completions() {
|
|
|
|
// Create a new engine
|
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Test source completion
|
2022-08-31 22:32:56 +02:00
|
|
|
let completion_str = "source-env ".to_string();
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer.complete(&completion_str, completion_str.len());
|
|
|
|
|
2023-12-19 10:14:34 +01:00
|
|
|
assert_eq!(2, suggestions.len());
|
2023-11-17 16:15:55 +01:00
|
|
|
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
|
2023-12-19 10:14:34 +01:00
|
|
|
#[cfg(windows)]
|
|
|
|
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
// Test use completion
|
|
|
|
let completion_str = "use ".to_string();
|
|
|
|
let suggestions = completer.complete(&completion_str, completion_str.len());
|
|
|
|
|
2023-12-19 10:14:34 +01:00
|
|
|
assert_eq!(2, suggestions.len());
|
2023-11-17 16:15:55 +01:00
|
|
|
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
|
2023-12-19 10:14:34 +01:00
|
|
|
#[cfg(windows)]
|
|
|
|
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
|
|
|
|
|
|
|
|
// Test overlay use completion
|
|
|
|
let completion_str = "overlay use ".to_string();
|
|
|
|
let suggestions = completer.complete(&completion_str, completion_str.len());
|
|
|
|
|
|
|
|
assert_eq!(2, suggestions.len());
|
|
|
|
assert_eq!("custom_completion.nu", suggestions.first().unwrap().value);
|
|
|
|
#[cfg(windows)]
|
|
|
|
assert_eq!("directory_completion\\", suggestions.get(1).unwrap().value);
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert_eq!("directory_completion/", suggestions.get(1).unwrap().value);
|
2022-08-23 16:24:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[ignore]
|
|
|
|
fn external_completer_trailing_space() {
|
|
|
|
// https://github.com/nushell/nushell/issues/6378
|
|
|
|
let block = "let external_completer = {|spans| $spans}";
|
|
|
|
let input = "gh alias ".to_string();
|
|
|
|
|
2022-09-25 22:06:13 +02:00
|
|
|
let suggestions = run_external_completion(block, &input);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!(3, suggestions.len());
|
2023-11-17 16:15:55 +01:00
|
|
|
assert_eq!("gh", suggestions.first().unwrap().value);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!("alias", suggestions.get(1).unwrap().value);
|
|
|
|
assert_eq!("", suggestions.get(2).unwrap().value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn external_completer_no_trailing_space() {
|
2023-07-03 07:45:10 +02:00
|
|
|
let block = "{|spans| $spans}";
|
2022-08-23 16:24:24 +02:00
|
|
|
let input = "gh alias".to_string();
|
|
|
|
|
2022-09-25 22:06:13 +02:00
|
|
|
let suggestions = run_external_completion(block, &input);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!(2, suggestions.len());
|
2023-11-17 16:15:55 +01:00
|
|
|
assert_eq!("gh", suggestions.first().unwrap().value);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!("alias", suggestions.get(1).unwrap().value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn external_completer_pass_flags() {
|
2023-07-03 07:45:10 +02:00
|
|
|
let block = "{|spans| $spans}";
|
2022-08-23 16:24:24 +02:00
|
|
|
let input = "gh api --".to_string();
|
|
|
|
|
2022-09-25 22:06:13 +02:00
|
|
|
let suggestions = run_external_completion(block, &input);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!(3, suggestions.len());
|
2023-11-17 16:15:55 +01:00
|
|
|
assert_eq!("gh", suggestions.first().unwrap().value);
|
2022-08-23 16:24:24 +02:00
|
|
|
assert_eq!("api", suggestions.get(1).unwrap().value);
|
|
|
|
assert_eq!("--", suggestions.get(2).unwrap().value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn file_completions() {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, dir_str, engine, stack) = new_engine();
|
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Test completions for the current folder
|
2023-01-30 02:37:54 +01:00
|
|
|
let target_dir = format!("cp {dir_str}");
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
folder(dir.join("another")),
|
|
|
|
file(dir.join("custom_completion.nu")),
|
2023-12-19 10:14:34 +01:00
|
|
|
folder(dir.join("directory_completion")),
|
2022-08-23 16:24:24 +02:00
|
|
|
file(dir.join("nushell")),
|
|
|
|
folder(dir.join("test_a")),
|
|
|
|
folder(dir.join("test_b")),
|
|
|
|
file(dir.join(".hidden_file")),
|
|
|
|
folder(dir.join(".hidden_folder")),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
// Test completions for a file
|
|
|
|
let target_dir = format!("cp {}", folder(dir.join("another")));
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![file(dir.join("another").join("newfile"))];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
2024-02-26 19:14:19 +01:00
|
|
|
|
|
|
|
// Test completions for hidden files
|
|
|
|
let target_dir = format!("ls {}/.", folder(dir.join(".hidden_folder")));
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
let expected_paths: Vec<String> =
|
|
|
|
vec![file(dir.join(".hidden_folder").join(".hidden_subfile"))];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
2022-08-23 16:24:24 +02:00
|
|
|
}
|
|
|
|
|
2023-10-02 19:44:51 +02:00
|
|
|
#[test]
|
|
|
|
fn partial_completions() {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, engine, stack) = new_partial_engine();
|
|
|
|
|
|
|
|
// Instantiate a new completer
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Test completions for a folder's name
|
|
|
|
let target_dir = format!("cd {}", file(dir.join("pa")));
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![
|
|
|
|
folder(dir.join("partial_a")),
|
|
|
|
folder(dir.join("partial_b")),
|
|
|
|
folder(dir.join("partial_c")),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
// Test completions for the files whose name begin with "h"
|
|
|
|
// and are present under directories whose names begin with "pa"
|
|
|
|
let dir_str = file(dir.join("pa").join("h"));
|
|
|
|
let target_dir = format!("cp {dir_str}");
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![
|
|
|
|
file(dir.join("partial_a").join("hello")),
|
|
|
|
file(dir.join("partial_a").join("hola")),
|
|
|
|
file(dir.join("partial_b").join("hello_b")),
|
|
|
|
file(dir.join("partial_b").join("hi_b")),
|
|
|
|
file(dir.join("partial_c").join("hello_c")),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
// Test completion for all files under directories whose names begin with "pa"
|
|
|
|
let dir_str = folder(dir.join("pa"));
|
|
|
|
let target_dir = format!("ls {dir_str}");
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![
|
|
|
|
file(dir.join("partial_a").join("anotherfile")),
|
|
|
|
file(dir.join("partial_a").join("hello")),
|
|
|
|
file(dir.join("partial_a").join("hola")),
|
|
|
|
file(dir.join("partial_b").join("hello_b")),
|
|
|
|
file(dir.join("partial_b").join("hi_b")),
|
|
|
|
file(dir.join("partial_c").join("hello_c")),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
// Test completion for a single file
|
|
|
|
let dir_str = file(dir.join("fi").join("so"));
|
|
|
|
let target_dir = format!("rm {dir_str}");
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![file(dir.join("final_partial").join("somefile"))];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
// Test completion where there is a sneaky `..` in the path
|
|
|
|
let dir_str = file(dir.join("par").join("..").join("fi").join("so"));
|
|
|
|
let target_dir = format!("rm {dir_str}");
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![file(dir.join("final_partial").join("somefile"))];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
}
|
|
|
|
|
2022-08-23 16:24:24 +02:00
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_ls_with_filecompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "ls ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_open_with_filecompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "open ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_rm_with_globcompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "rm ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_cp_with_globcompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "cp ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_save_with_filecompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "save ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_touch_with_filecompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "touch ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn command_watch_with_filecompletion() {
|
2022-08-23 16:24:24 +02:00
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "watch ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
2022-12-08 21:37:10 +01:00
|
|
|
#[test]
|
|
|
|
fn file_completion_quoted() {
|
|
|
|
let (_, _, engine, stack) = new_quote_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "open ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2024-02-07 23:42:50 +01:00
|
|
|
"\'[a] bc.txt\'".to_string(),
|
2023-10-18 23:02:11 +02:00
|
|
|
"`--help`".to_string(),
|
|
|
|
"`-42`".to_string(),
|
|
|
|
"`-inf`".to_string(),
|
|
|
|
"`4.2`".to_string(),
|
2022-12-08 21:37:10 +01:00
|
|
|
"`te st.txt`".to_string(),
|
|
|
|
"`te#st.txt`".to_string(),
|
|
|
|
"`te'st.txt`".to_string(),
|
2023-01-10 20:41:54 +01:00
|
|
|
"`te(st).txt`".to_string(),
|
2023-10-06 18:45:30 +02:00
|
|
|
format!("`{}`", folder("test dir".into())),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
|
|
|
|
let dir: PathBuf = "test dir".into();
|
|
|
|
let target_dir = format!("open '{}'", folder(dir.clone()));
|
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
let expected_paths: Vec<String> = vec![
|
|
|
|
format!("`{}`", file(dir.join("double quote"))),
|
|
|
|
format!("`{}`", file(dir.join("single quote"))),
|
2022-12-08 21:37:10 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
2022-08-23 16:24:24 +02:00
|
|
|
#[test]
|
|
|
|
fn flag_completions() {
|
|
|
|
// Create a new engine
|
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
// Test completions for the 'ls' flags
|
|
|
|
let suggestions = completer.complete("ls -", 4);
|
|
|
|
|
2022-12-27 19:46:23 +01:00
|
|
|
assert_eq!(16, suggestions.len());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
let expected: Vec<String> = vec![
|
|
|
|
"--all".into(),
|
|
|
|
"--directory".into(),
|
|
|
|
"--du".into(),
|
|
|
|
"--full-paths".into(),
|
|
|
|
"--help".into(),
|
|
|
|
"--long".into(),
|
2022-12-27 19:46:23 +01:00
|
|
|
"--mime-type".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"--short-names".into(),
|
|
|
|
"-D".into(),
|
|
|
|
"-a".into(),
|
|
|
|
"-d".into(),
|
|
|
|
"-f".into(),
|
|
|
|
"-h".into(),
|
|
|
|
"-l".into(),
|
2022-12-27 19:46:23 +01:00
|
|
|
"-m".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"-s".into(),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-22 20:50:16 +02:00
|
|
|
fn folder_with_directorycompletions() {
|
2022-08-23 16:24:24 +02:00
|
|
|
// Create a new engine
|
|
|
|
let (dir, dir_str, engine, stack) = new_engine();
|
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Test completions for the current folder
|
2023-01-30 02:37:54 +01:00
|
|
|
let target_dir = format!("cd {dir_str}");
|
2022-08-23 16:24:24 +02:00
|
|
|
let suggestions = completer.complete(&target_dir, target_dir.len());
|
|
|
|
|
|
|
|
// Create the expected values
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
folder(dir.join("another")),
|
2023-12-19 10:14:34 +01:00
|
|
|
folder(dir.join("directory_completion")),
|
2022-08-23 16:24:24 +02:00
|
|
|
folder(dir.join("test_a")),
|
|
|
|
folder(dir.join("test_b")),
|
|
|
|
folder(dir.join(".hidden_folder")),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match the results
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn variables_completions() {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Add record value as example
|
|
|
|
let record = "let actor = { name: 'Tom Hardy', age: 44 }";
|
|
|
|
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Test completions for $nu
|
|
|
|
let suggestions = completer.complete("$nu.", 4);
|
|
|
|
|
2024-01-17 16:40:59 +01:00
|
|
|
assert_eq!(15, suggestions.len());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
let expected: Vec<String> = vec![
|
|
|
|
"config-path".into(),
|
2023-04-07 20:51:09 +02:00
|
|
|
"current-exe".into(),
|
2023-04-14 22:16:00 +02:00
|
|
|
"default-config-dir".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"env-path".into(),
|
2024-01-17 16:40:59 +01:00
|
|
|
"history-enabled".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"history-path".into(),
|
|
|
|
"home-path".into(),
|
2023-03-09 03:59:33 +01:00
|
|
|
"is-interactive".into(),
|
|
|
|
"is-login".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"loginshell-path".into(),
|
|
|
|
"os-info".into(),
|
|
|
|
"pid".into(),
|
2023-06-20 23:33:01 +02:00
|
|
|
"plugin-path".into(),
|
FEATURE: add the startup time to `$nu` (#8353)
# Description
in https://github.com/nushell/nushell/issues/8311 and the discord
server, the idea of moving the default banner from the `rust` source to
the `nushell` standar library has emerged :yum:
however, in order to do this, one need to have access to all the
variables used in the default banner => all of them are accessible
because known constants, except for the startup time of the shell, which
is not anywhere in the shell...
#### this PR adds exactly this, i.e. the new `startup_time` to the `$nu`
variable, which is computed to have the exact same value as the value
shown in the banner.
## the changes
in order to achieve this, i had to
- add `startup_time` as an `i64` to the `EngineState` => this is, to the
best of my knowledge, the easiest way to pass such an information around
down to where the banner startup time is computed and where the `$nu`
variable is evaluated
- add `startup-time` to the `$nu` variable and use the `EngineState`
getter for `startup_time` to show it as a `Value::Duration`
- pass `engine_state` as a `&mut`able argument from `main.rs` down to
`repl.rs` to allow the setter to change the value of `startup_time` =>
without this, the value would not change and would show `-1ns` as the
default value...
- the value of the startup time is computed in `evaluate_repl` in
`repl.rs`, only once at the beginning, and the same value is used in the
default banner :ok_hand:
# User-Facing Changes
one can now access to the same time as shown in the default banner with
```bash
$nu.startup-time
```
# Tests + Formatting
- :green_circle: `cargo fmt --all`
- :green_circle: `cargo clippy --workspace -- -D warnings -D
clippy::unwrap_used -A clippy::needless_collect`
- :green_circle: `cargo test --workspace`
# After Submitting
```
$nothing
```
2023-03-09 21:18:58 +01:00
|
|
|
"startup-time".into(),
|
2022-08-23 16:24:24 +02:00
|
|
|
"temp-path".into(),
|
|
|
|
];
|
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
|
|
|
// Test completions for $nu.h (filter)
|
|
|
|
let suggestions = completer.complete("$nu.h", 5);
|
|
|
|
|
2024-01-17 16:40:59 +01:00
|
|
|
assert_eq!(3, suggestions.len());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
2024-01-17 16:40:59 +01:00
|
|
|
let expected: Vec<String> = vec![
|
|
|
|
"history-enabled".into(),
|
|
|
|
"history-path".into(),
|
|
|
|
"home-path".into(),
|
|
|
|
];
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
2023-04-26 16:15:27 +02:00
|
|
|
// Test completions for $nu.os-info
|
|
|
|
let suggestions = completer.complete("$nu.os-info.", 12);
|
|
|
|
assert_eq!(4, suggestions.len());
|
|
|
|
let expected: Vec<String> = vec![
|
|
|
|
"arch".into(),
|
|
|
|
"family".into(),
|
|
|
|
"kernel_version".into(),
|
|
|
|
"name".into(),
|
|
|
|
];
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
2022-08-23 16:24:24 +02:00
|
|
|
// Test completions for custom var
|
|
|
|
let suggestions = completer.complete("$actor.", 7);
|
|
|
|
|
|
|
|
assert_eq!(2, suggestions.len());
|
|
|
|
|
|
|
|
let expected: Vec<String> = vec!["age".into(), "name".into()];
|
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
|
|
|
// Test completions for custom var (filtering)
|
|
|
|
let suggestions = completer.complete("$actor.n", 8);
|
|
|
|
|
|
|
|
assert_eq!(1, suggestions.len());
|
|
|
|
|
|
|
|
let expected: Vec<String> = vec!["name".into()];
|
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
|
|
|
// Test completions for $env
|
|
|
|
let suggestions = completer.complete("$env.", 5);
|
|
|
|
|
2023-02-09 03:53:46 +01:00
|
|
|
assert_eq!(3, suggestions.len());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
2023-02-09 03:53:46 +01:00
|
|
|
#[cfg(windows)]
|
|
|
|
let expected: Vec<String> = vec!["PWD".into(), "Path".into(), "TEST".into()];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected: Vec<String> = vec!["PATH".into(), "PWD".into(), "TEST".into()];
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
|
|
|
|
// Test completions for $env
|
|
|
|
let suggestions = completer.complete("$env.T", 6);
|
|
|
|
|
|
|
|
assert_eq!(1, suggestions.len());
|
|
|
|
|
|
|
|
let expected: Vec<String> = vec!["TEST".into()];
|
|
|
|
|
|
|
|
// Match results
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_of_command_and_flags() {
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Create an alias
|
|
|
|
let alias = r#"alias ll = ls -l"#;
|
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let suggestions = completer.complete("ll t", 4);
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a\\".to_string(), "test_b\\".to_string()];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_of_basic_command() {
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Create an alias
|
|
|
|
let alias = r#"alias ll = ls "#;
|
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let suggestions = completer.complete("ll t", 4);
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a\\".to_string(), "test_b\\".to_string()];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_of_another_alias() {
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Create an alias
|
|
|
|
let alias = r#"alias ll = ls -la"#;
|
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir.clone()).is_ok());
|
|
|
|
// Create the second alias
|
|
|
|
let alias = r#"alias lf = ll -f"#;
|
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let suggestions = completer.complete("lf t", 4);
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a\\".to_string(), "test_b\\".to_string()];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec!["test_a/".to_string(), "test_b/".to_string()];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_external_completion(block: &str, input: &str) -> Vec<Suggestion> {
|
|
|
|
// Create a new engine
|
|
|
|
let (dir, _, mut engine_state, mut stack) = new_engine();
|
|
|
|
let (_, delta) = {
|
|
|
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
2023-04-07 20:09:38 +02:00
|
|
|
let block = parse(&mut working_set, None, block.as_bytes(), false);
|
2023-04-07 02:35:45 +02:00
|
|
|
assert!(working_set.parse_errors.is_empty());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
(block, working_set.render())
|
|
|
|
};
|
|
|
|
|
|
|
|
assert!(engine_state.merge_delta(delta).is_ok());
|
|
|
|
|
|
|
|
// Merge environment into the permanent state
|
2023-06-04 21:04:28 +02:00
|
|
|
assert!(engine_state.merge_env(&mut stack, &dir).is_ok());
|
2022-08-23 16:24:24 +02:00
|
|
|
|
|
|
|
let latest_block_id = engine_state.num_blocks() - 1;
|
|
|
|
|
|
|
|
// Change config adding the external completer
|
|
|
|
let mut config = engine_state.get_config().clone();
|
|
|
|
config.external_completer = Some(latest_block_id);
|
2023-11-08 20:31:30 +01:00
|
|
|
engine_state.set_config(config);
|
2022-08-23 16:24:24 +02:00
|
|
|
|
Fix typos by codespell (#7600)
# Description
Found via `codespell -S target -L
crate,ser,numer,falsy,ro,te,nd,bu,ndoes,statics,ons,fo,rouge,pard`
# User-Facing Changes
None.
# Tests + Formatting
None and done.
# After Submitting
None.
2022-12-26 08:31:26 +01:00
|
|
|
// Instantiate a new completer
|
2022-08-23 16:24:24 +02:00
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine_state), stack);
|
|
|
|
|
2022-09-25 22:06:13 +02:00
|
|
|
completer.complete(input, input.len())
|
2022-08-23 16:24:24 +02:00
|
|
|
}
|
2022-08-24 21:46:00 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unknown_command_completion() {
|
|
|
|
let (_, _, engine, stack) = new_engine();
|
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
let target_dir = "thiscommanddoesnotexist ";
|
|
|
|
let suggestions = completer.complete(target_dir, target_dir.len());
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-08-24 21:46:00 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-08-24 21:46:00 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions)
|
|
|
|
}
|
2022-09-29 10:43:58 +02:00
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn flagcompletion_triggers_after_cursor(mut completer: NuCompleter) {
|
|
|
|
let suggestions = completer.complete("tst -h", 5);
|
|
|
|
let expected: Vec<String> = 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<String> = 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<String> = 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<String> = 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<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another\\".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion\\".to_string(),
|
2022-09-29 10:43:58 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a\\".to_string(),
|
|
|
|
"test_b\\".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder\\".to_string(),
|
|
|
|
];
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
let expected_paths: Vec<String> = vec![
|
2023-02-22 14:03:48 +01:00
|
|
|
"another/".to_string(),
|
|
|
|
"custom_completion.nu".to_string(),
|
2023-12-19 10:14:34 +01:00
|
|
|
"directory_completion/".to_string(),
|
2022-09-29 10:43:58 +02:00
|
|
|
"nushell".to_string(),
|
|
|
|
"test_a/".to_string(),
|
|
|
|
"test_b/".to_string(),
|
|
|
|
".hidden_file".to_string(),
|
|
|
|
".hidden_folder/".to_string(),
|
|
|
|
];
|
|
|
|
|
|
|
|
match_suggestions(expected_paths, suggestions);
|
|
|
|
}
|
2022-12-21 23:33:26 +01:00
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_custom_completion_positional(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam ", 5);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_custom_completion_long_flag_1(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam --foo=", 11);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_custom_completion_long_flag_2(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam --foo ", 11);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_custom_completion_long_flag_short(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam -f ", 8);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_custom_completion_short_flag(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam -b ", 8);
|
|
|
|
let expected: Vec<String> = vec!["cat".into(), "dog".into(), "eel".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn extern_complete_flags(mut extern_completer: NuCompleter) {
|
|
|
|
let suggestions = extern_completer.complete("spam -", 6);
|
|
|
|
let expected: Vec<String> = vec!["--foo".into(), "-b".into(), "-f".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
2023-01-17 07:30:00 +01:00
|
|
|
|
2023-11-29 23:17:06 +01:00
|
|
|
#[rstest]
|
|
|
|
fn custom_completer_triggers_cursor_before_word(mut custom_completer: NuCompleter) {
|
|
|
|
let suggestions = custom_completer.complete("cmd foo bar", 8);
|
|
|
|
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn custom_completer_triggers_cursor_on_word_left_boundary(mut custom_completer: NuCompleter) {
|
|
|
|
let suggestions = custom_completer.complete("cmd foo bar", 8);
|
|
|
|
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn custom_completer_triggers_cursor_next_to_word(mut custom_completer: NuCompleter) {
|
|
|
|
let suggestions = custom_completer.complete("cmd foo bar", 11);
|
|
|
|
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "bar".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
fn custom_completer_triggers_cursor_after_word(mut custom_completer: NuCompleter) {
|
|
|
|
let suggestions = custom_completer.complete("cmd foo bar ", 12);
|
|
|
|
let expected: Vec<String> = vec!["cmd".into(), "foo".into(), "bar".into(), "".into()];
|
|
|
|
match_suggestions(expected, suggestions);
|
|
|
|
}
|
|
|
|
|
2023-02-18 18:38:29 +01:00
|
|
|
#[ignore = "was reverted, still needs fixing"]
|
2023-01-17 07:30:00 +01:00
|
|
|
#[rstest]
|
2023-02-18 18:38:29 +01:00
|
|
|
fn alias_offset_bug_7648() {
|
2023-01-17 07:30:00 +01:00
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Create an alias
|
|
|
|
let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#;
|
2023-01-27 18:45:57 +01:00
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
2023-01-17 07:30:00 +01:00
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
2023-02-18 18:38:29 +01:00
|
|
|
// Issue #7648
|
2023-01-17 07:30:00 +01:00
|
|
|
// 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);
|
|
|
|
}
|
2023-01-19 11:19:27 +01:00
|
|
|
|
2023-02-18 18:38:29 +01:00
|
|
|
#[ignore = "was reverted, still needs fixing"]
|
2023-01-19 11:19:27 +01:00
|
|
|
#[rstest]
|
|
|
|
fn alias_offset_bug_7754() {
|
|
|
|
let (dir, _, mut engine, mut stack) = new_engine();
|
|
|
|
|
|
|
|
// Create an alias
|
|
|
|
let alias = r#"alias ll = ls -l"#;
|
2023-01-27 18:45:57 +01:00
|
|
|
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
|
2023-01-19 11:19:27 +01:00
|
|
|
|
|
|
|
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack);
|
|
|
|
|
|
|
|
// Issue #7754
|
|
|
|
// Nushell crashes when an alias name is shorter than the alias command
|
|
|
|
// and the alias command contains pipes.
|
|
|
|
// This crashes before PR #7756
|
|
|
|
let _suggestions = completer.complete("ll -a | c", 9);
|
|
|
|
}
|
2023-02-09 03:53:46 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn get_path_env_var_8003() {
|
|
|
|
// Create a new engine
|
|
|
|
let (_, _, engine, _) = new_engine();
|
|
|
|
// Get the path env var in a platform agnostic way
|
|
|
|
let the_path = engine.get_path_env_var();
|
|
|
|
// Make sure it's not empty
|
|
|
|
assert!(the_path.is_some());
|
|
|
|
}
|