From 406df7f208a94e8ac2bfeca4c3bec15fc1120385 Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Sat, 4 May 2024 02:53:15 +0200 Subject: [PATCH 01/15] Avoid taking unnecessary ownership of intermediates (#12740) # Description Judiciously try to avoid allocations/clone by changing the signature of functions - **Don't pass str by value unnecessarily if only read** - **Don't require a vec in `Sandbox::with_files`** - **Remove unnecessary string clone** - **Fixup unnecessary borrow** - **Use `&str` in shape color instead** - **Vec -> Slice** - **Elide string clone** - **Elide `Path` clone** - **Take &str to elide clone in tests** # User-Facing Changes None # Tests + Formatting This touches many tests purely in changing from owned to borrowed/static data --- crates/nu-cli/src/syntax_highlight.rs | 4 +- crates/nu-color-config/src/color_config.rs | 12 +-- crates/nu-color-config/src/shape_color.rs | 8 +- .../src/conversions/into/datetime.rs | 4 +- .../nu-command/src/env/config/config_env.rs | 2 +- crates/nu-command/src/env/config/config_nu.rs | 2 +- crates/nu-command/src/env/config/utils.rs | 4 +- crates/nu-command/src/formats/from/xml.rs | 8 +- crates/nu-command/src/formats/from/yaml.rs | 22 ++--- crates/nu-command/tests/commands/alias.rs | 2 +- crates/nu-command/tests/commands/cd.rs | 2 +- crates/nu-command/tests/commands/complete.rs | 6 +- .../tests/commands/database/into_sqlite.rs | 2 +- crates/nu-command/tests/commands/du.rs | 2 +- crates/nu-command/tests/commands/every.rs | 16 ++-- crates/nu-command/tests/commands/first.rs | 6 +- crates/nu-command/tests/commands/format.rs | 4 +- crates/nu-command/tests/commands/get.rs | 16 ++-- crates/nu-command/tests/commands/glob.rs | 16 ++-- crates/nu-command/tests/commands/help.rs | 24 +++--- crates/nu-command/tests/commands/last.rs | 4 +- crates/nu-command/tests/commands/ls.rs | 64 +++++++-------- crates/nu-command/tests/commands/move_/umv.rs | 60 +++++++------- crates/nu-command/tests/commands/nu_check.rs | 48 +++++------ crates/nu-command/tests/commands/open.rs | 14 ++-- crates/nu-command/tests/commands/parse.rs | 12 +-- .../nu-command/tests/commands/path/exists.rs | 2 +- .../nu-command/tests/commands/path/expand.rs | 20 ++--- .../nu-command/tests/commands/path/type_.rs | 12 +-- crates/nu-command/tests/commands/prepend.rs | 2 +- crates/nu-command/tests/commands/range.rs | 6 +- .../nu-command/tests/commands/redirection.rs | 4 +- crates/nu-command/tests/commands/rm.rs | 62 +++++++------- .../nu-command/tests/commands/run_external.rs | 16 ++-- crates/nu-command/tests/commands/save.rs | 32 ++++---- crates/nu-command/tests/commands/select.rs | 4 +- .../nu-command/tests/commands/source_env.rs | 28 +++---- crates/nu-command/tests/commands/split_by.rs | 2 +- .../nu-command/tests/commands/split_column.rs | 2 +- crates/nu-command/tests/commands/split_row.rs | 2 +- .../tests/commands/str_/into_string.rs | 4 +- crates/nu-command/tests/commands/str_/mod.rs | 26 +++--- crates/nu-command/tests/commands/table.rs | 6 +- crates/nu-command/tests/commands/touch.rs | 12 +-- crates/nu-command/tests/commands/ucp.rs | 64 +++++++-------- crates/nu-command/tests/commands/use_.rs | 16 ++-- crates/nu-command/tests/commands/zip.rs | 2 +- .../tests/format_conversions/csv.rs | 30 +++---- .../tests/format_conversions/json.rs | 12 +-- .../tests/format_conversions/ssv.rs | 6 +- .../tests/format_conversions/tsv.rs | 20 ++--- crates/nu-parser/src/flatten.rs | 82 ++++++++++--------- crates/nu-table/src/types/general.rs | 4 +- crates/nu-test-support/src/macros.rs | 6 +- crates/nu-test-support/src/playground/play.rs | 2 +- tests/modules/mod.rs | 74 ++++++++--------- tests/overlays/mod.rs | 6 +- tests/parsing/mod.rs | 24 +++--- tests/path/canonicalize.rs | 38 ++++----- tests/plugins/core_inc.rs | 12 +-- tests/plugins/formats/ics.rs | 6 +- tests/plugins/formats/ini.rs | 2 +- tests/plugins/formats/vcf.rs | 6 +- tests/plugins/registry_file.rs | 6 +- tests/scope/mod.rs | 6 +- tests/shell/environment/env.rs | 6 +- tests/shell/mod.rs | 22 ++--- tests/shell/pipeline/commands/external.rs | 18 ++-- tests/shell/pipeline/commands/internal.rs | 4 +- 69 files changed, 527 insertions(+), 553 deletions(-) diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index d4bbb7db92..e296943af6 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -88,7 +88,7 @@ impl Highlighter for NuHighlighter { .to_string(); let mut add_colored_token = |shape: &FlatShape, text: String| { - output.push((get_shape_color(shape.to_string(), &self.config), text)); + output.push((get_shape_color(shape.as_str(), &self.config), text)); }; match shape.1 { @@ -128,7 +128,7 @@ impl Highlighter for NuHighlighter { let start = part.start - span.start; let end = part.end - span.start; let text = next_token[start..end].to_string(); - let mut style = get_shape_color(shape.to_string(), &self.config); + let mut style = get_shape_color(shape.as_str(), &self.config); if highlight { style = get_matching_brackets_style(style, &self.config); } diff --git a/crates/nu-color-config/src/color_config.rs b/crates/nu-color-config/src/color_config.rs index 8f25ada576..ad5040893a 100644 --- a/crates/nu-color-config/src/color_config.rs +++ b/crates/nu-color-config/src/color_config.rs @@ -13,7 +13,7 @@ pub fn lookup_ansi_color_style(s: &str) -> Style { .and_then(|c| c.map(|c| c.normal())) .unwrap_or_default() } else if s.starts_with('{') { - color_string_to_nustyle(s.to_string()) + color_string_to_nustyle(s) } else { lookup_style(s) } @@ -74,13 +74,13 @@ fn get_style_from_value(record: &Record) -> Option { } } -fn color_string_to_nustyle(color_string: String) -> Style { +fn color_string_to_nustyle(color_string: &str) -> Style { // eprintln!("color_string: {}", &color_string); if color_string.is_empty() { return Style::default(); } - let nu_style = match nu_json::from_str::(&color_string) { + let nu_style = match nu_json::from_str::(color_string) { Ok(s) => s, Err(_) => return Style::default(), }; @@ -97,13 +97,13 @@ mod tests { #[test] fn test_color_string_to_nustyle_empty_string() { let color_string = String::new(); - let style = color_string_to_nustyle(color_string); + let style = color_string_to_nustyle(&color_string); assert_eq!(style, Style::default()); } #[test] fn test_color_string_to_nustyle_valid_string() { - let color_string = r#"{"fg": "black", "bg": "white", "attr": "b"}"#.to_string(); + let color_string = r#"{"fg": "black", "bg": "white", "attr": "b"}"#; let style = color_string_to_nustyle(color_string); assert_eq!(style.foreground, Some(Color::Black)); assert_eq!(style.background, Some(Color::White)); @@ -112,7 +112,7 @@ mod tests { #[test] fn test_color_string_to_nustyle_invalid_string() { - let color_string = "invalid string".to_string(); + let color_string = "invalid string"; let style = color_string_to_nustyle(color_string); assert_eq!(style, Style::default()); } diff --git a/crates/nu-color-config/src/shape_color.rs b/crates/nu-color-config/src/shape_color.rs index cb896f2bfc..72cc955e0b 100644 --- a/crates/nu-color-config/src/shape_color.rs +++ b/crates/nu-color-config/src/shape_color.rs @@ -3,8 +3,8 @@ use nu_ansi_term::{Color, Style}; use nu_protocol::{Config, Value}; // The default colors for shapes, used when there is no config for them. -pub fn default_shape_color(shape: String) -> Style { - match shape.as_ref() { +pub fn default_shape_color(shape: &str) -> Style { + match shape { "shape_and" => Style::new().fg(Color::Purple).bold(), "shape_binary" => Style::new().fg(Color::Purple).bold(), "shape_block" => Style::new().fg(Color::Blue).bold(), @@ -45,8 +45,8 @@ pub fn default_shape_color(shape: String) -> Style { } } -pub fn get_shape_color(shape: String, conf: &Config) -> Style { - match conf.color_config.get(shape.as_str()) { +pub fn get_shape_color(shape: &str, conf: &Config) -> Style { + match conf.color_config.get(shape) { Some(int_color) => { // Shapes do not use color_config closures, currently. match int_color { diff --git a/crates/nu-command/src/conversions/into/datetime.rs b/crates/nu-command/src/conversions/into/datetime.rs index 157ae95079..af10732aea 100644 --- a/crates/nu-command/src/conversions/into/datetime.rs +++ b/crates/nu-command/src/conversions/into/datetime.rs @@ -39,7 +39,7 @@ impl Zone { Self::Error // Out of range } } - fn from_string(s: String) -> Self { + fn from_string(s: &str) -> Self { match s.to_ascii_lowercase().as_str() { "utc" | "u" => Self::Utc, "local" | "l" => Self::Local, @@ -126,7 +126,7 @@ impl Command for SubCommand { span: zone_offset.span, }), None => timezone.as_ref().map(|zone| Spanned { - item: Zone::from_string(zone.item.clone()), + item: Zone::from_string(&zone.item), span: zone.span, }), }; diff --git a/crates/nu-command/src/env/config/config_env.rs b/crates/nu-command/src/env/config/config_env.rs index 2bcb3bc175..3c8dff487e 100644 --- a/crates/nu-command/src/env/config/config_env.rs +++ b/crates/nu-command/src/env/config/config_env.rs @@ -57,7 +57,7 @@ impl Command for ConfigEnv { let env_vars_str = env_to_strings(engine_state, stack)?; let nu_config = match engine_state.get_config_path("env-path") { - Some(path) => path.clone(), + Some(path) => path, None => { return Err(ShellError::GenericError { error: "Could not find $nu.env-path".into(), diff --git a/crates/nu-command/src/env/config/config_nu.rs b/crates/nu-command/src/env/config/config_nu.rs index 835926fa84..c43d8d0726 100644 --- a/crates/nu-command/src/env/config/config_nu.rs +++ b/crates/nu-command/src/env/config/config_nu.rs @@ -61,7 +61,7 @@ impl Command for ConfigNu { let env_vars_str = env_to_strings(engine_state, stack)?; let nu_config = match engine_state.get_config_path("config-path") { - Some(path) => path.clone(), + Some(path) => path, None => { return Err(ShellError::GenericError { error: "Could not find $nu.config-path".into(), diff --git a/crates/nu-command/src/env/config/utils.rs b/crates/nu-command/src/env/config/utils.rs index 63a323af7b..4b3ea43483 100644 --- a/crates/nu-command/src/env/config/utils.rs +++ b/crates/nu-command/src/env/config/utils.rs @@ -1,10 +1,10 @@ use crate::ExternalCommand; use nu_protocol::{OutDest, Span, Spanned}; -use std::{collections::HashMap, path::PathBuf}; +use std::{collections::HashMap, path::Path}; pub(crate) fn gen_command( span: Span, - config_path: PathBuf, + config_path: &Path, item: String, config_args: Vec, env_vars_str: HashMap, diff --git a/crates/nu-command/src/formats/from/xml.rs b/crates/nu-command/src/formats/from/xml.rs index 5ac94051f6..c3464e7a25 100644 --- a/crates/nu-command/src/formats/from/xml.rs +++ b/crates/nu-command/src/formats/from/xml.rs @@ -197,15 +197,15 @@ fn from_document_to_value(d: &roxmltree::Document, info: &ParsingInfo) -> Value element_to_value(&d.root_element(), info) } -fn from_xml_string_to_value(s: String, info: &ParsingInfo) -> Result { - let parsed = roxmltree::Document::parse(&s)?; +fn from_xml_string_to_value(s: &str, info: &ParsingInfo) -> Result { + let parsed = roxmltree::Document::parse(s)?; Ok(from_document_to_value(&parsed, info)) } fn from_xml(input: PipelineData, info: &ParsingInfo) -> Result { let (concat_string, span, metadata) = input.collect_string_strict(info.span)?; - match from_xml_string_to_value(concat_string, info) { + match from_xml_string_to_value(&concat_string, info) { Ok(x) => Ok(x.into_pipeline_data_with_metadata(metadata)), Err(err) => Err(process_xml_parse_error(err, span)), } @@ -370,7 +370,7 @@ mod tests { keep_comments: false, keep_processing_instructions: false, }; - from_xml_string_to_value(xml.to_string(), &info) + from_xml_string_to_value(xml, &info) } #[test] diff --git a/crates/nu-command/src/formats/from/yaml.rs b/crates/nu-command/src/formats/from/yaml.rs index 5edb8bdac9..74914ed0c8 100644 --- a/crates/nu-command/src/formats/from/yaml.rs +++ b/crates/nu-command/src/formats/from/yaml.rs @@ -185,14 +185,10 @@ fn convert_yaml_value_to_nu_value( }) } -pub fn from_yaml_string_to_value( - s: String, - span: Span, - val_span: Span, -) -> Result { +pub fn from_yaml_string_to_value(s: &str, span: Span, val_span: Span) -> Result { let mut documents = vec![]; - for document in serde_yaml::Deserializer::from_str(&s) { + for document in serde_yaml::Deserializer::from_str(s) { let v: serde_yaml::Value = serde_yaml::Value::deserialize(document).map_err(|x| ShellError::UnsupportedInput { msg: format!("Could not load YAML: {x}"), @@ -238,7 +234,7 @@ pub fn get_examples() -> Vec> { fn from_yaml(input: PipelineData, head: Span) -> Result { let (concat_string, span, metadata) = input.collect_string_strict(head)?; - match from_yaml_string_to_value(concat_string, head, span) { + match from_yaml_string_to_value(&concat_string, head, span) { Ok(x) => Ok(x.into_pipeline_data_with_metadata(metadata)), Err(other) => Err(other), } @@ -274,11 +270,7 @@ mod test { ]; let config = Config::default(); for tc in tt { - let actual = from_yaml_string_to_value( - tc.input.to_owned(), - Span::test_data(), - Span::test_data(), - ); + let actual = from_yaml_string_to_value(tc.input, Span::test_data(), Span::test_data()); if actual.is_err() { assert!( tc.expected.is_err(), @@ -313,11 +305,7 @@ mod test { // table was non-deterministic. It would take a few executions of the YAML conversion to // see this ordering difference. This loop should be far more than enough to catch a regression. for ii in 1..1000 { - let actual = from_yaml_string_to_value( - String::from(test_yaml), - Span::test_data(), - Span::test_data(), - ); + let actual = from_yaml_string_to_value(test_yaml, Span::test_data(), Span::test_data()); let expected: Result = Ok(Value::test_list(vec![ Value::test_record(record! { diff --git a/crates/nu-command/tests/commands/alias.rs b/crates/nu-command/tests/commands/alias.rs index 65fbbc1d4f..03df53ae42 100644 --- a/crates/nu-command/tests/commands/alias.rs +++ b/crates/nu-command/tests/commands/alias.rs @@ -92,7 +92,7 @@ fn alias_wont_recurse() { #[test] fn alias_wont_recurse2() { Playground::setup("alias_wont_recurse2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def eggs [] { spam 'eggs' } diff --git a/crates/nu-command/tests/commands/cd.rs b/crates/nu-command/tests/commands/cd.rs index 9cdafc005a..fa9ea382f2 100644 --- a/crates/nu-command/tests/commands/cd.rs +++ b/crates/nu-command/tests/commands/cd.rs @@ -151,7 +151,7 @@ fn filesystem_change_to_a_directory_containing_spaces() { #[test] fn filesystem_not_a_directory() { Playground::setup("cd_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("ferris_did_it.txt")]); + sandbox.with_files(&[EmptyFile("ferris_did_it.txt")]); let actual = nu!( cwd: dirs.test(), diff --git a/crates/nu-command/tests/commands/complete.rs b/crates/nu-command/tests/commands/complete.rs index c68845ff24..cc398d4c8c 100644 --- a/crates/nu-command/tests/commands/complete.rs +++ b/crates/nu-command/tests/commands/complete.rs @@ -38,7 +38,7 @@ fn capture_error_with_too_much_stderr_not_hang_nushell() { for _ in 0..bytes { large_file_body.push('a'); } - sandbox.with_files(vec![FileWithContent("a_large_file.txt", &large_file_body)]); + sandbox.with_files(&[FileWithContent("a_large_file.txt", &large_file_body)]); let actual = nu!(cwd: dirs.test(), "sh -c 'cat a_large_file.txt 1>&2' | complete | get stderr"); @@ -58,7 +58,7 @@ fn capture_error_with_too_much_stdout_not_hang_nushell() { for _ in 0..bytes { large_file_body.push('a'); } - sandbox.with_files(vec![FileWithContent("a_large_file.txt", &large_file_body)]); + sandbox.with_files(&[FileWithContent("a_large_file.txt", &large_file_body)]); let actual = nu!(cwd: dirs.test(), "sh -c 'cat a_large_file.txt' | complete | get stdout"); @@ -81,7 +81,7 @@ fn capture_error_with_both_stdout_stderr_messages_not_hang_nushell() { "#; let expect_body = "=".repeat(40960); - sandbox.with_files(vec![FileWithContent("test.sh", script_body)]); + sandbox.with_files(&[FileWithContent("test.sh", script_body)]); // check for stdout let actual = nu!(cwd: dirs.test(), "sh test.sh | complete | get stdout | str trim"); diff --git a/crates/nu-command/tests/commands/database/into_sqlite.rs b/crates/nu-command/tests/commands/database/into_sqlite.rs index 6c25be1f9a..595c88dc38 100644 --- a/crates/nu-command/tests/commands/database/into_sqlite.rs +++ b/crates/nu-command/tests/commands/database/into_sqlite.rs @@ -304,7 +304,7 @@ fn into_sqlite_big_insert() { let nuon_path = dirs.test().join(NUON_FILE_NAME); - playground.with_files(vec![Stub::EmptyFile(&nuon_path.to_string_lossy())]); + playground.with_files(&[Stub::EmptyFile(&nuon_path.to_string_lossy())]); let mut expected_rows = Vec::new(); let mut nuon_file = std::fs::OpenOptions::new() diff --git a/crates/nu-command/tests/commands/du.rs b/crates/nu-command/tests/commands/du.rs index b5ec265153..1e22d54f2f 100644 --- a/crates/nu-command/tests/commands/du.rs +++ b/crates/nu-command/tests/commands/du.rs @@ -51,7 +51,7 @@ fn test_du_flag_max_depth() { #[case("a][c")] fn du_files_with_glob_metachars(#[case] src_name: &str) { Playground::setup("du_test_16", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile(src_name)]); + sandbox.with_files(&[EmptyFile(src_name)]); let src = dirs.test().join(src_name); diff --git a/crates/nu-command/tests/commands/every.rs b/crates/nu-command/tests/commands/every.rs index 688790c20a..6c52651512 100644 --- a/crates/nu-command/tests/commands/every.rs +++ b/crates/nu-command/tests/commands/every.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn gets_all_rows_by_every_zero() { Playground::setup("every_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -32,7 +32,7 @@ fn gets_all_rows_by_every_zero() { #[test] fn gets_no_rows_by_every_skip_zero() { Playground::setup("every_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -56,7 +56,7 @@ fn gets_no_rows_by_every_skip_zero() { #[test] fn gets_all_rows_by_every_one() { Playground::setup("every_test_3", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -83,7 +83,7 @@ fn gets_all_rows_by_every_one() { #[test] fn gets_no_rows_by_every_skip_one() { Playground::setup("every_test_4", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -107,7 +107,7 @@ fn gets_no_rows_by_every_skip_one() { #[test] fn gets_first_row_by_every_too_much() { Playground::setup("every_test_5", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -132,7 +132,7 @@ fn gets_first_row_by_every_too_much() { #[test] fn gets_all_rows_except_first_by_every_skip_too_much() { Playground::setup("every_test_6", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -156,7 +156,7 @@ fn gets_all_rows_except_first_by_every_skip_too_much() { #[test] fn gets_every_third_row() { Playground::setup("every_test_7", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), @@ -181,7 +181,7 @@ fn gets_every_third_row() { #[test] fn skips_every_third_row() { Playground::setup("every_test_8", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("amigos.txt"), EmptyFile("arepas.clu"), EmptyFile("los.txt"), diff --git a/crates/nu-command/tests/commands/first.rs b/crates/nu-command/tests/commands/first.rs index b034274db0..e01478f820 100644 --- a/crates/nu-command/tests/commands/first.rs +++ b/crates/nu-command/tests/commands/first.rs @@ -5,7 +5,7 @@ use nu_test_support::playground::Playground; #[test] fn gets_first_rows_by_amount() { Playground::setup("first_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -21,7 +21,7 @@ fn gets_first_rows_by_amount() { #[test] fn gets_all_rows_if_amount_higher_than_all_rows() { Playground::setup("first_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -38,7 +38,7 @@ fn gets_all_rows_if_amount_higher_than_all_rows() { #[test] fn gets_first_row_when_no_amount_given() { Playground::setup("first_test_3", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); + sandbox.with_files(&[EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); // FIXME: We should probably change first to return a one row table instead of a record here let actual = nu!(cwd: dirs.test(), "ls | first | values | length"); diff --git a/crates/nu-command/tests/commands/format.rs b/crates/nu-command/tests/commands/format.rs index 75567a9a30..6b1649c8b5 100644 --- a/crates/nu-command/tests/commands/format.rs +++ b/crates/nu-command/tests/commands/format.rs @@ -65,7 +65,7 @@ fn error_unmatched_brace() { #[test] fn format_filesize_works() { Playground::setup("format_filesize_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -90,7 +90,7 @@ fn format_filesize_works_with_nonempty_files() { Playground::setup( "format_filesize_works_with_nonempty_files", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "sample.toml", r#" [dependency] diff --git a/crates/nu-command/tests/commands/get.rs b/crates/nu-command/tests/commands/get.rs index 4be0c76a6e..049b5b2899 100644 --- a/crates/nu-command/tests/commands/get.rs +++ b/crates/nu-command/tests/commands/get.rs @@ -17,7 +17,7 @@ fn simple_get_list() { #[test] fn fetches_a_row() { Playground::setup("get_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" nu_party_venue = "zion" @@ -33,7 +33,7 @@ fn fetches_a_row() { #[test] fn fetches_by_index() { Playground::setup("get_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -53,7 +53,7 @@ fn fetches_by_index() { #[test] fn fetches_by_column_path() { Playground::setup("get_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -70,7 +70,7 @@ fn fetches_by_column_path() { #[test] fn column_paths_are_either_double_quoted_or_regular_unquoted_words_separated_by_dot() { Playground::setup("get_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -88,7 +88,7 @@ fn column_paths_are_either_double_quoted_or_regular_unquoted_words_separated_by_ #[test] fn fetches_more_than_one_column_path() { Playground::setup("get_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [[fortune_tellers]] @@ -121,7 +121,7 @@ fn fetches_more_than_one_column_path() { #[test] fn errors_fetching_by_column_not_present() { Playground::setup("get_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [tacos] @@ -141,7 +141,7 @@ fn errors_fetching_by_column_not_present() { #[test] fn errors_fetching_by_column_using_a_number() { Playground::setup("get_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [spanish_lesson] @@ -158,7 +158,7 @@ fn errors_fetching_by_column_using_a_number() { #[test] fn errors_fetching_by_index_out_of_bounds() { Playground::setup("get_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [spanish_lesson] diff --git a/crates/nu-command/tests/commands/glob.rs b/crates/nu-command/tests/commands/glob.rs index 0ab35158b0..235896f63d 100644 --- a/crates/nu-command/tests/commands/glob.rs +++ b/crates/nu-command/tests/commands/glob.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; #[test] fn empty_glob_pattern_triggers_error() { Playground::setup("glob_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -25,7 +25,7 @@ fn empty_glob_pattern_triggers_error() { #[test] fn nonempty_glob_lists_matching_paths() { Playground::setup("glob_sanity_star", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -43,13 +43,13 @@ fn nonempty_glob_lists_matching_paths() { #[test] fn glob_subdirs() { Playground::setup("glob_subdirs", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), ]); sandbox.mkdir("children"); - sandbox.within("children").with_files(vec![ + sandbox.within("children").with_files(&[ EmptyFile("timothy.txt"), EmptyFile("tiffany.txt"), EmptyFile("trish.txt"), @@ -70,13 +70,13 @@ fn glob_subdirs() { #[test] fn glob_subdirs_ignore_dirs() { Playground::setup("glob_subdirs_ignore_directories", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), ]); sandbox.mkdir("children"); - sandbox.within("children").with_files(vec![ + sandbox.within("children").with_files(&[ EmptyFile("timothy.txt"), EmptyFile("tiffany.txt"), EmptyFile("trish.txt"), @@ -97,13 +97,13 @@ fn glob_subdirs_ignore_dirs() { #[test] fn glob_ignore_files() { Playground::setup("glob_ignore_files", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), ]); sandbox.mkdir("children"); - sandbox.within("children").with_files(vec![ + sandbox.within("children").with_files(&[ EmptyFile("timothy.txt"), EmptyFile("tiffany.txt"), EmptyFile("trish.txt"), diff --git a/crates/nu-command/tests/commands/help.rs b/crates/nu-command/tests/commands/help.rs index 50367e42fd..26e4a92b26 100644 --- a/crates/nu-command/tests/commands/help.rs +++ b/crates/nu-command/tests/commands/help.rs @@ -38,7 +38,7 @@ fn help_aliases() { #[test] fn help_alias_usage_1() { Playground::setup("help_alias_usage_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -70,7 +70,7 @@ fn help_alias_usage_2() { #[test] fn help_alias_usage_3() { Playground::setup("help_alias_usage_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -92,7 +92,7 @@ fn help_alias_usage_3() { #[test] fn help_alias_name() { Playground::setup("help_alias_name", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -113,7 +113,7 @@ fn help_alias_name() { #[test] fn help_alias_name_f() { Playground::setup("help_alias_name_f", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -132,7 +132,7 @@ fn help_alias_name_f() { #[test] fn help_export_alias_name_single_word() { Playground::setup("help_export_alias_name_single_word", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -153,7 +153,7 @@ fn help_export_alias_name_single_word() { #[test] fn help_export_alias_name_multi_word() { Playground::setup("help_export_alias_name_multi_word", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -174,7 +174,7 @@ fn help_export_alias_name_multi_word() { #[test] fn help_module_usage_1() { Playground::setup("help_module_usage", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -199,7 +199,7 @@ fn help_module_usage_1() { #[test] fn help_module_name() { Playground::setup("help_module_name", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # line1 @@ -222,7 +222,7 @@ fn help_module_name() { #[test] fn help_module_sorted_decls() { Playground::setup("help_module_sorted_decls", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" module SPAM { @@ -242,7 +242,7 @@ fn help_module_sorted_decls() { #[test] fn help_module_sorted_aliases() { Playground::setup("help_module_sorted_aliases", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" module SPAM { @@ -262,7 +262,7 @@ fn help_module_sorted_aliases() { #[test] fn help_usage_extra_usage_command() { Playground::setup("help_usage_extra_usage_command", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # module_line1 @@ -299,7 +299,7 @@ fn help_usage_extra_usage_command() { #[test] fn help_usage_extra_usage_alias() { Playground::setup("help_usage_extra_usage_alias", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "spam.nu", r#" # module_line1 diff --git a/crates/nu-command/tests/commands/last.rs b/crates/nu-command/tests/commands/last.rs index f842f26520..b0c67e49be 100644 --- a/crates/nu-command/tests/commands/last.rs +++ b/crates/nu-command/tests/commands/last.rs @@ -15,7 +15,7 @@ fn gets_the_last_row() { #[test] fn gets_last_rows_by_amount() { Playground::setup("last_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -31,7 +31,7 @@ fn gets_last_rows_by_amount() { #[test] fn gets_last_row_when_no_amount_given() { Playground::setup("last_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); + sandbox.with_files(&[EmptyFile("caballeros.txt"), EmptyFile("arepas.clu")]); // FIXME: We should probably change last to return a one row table instead of a record here let actual = nu!(cwd: dirs.test(), "ls | last | values | length"); diff --git a/crates/nu-command/tests/commands/ls.rs b/crates/nu-command/tests/commands/ls.rs index 61afe355e5..8ccdcfaf93 100644 --- a/crates/nu-command/tests/commands/ls.rs +++ b/crates/nu-command/tests/commands/ls.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn lists_regular_files() { Playground::setup("ls_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -26,7 +26,7 @@ fn lists_regular_files() { #[test] fn lists_regular_files_using_asterisk_wildcard() { Playground::setup("ls_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -56,11 +56,11 @@ fn lists_regular_files_in_special_folder() { .mkdir("abcd") .mkdir("abcd/*") .mkdir("abcd/?") - .with_files(vec![EmptyFile("[abcd]/test.txt")]) - .with_files(vec![EmptyFile("abcd]/test.txt")]) - .with_files(vec![EmptyFile("abcd/*/test.txt")]) - .with_files(vec![EmptyFile("abcd/?/test.txt")]) - .with_files(vec![EmptyFile("abcd/?/test2.txt")]); + .with_files(&[EmptyFile("[abcd]/test.txt")]) + .with_files(&[EmptyFile("abcd]/test.txt")]) + .with_files(&[EmptyFile("abcd/*/test.txt")]) + .with_files(&[EmptyFile("abcd/?/test.txt")]) + .with_files(&[EmptyFile("abcd/?/test2.txt")]); let actual = nu!( cwd: dirs.test().join("abcd]"), format!(r#"ls | length"#)); @@ -119,7 +119,7 @@ fn lists_regular_files_in_special_folder() { #[case("'[bbcd].txt'", 1)] fn lists_regular_files_using_question_mark(#[case] command: &str, #[case] expected: usize) { Playground::setup("ls_test_3", |dirs, sandbox| { - sandbox.mkdir("abcd").mkdir("bbcd").with_files(vec![ + sandbox.mkdir("abcd").mkdir("bbcd").with_files(&[ EmptyFile("abcd/xy.txt"), EmptyFile("bbcd/yy.txt"), EmptyFile("[abcd].txt"), @@ -141,7 +141,7 @@ fn lists_regular_files_using_question_mark(#[case] command: &str, #[case] expect #[test] fn lists_regular_files_using_question_mark_wildcard() { Playground::setup("ls_test_3", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.10.txt"), EmptyFile("jt.10.txt"), EmptyFile("andres.10.txt"), @@ -164,11 +164,11 @@ fn lists_regular_files_using_question_mark_wildcard() { fn lists_all_files_in_directories_from_stream() { Playground::setup("ls_test_4", |dirs, sandbox| { sandbox - .with_files(vec![EmptyFile("root1.txt"), EmptyFile("root2.txt")]) + .with_files(&[EmptyFile("root1.txt"), EmptyFile("root2.txt")]) .within("dir_a") - .with_files(vec![EmptyFile("yehuda.10.txt"), EmptyFile("jt10.txt")]) + .with_files(&[EmptyFile("yehuda.10.txt"), EmptyFile("jt10.txt")]) .within("dir_b") - .with_files(vec![ + .with_files(&[ EmptyFile("andres.10.txt"), EmptyFile("chicken_not_to_be_picked_up.100.txt"), ]); @@ -206,7 +206,7 @@ fn does_not_fail_if_glob_matches_empty_directory() { #[test] fn fails_when_glob_doesnt_match() { Playground::setup("ls_test_5", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("root1.txt"), EmptyFile("root2.txt")]); + sandbox.with_files(&[EmptyFile("root1.txt"), EmptyFile("root2.txt")]); let actual = nu!( cwd: dirs.test(), @@ -220,7 +220,7 @@ fn fails_when_glob_doesnt_match() { #[test] fn list_files_from_two_parents_up_using_multiple_dots() { Playground::setup("ls_test_6", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yahuda.yaml"), EmptyFile("jtjson"), EmptyFile("andres.xml"), @@ -243,7 +243,7 @@ fn list_files_from_two_parents_up_using_multiple_dots() { #[test] fn lists_hidden_file_when_explicitly_specified() { Playground::setup("ls_test_7", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -267,19 +267,19 @@ fn lists_hidden_file_when_explicitly_specified() { fn lists_all_hidden_files_when_glob_contains_dot() { Playground::setup("ls_test_8", |dirs, sandbox| { sandbox - .with_files(vec![ + .with_files(&[ EmptyFile("root1.txt"), EmptyFile("root2.txt"), EmptyFile(".dotfile1"), ]) .within("dir_a") - .with_files(vec![ + .with_files(&[ EmptyFile("yehuda.10.txt"), EmptyFile("jt10.txt"), EmptyFile(".dotfile2"), ]) .within("dir_b") - .with_files(vec![ + .with_files(&[ EmptyFile("andres.10.txt"), EmptyFile("chicken_not_to_be_picked_up.100.txt"), EmptyFile(".dotfile3"), @@ -304,19 +304,19 @@ fn lists_all_hidden_files_when_glob_contains_dot() { fn lists_all_hidden_files_when_glob_does_not_contain_dot() { Playground::setup("ls_test_8", |dirs, sandbox| { sandbox - .with_files(vec![ + .with_files(&[ EmptyFile("root1.txt"), EmptyFile("root2.txt"), EmptyFile(".dotfile1"), ]) .within("dir_a") - .with_files(vec![ + .with_files(&[ EmptyFile("yehuda.10.txt"), EmptyFile("jt10.txt"), EmptyFile(".dotfile2"), ]) .within(".dir_b") - .with_files(vec![ + .with_files(&[ EmptyFile("andres.10.txt"), EmptyFile("chicken_not_to_be_picked_up.100.txt"), EmptyFile(".dotfile3"), @@ -340,7 +340,7 @@ fn lists_all_hidden_files_when_glob_does_not_contain_dot() { #[cfg(unix)] fn glob_with_hidden_directory() { Playground::setup("ls_test_8", |dirs, sandbox| { - sandbox.within(".dir_b").with_files(vec![ + sandbox.within(".dir_b").with_files(&[ EmptyFile("andres.10.txt"), EmptyFile("chicken_not_to_be_picked_up.100.txt"), EmptyFile(".dotfile3"), @@ -376,7 +376,7 @@ fn fails_with_ls_to_dir_without_permission() { Playground::setup("ls_test_1", |dirs, sandbox| { sandbox .within("dir_a") - .with_files(vec![EmptyFile("yehuda.11.txt"), EmptyFile("jt10.txt")]); + .with_files(&[EmptyFile("yehuda.11.txt"), EmptyFile("jt10.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -404,7 +404,7 @@ fn fails_with_ls_to_dir_without_permission() { #[test] fn lists_files_including_starting_with_dot() { Playground::setup("ls_test_9", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -427,7 +427,7 @@ fn lists_files_including_starting_with_dot() { #[test] fn list_all_columns() { Playground::setup("ls_test_all_columns", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("Leonardo.yaml"), EmptyFile("Raphael.json"), EmptyFile("Donatello.xml"), @@ -486,7 +486,7 @@ fn lists_with_directory_flag() { Playground::setup("ls_test_flag_directory_1", |dirs, sandbox| { sandbox .within("dir_files") - .with_files(vec![EmptyFile("nushell.json")]) + .with_files(&[EmptyFile("nushell.json")]) .within("dir_empty"); let actual = nu!( cwd: dirs.test(), pipeline( @@ -514,7 +514,7 @@ fn lists_with_directory_flag_without_argument() { Playground::setup("ls_test_flag_directory_2", |dirs, sandbox| { sandbox .within("dir_files") - .with_files(vec![EmptyFile("nushell.json")]) + .with_files(&[EmptyFile("nushell.json")]) .within("dir_empty"); // Test if there are some files in the current directory let actual = nu!( @@ -631,7 +631,7 @@ fn list_directory_contains_invalid_utf8() { #[test] fn list_ignores_ansi() { Playground::setup("ls_test_ansi", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), @@ -662,7 +662,7 @@ fn list_unknown_flag() { fn list_flag_false() { // Check that ls flags respect explicit values Playground::setup("ls_test_false_flag", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile(".hidden"), EmptyFile("normal"), EmptyFile("another_normal"), @@ -705,7 +705,7 @@ fn list_flag_false() { #[test] fn list_empty_string() { Playground::setup("ls_empty_string", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("yehuda.txt")]); + sandbox.with_files(&[EmptyFile("yehuda.txt")]); let actual = nu!(cwd: dirs.test(), "ls ''"); assert!(actual.err.contains("does not exist")); @@ -717,7 +717,7 @@ fn list_with_tilde() { Playground::setup("ls_tilde", |dirs, sandbox| { sandbox .within("~tilde") - .with_files(vec![EmptyFile("f1.txt"), EmptyFile("f2.txt")]); + .with_files(&[EmptyFile("f1.txt"), EmptyFile("f2.txt")]); let actual = nu!(cwd: dirs.test(), "ls '~tilde'"); assert!(actual.out.contains("f1.txt")); @@ -737,7 +737,7 @@ fn list_with_tilde() { #[test] fn list_with_multiple_path() { Playground::setup("ls_multiple_path", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("f1.txt"), EmptyFile("f2.txt"), EmptyFile("f3.txt"), diff --git a/crates/nu-command/tests/commands/move_/umv.rs b/crates/nu-command/tests/commands/move_/umv.rs index 0d47fe3146..0c96c88a36 100644 --- a/crates/nu-command/tests/commands/move_/umv.rs +++ b/crates/nu-command/tests/commands/move_/umv.rs @@ -8,7 +8,7 @@ use std::path::Path; fn moves_a_file() { Playground::setup("umv_test_1", |dirs, sandbox| { sandbox - .with_files(vec![EmptyFile("andres.txt")]) + .with_files(&[EmptyFile("andres.txt")]) .mkdir("expected"); let original = dirs.test().join("andres.txt"); @@ -27,7 +27,7 @@ fn moves_a_file() { #[test] fn overwrites_if_moving_to_existing_file_and_force_provided() { Playground::setup("umv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("andres.txt"), EmptyFile("jttxt")]); + sandbox.with_files(&[EmptyFile("andres.txt"), EmptyFile("jttxt")]); let original = dirs.test().join("andres.txt"); let expected = dirs.test().join("jttxt"); @@ -63,9 +63,7 @@ fn moves_a_directory() { #[test] fn moves_the_file_inside_directory_if_path_to_move_is_existing_directory() { Playground::setup("umv_test_4", |dirs, sandbox| { - sandbox - .with_files(vec![EmptyFile("jttxt")]) - .mkdir("expected"); + sandbox.with_files(&[EmptyFile("jttxt")]).mkdir("expected"); let original_dir = dirs.test().join("jttxt"); let expected = dirs.test().join("expected/jttxt"); @@ -85,7 +83,7 @@ fn moves_the_directory_inside_directory_if_path_to_move_is_existing_directory() Playground::setup("umv_test_5", |dirs, sandbox| { sandbox .within("contributors") - .with_files(vec![EmptyFile("jttxt")]) + .with_files(&[EmptyFile("jttxt")]) .mkdir("expected"); let original_dir = dirs.test().join("contributors"); @@ -107,7 +105,7 @@ fn moves_using_path_with_wildcard() { Playground::setup("umv_test_7", |dirs, sandbox| { sandbox .within("originals") - .with_files(vec![ + .with_files(&[ EmptyFile("andres.ini"), EmptyFile("caco3_plastics.csv"), EmptyFile("cargo_sample.toml"), @@ -138,7 +136,7 @@ fn moves_using_a_glob() { Playground::setup("umv_test_8", |dirs, sandbox| { sandbox .within("meals") - .with_files(vec![ + .with_files(&[ EmptyFile("arepa.txt"), EmptyFile("empanada.txt"), EmptyFile("taquiza.txt"), @@ -166,11 +164,11 @@ fn moves_a_directory_with_files() { sandbox .mkdir("vehicles/car") .mkdir("vehicles/bicycle") - .with_files(vec![ + .with_files(&[ EmptyFile("vehicles/car/car1.txt"), EmptyFile("vehicles/car/car2.txt"), ]) - .with_files(vec![ + .with_files(&[ EmptyFile("vehicles/bicycle/bicycle1.txt"), EmptyFile("vehicles/bicycle/bicycle2.txt"), ]); @@ -213,7 +211,7 @@ fn errors_if_source_doesnt_exist() { #[ignore = "GNU/uutils overwrites rather than error out"] fn error_if_moving_to_existing_file_without_force() { Playground::setup("umv_test_10_0", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("andres.txt"), EmptyFile("jttxt")]); + sandbox.with_files(&[EmptyFile("andres.txt"), EmptyFile("jttxt")]); let actual = nu!( cwd: dirs.test(), @@ -226,7 +224,7 @@ fn error_if_moving_to_existing_file_without_force() { #[test] fn errors_if_destination_doesnt_exist() { Playground::setup("umv_test_10_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("empty.txt")]); + sandbox.with_files(&[EmptyFile("empty.txt")]); let actual = nu!( cwd: dirs.test(), @@ -241,7 +239,7 @@ fn errors_if_destination_doesnt_exist() { #[ignore = "GNU/uutils doesnt expand, rather cannot stat 'file?.txt'"] fn errors_if_multiple_sources_but_destination_not_a_directory() { Playground::setup("umv_test_10_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("file1.txt"), EmptyFile("file2.txt"), EmptyFile("file3.txt"), @@ -261,9 +259,7 @@ fn errors_if_multiple_sources_but_destination_not_a_directory() { #[test] fn errors_if_renaming_directory_to_an_existing_file() { Playground::setup("umv_test_10_3", |dirs, sandbox| { - sandbox - .mkdir("mydir") - .with_files(vec![EmptyFile("empty.txt")]); + sandbox.mkdir("mydir").with_files(&[EmptyFile("empty.txt")]); let actual = nu!( cwd: dirs.test(), @@ -293,7 +289,7 @@ fn does_not_error_on_relative_parent_path() { Playground::setup("umv_test_11", |dirs, sandbox| { sandbox .mkdir("first") - .with_files(vec![EmptyFile("first/william_hartnell.txt")]); + .with_files(&[EmptyFile("first/william_hartnell.txt")]); let original = dirs.test().join("first/william_hartnell.txt"); let expected = dirs.test().join("william_hartnell.txt"); @@ -311,7 +307,7 @@ fn does_not_error_on_relative_parent_path() { #[test] fn move_files_using_glob_two_parents_up_using_multiple_dots() { Playground::setup("umv_test_12", |dirs, sandbox| { - sandbox.within("foo").within("bar").with_files(vec![ + sandbox.within("foo").within("bar").with_files(&[ EmptyFile("jtjson"), EmptyFile("andres.xml"), EmptyFile("yehuda.yaml"), @@ -345,7 +341,7 @@ fn move_files_using_glob_two_parents_up_using_multiple_dots() { #[test] fn move_file_from_two_parents_up_using_multiple_dots_to_current_dir() { Playground::setup("cp_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("hello_there")]); + sandbox.with_files(&[EmptyFile("hello_there")]); sandbox.within("foo").mkdir("bar"); nu!( @@ -380,7 +376,7 @@ fn does_not_error_when_some_file_is_moving_into_itself() { #[test] fn mv_ignores_ansi() { Playground::setup("umv_test_ansi", |_dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("test.txt")]); + sandbox.with_files(&[EmptyFile("test.txt")]); let actual = nu!( cwd: sandbox.cwd(), r#" @@ -420,7 +416,7 @@ fn mv_change_case_of_directory() { Playground::setup("mv_change_case_of_directory", |dirs, sandbox| { sandbox .mkdir("somedir") - .with_files(vec![EmptyFile("somedir/somefile.txt")]); + .with_files(&[EmptyFile("somedir/somefile.txt")]); let original_dir = String::from("somedir"); let new_dir = String::from("SomeDir"); @@ -459,7 +455,7 @@ fn mv_change_case_of_directory() { // but fail on both macOS and Windows. fn mv_change_case_of_file() { Playground::setup("mv_change_case_of_file", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("somefile.txt")]); + sandbox.with_files(&[EmptyFile("somefile.txt")]); let original_file_name = String::from("somefile.txt"); let new_file_name = String::from("SomeFile.txt"); @@ -489,7 +485,7 @@ fn mv_change_case_of_file() { #[ignore = "Update not supported..remove later"] fn mv_with_update_flag() { Playground::setup("umv_with_update_flag", |_dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("valid.txt"), FileWithContent("newer_valid.txt", "body"), ]); @@ -502,12 +498,12 @@ fn mv_with_update_flag() { // create a file after assert to make sure that newest_valid.txt is newest std::thread::sleep(std::time::Duration::from_secs(1)); - sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); + sandbox.with_files(&[FileWithContent("newest_valid.txt", "newest_body")]); let actual = nu!(cwd: sandbox.cwd(), "mv -uf newest_valid.txt valid.txt; open valid.txt"); assert_eq!(actual.out, "newest_body"); // when destination doesn't exist - sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); + sandbox.with_files(&[FileWithContent("newest_valid.txt", "newest_body")]); let actual = nu!(cwd: sandbox.cwd(), "mv -uf newest_valid.txt des_missing.txt; open des_missing.txt"); assert_eq!(actual.out, "newest_body"); }); @@ -518,8 +514,8 @@ fn test_mv_no_clobber() { Playground::setup("umv_test_13", |dirs, sandbox| { let file_a = "test_mv_no_clobber_file_a"; let file_b = "test_mv_no_clobber_file_b"; - sandbox.with_files(vec![EmptyFile(file_a)]); - sandbox.with_files(vec![EmptyFile(file_b)]); + sandbox.with_files(&[EmptyFile(file_a)]); + sandbox.with_files(&[EmptyFile(file_b)]); let actual = nu!( cwd: dirs.test(), @@ -566,7 +562,7 @@ fn mv_with_no_target() { #[case("a][c")] fn mv_files_with_glob_metachars(#[case] src_name: &str) { Playground::setup("umv_test_16", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( src_name, "What is the sound of one hand clapping?", )]); @@ -592,7 +588,7 @@ fn mv_files_with_glob_metachars(#[case] src_name: &str) { #[case("a][c")] fn mv_files_with_glob_metachars_when_input_are_variables(#[case] src_name: &str) { Playground::setup("umv_test_18", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( src_name, "What is the sound of one hand clapping?", )]); @@ -626,7 +622,7 @@ fn mv_with_cd() { Playground::setup("umv_test_17", |_dirs, sandbox| { sandbox .mkdir("tmp_dir") - .with_files(vec![FileWithContent("tmp_dir/file.txt", "body")]); + .with_files(&[FileWithContent("tmp_dir/file.txt", "body")]); let actual = nu!( cwd: sandbox.cwd(), @@ -642,7 +638,7 @@ fn test_cp_inside_glob_metachars_dir() { let sub_dir = "test[]"; sandbox .within(sub_dir) - .with_files(vec![FileWithContent("test_file.txt", "hello")]); + .with_files(&[FileWithContent("test_file.txt", "hello")]); let actual = nu!( cwd: dirs.test().join(sub_dir), @@ -661,7 +657,7 @@ fn test_cp_inside_glob_metachars_dir() { #[test] fn mv_with_tilde() { Playground::setup("mv_tilde", |dirs, sandbox| { - sandbox.within("~tilde").with_files(vec![ + sandbox.within("~tilde").with_files(&[ EmptyFile("f1.txt"), EmptyFile("f2.txt"), EmptyFile("f3.txt"), diff --git a/crates/nu-command/tests/commands/nu_check.rs b/crates/nu-command/tests/commands/nu_check.rs index c8c8254411..ee8bf32c24 100644 --- a/crates/nu-command/tests/commands/nu_check.rs +++ b/crates/nu-command/tests/commands/nu_check.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn parse_script_success() { Playground::setup("nu_check_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "script.nu", r#" greet "world" @@ -30,7 +30,7 @@ fn parse_script_success() { #[test] fn parse_script_with_wrong_type() { Playground::setup("nu_check_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "script.nu", r#" greet "world" @@ -54,7 +54,7 @@ fn parse_script_with_wrong_type() { #[test] fn parse_script_failure() { Playground::setup("nu_check_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "script.nu", r#" greet "world" @@ -79,7 +79,7 @@ fn parse_script_failure() { #[test] fn parse_module_success() { Playground::setup("nu_check_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -108,7 +108,7 @@ fn parse_module_success() { #[test] fn parse_module_with_wrong_type() { Playground::setup("nu_check_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -136,7 +136,7 @@ fn parse_module_with_wrong_type() { #[test] fn parse_module_failure() { Playground::setup("nu_check_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -179,7 +179,7 @@ fn file_not_exist() { #[test] fn parse_module_success_2() { Playground::setup("nu_check_test_10", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -202,7 +202,7 @@ fn parse_module_success_2() { #[test] fn parse_script_success_with_raw_stream() { Playground::setup("nu_check_test_11", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "script.nu", r#" greet "world" @@ -227,7 +227,7 @@ fn parse_script_success_with_raw_stream() { #[test] fn parse_module_success_with_raw_stream() { Playground::setup("nu_check_test_12", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -285,7 +285,7 @@ fn parse_string_as_script() { #[test] fn parse_module_success_with_internal_stream() { Playground::setup("nu_check_test_15", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" # foo.nu @@ -314,7 +314,7 @@ fn parse_module_success_with_internal_stream() { #[test] fn parse_script_success_with_complex_internal_stream() { Playground::setup("nu_check_test_16", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -363,7 +363,7 @@ fn parse_script_success_with_complex_internal_stream() { #[test] fn parse_script_failure_with_complex_internal_stream() { Playground::setup("nu_check_test_17", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -412,7 +412,7 @@ fn parse_script_failure_with_complex_internal_stream() { #[test] fn parse_script_success_with_complex_external_stream() { Playground::setup("nu_check_test_18", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -461,7 +461,7 @@ fn parse_script_success_with_complex_external_stream() { #[test] fn parse_module_success_with_complex_external_stream() { Playground::setup("nu_check_test_19", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -510,7 +510,7 @@ fn parse_module_success_with_complex_external_stream() { #[test] fn parse_with_flag_success_for_complex_external_stream() { Playground::setup("nu_check_test_20", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -559,7 +559,7 @@ fn parse_with_flag_success_for_complex_external_stream() { #[test] fn parse_with_flag_failure_for_complex_external_stream() { Playground::setup("nu_check_test_21", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -608,7 +608,7 @@ fn parse_with_flag_failure_for_complex_external_stream() { #[test] fn parse_with_flag_failure_for_complex_list_stream() { Playground::setup("nu_check_test_22", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "grep.nu", r#" #grep for nu @@ -659,7 +659,7 @@ fn parse_script_with_nested_scripts_success() { Playground::setup("nu_check_test_24", |dirs, sandbox| { sandbox .mkdir("lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol.nu", r#" source-env ../foo.nu @@ -667,13 +667,13 @@ fn parse_script_with_nested_scripts_success() { overlay use ../lol/lol_shell.nu "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol_shell.nu", r#" export def ls [] { "lol" } "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" $env.FOO = 'foo' @@ -696,13 +696,13 @@ fn nu_check_respects_file_pwd() { Playground::setup("nu_check_test_25", |dirs, sandbox| { sandbox .mkdir("lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol.nu", r#" $env.RETURN = (nu-check ../foo.nu) "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" echo 'foo' @@ -725,14 +725,14 @@ fn nu_check_module_dir() { Playground::setup("nu_check_test_26", |dirs, sandbox| { sandbox .mkdir("lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/mod.nu", r#" export module foo.nu export def main [] { 'lol' } "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/foo.nu", r#" export def main [] { 'lol foo' } diff --git a/crates/nu-command/tests/commands/open.rs b/crates/nu-command/tests/commands/open.rs index 434bdbb764..f857718c72 100644 --- a/crates/nu-command/tests/commands/open.rs +++ b/crates/nu-command/tests/commands/open.rs @@ -8,7 +8,7 @@ use rstest::rstest; #[test] fn parses_file_with_uppercase_extension() { Playground::setup("open_test_uppercase_extension", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "nu.zion.JSON", r#"{ "glossary": { @@ -38,7 +38,7 @@ fn parses_file_with_uppercase_extension() { #[test] fn parses_file_with_multiple_extensions() { Playground::setup("open_test_multiple_extensions", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ FileWithContent("file.tar.gz", "this is a tar.gz file"), FileWithContent("file.tar.xz", "this is a tar.xz file"), ]); @@ -77,7 +77,7 @@ fn parses_file_with_multiple_extensions() { #[test] fn parses_dotfile() { Playground::setup("open_test_dotfile", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( ".gitignore", r#" /target/ @@ -101,7 +101,7 @@ fn parses_dotfile() { #[test] fn parses_csv() { Playground::setup("open_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "nu.zion.csv", r#" author,lang,source @@ -318,7 +318,7 @@ fn test_open_block_command() { #[test] fn open_ignore_ansi() { Playground::setup("open_test_ansi", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("nu.zion.txt")]); + sandbox.with_files(&[EmptyFile("nu.zion.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -345,7 +345,7 @@ fn open_no_parameter() { #[case("a][c")] fn open_files_with_glob_metachars(#[case] src_name: &str) { Playground::setup("open_test_with_glob_metachars", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent(src_name, "hello")]); + sandbox.with_files(&[FileWithContent(src_name, "hello")]); let src = dirs.test().join(src_name); @@ -384,7 +384,7 @@ fn open_files_inside_glob_metachars_dir() { let sub_dir = "test[]"; sandbox .within(sub_dir) - .with_files(vec![FileWithContent("test_file.txt", "hello")]); + .with_files(&[FileWithContent("test_file.txt", "hello")]); let actual = nu!( cwd: dirs.test().join(sub_dir), diff --git a/crates/nu-command/tests/commands/parse.rs b/crates/nu-command/tests/commands/parse.rs index 93a2b395da..7f98eed83d 100644 --- a/crates/nu-command/tests/commands/parse.rs +++ b/crates/nu-command/tests/commands/parse.rs @@ -8,7 +8,7 @@ mod simple { #[test] fn extracts_fields_from_the_given_the_pattern() { Playground::setup("parse_test_1", |dirs, sandbox| { - sandbox.with_files(vec![Stub::FileWithContentToBeTrimmed( + sandbox.with_files(&[Stub::FileWithContentToBeTrimmed( "key_value_separated_arepa_ingredients.txt", r#" VAR1=Cheese @@ -117,7 +117,7 @@ mod regex { #[test] fn extracts_fields_with_all_named_groups() { Playground::setup("parse_test_regex_1", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); + sandbox.with_files(&nushell_git_log_oneline()); let actual = nu!( cwd: dirs.test(), pipeline( @@ -136,7 +136,7 @@ mod regex { #[test] fn extracts_fields_with_all_unnamed_groups() { Playground::setup("parse_test_regex_2", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); + sandbox.with_files(&nushell_git_log_oneline()); let actual = nu!( cwd: dirs.test(), pipeline( @@ -155,7 +155,7 @@ mod regex { #[test] fn extracts_fields_with_named_and_unnamed_groups() { Playground::setup("parse_test_regex_3", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); + sandbox.with_files(&nushell_git_log_oneline()); let actual = nu!( cwd: dirs.test(), pipeline( @@ -174,7 +174,7 @@ mod regex { #[test] fn errors_with_invalid_regex() { Playground::setup("parse_test_regex_1", |dirs, sandbox| { - sandbox.with_files(nushell_git_log_oneline()); + sandbox.with_files(&nushell_git_log_oneline()); let actual = nu!( cwd: dirs.test(), pipeline( @@ -216,7 +216,7 @@ mod regex { fn parse_handles_external_stream_chunking() { Playground::setup("parse_test_streaming_1", |dirs, sandbox| { let data: String = "abcdefghijklmnopqrstuvwxyz".repeat(1000); - sandbox.with_files(vec![Stub::FileWithContent("data.txt", &data)]); + sandbox.with_files(&[Stub::FileWithContent("data.txt", &data)]); let actual = nu!( cwd: dirs.test(), diff --git a/crates/nu-command/tests/commands/path/exists.rs b/crates/nu-command/tests/commands/path/exists.rs index 5b1b39a002..96fa02c0e8 100644 --- a/crates/nu-command/tests/commands/path/exists.rs +++ b/crates/nu-command/tests/commands/path/exists.rs @@ -5,7 +5,7 @@ use nu_test_support::playground::Playground; #[test] fn checks_if_existing_file_exists() { Playground::setup("path_exists_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), diff --git a/crates/nu-command/tests/commands/path/expand.rs b/crates/nu-command/tests/commands/path/expand.rs index f3bdeb817b..71f2e03284 100644 --- a/crates/nu-command/tests/commands/path/expand.rs +++ b/crates/nu-command/tests/commands/path/expand.rs @@ -7,9 +7,7 @@ use std::path::PathBuf; #[test] fn expands_path_with_dot() { Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -28,9 +26,7 @@ fn expands_path_with_dot() { #[test] fn expands_path_without_follow_symlink() { Playground::setup("path_expand_3", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -49,9 +45,7 @@ fn expands_path_without_follow_symlink() { #[test] fn expands_path_with_double_dot() { Playground::setup("path_expand_2", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -69,9 +63,7 @@ fn expands_path_with_double_dot() { #[test] fn const_path_expand() { Playground::setup("const_path_expand", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -121,9 +113,7 @@ mod windows { #[test] fn expands_path_without_follow_symlink() { Playground::setup("path_expand_3", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let cwd = dirs.test(); std::os::windows::fs::symlink_file( diff --git a/crates/nu-command/tests/commands/path/type_.rs b/crates/nu-command/tests/commands/path/type_.rs index f2ba95fd3e..2317cea060 100644 --- a/crates/nu-command/tests/commands/path/type_.rs +++ b/crates/nu-command/tests/commands/path/type_.rs @@ -18,9 +18,7 @@ fn returns_type_of_missing_file() { #[test] fn returns_type_of_existing_file() { Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -37,9 +35,7 @@ fn returns_type_of_existing_file() { #[test] fn returns_type_of_existing_directory() { Playground::setup("path_expand_1", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -65,9 +61,7 @@ fn returns_type_of_existing_directory() { #[test] fn returns_type_of_existing_file_const() { Playground::setup("path_type_const", |dirs, sandbox| { - sandbox - .within("menu") - .with_files(vec![EmptyFile("spam.txt")]); + sandbox.within("menu").with_files(&[EmptyFile("spam.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( diff --git a/crates/nu-command/tests/commands/prepend.rs b/crates/nu-command/tests/commands/prepend.rs index 6af762225c..8ae5d78fec 100644 --- a/crates/nu-command/tests/commands/prepend.rs +++ b/crates/nu-command/tests/commands/prepend.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn adds_a_row_to_the_beginning() { Playground::setup("prepend_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" Andrés N. Robalino diff --git a/crates/nu-command/tests/commands/range.rs b/crates/nu-command/tests/commands/range.rs index 3080e0af0b..5135de6f20 100644 --- a/crates/nu-command/tests/commands/range.rs +++ b/crates/nu-command/tests/commands/range.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn selects_a_row() { Playground::setup("range_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("tests.txt")]); + sandbox.with_files(&[EmptyFile("notes.txt"), EmptyFile("tests.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -24,7 +24,7 @@ fn selects_a_row() { #[test] fn selects_some_rows() { Playground::setup("range_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("notes.txt"), EmptyFile("tests.txt"), EmptyFile("persons.txt"), @@ -47,7 +47,7 @@ fn selects_some_rows() { #[test] fn negative_indices() { Playground::setup("range_test_negative_indices", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("notes.txt"), EmptyFile("tests.txt"), EmptyFile("persons.txt"), diff --git a/crates/nu-command/tests/commands/redirection.rs b/crates/nu-command/tests/commands/redirection.rs index 7f12f982ee..1eb57077b9 100644 --- a/crates/nu-command/tests/commands/redirection.rs +++ b/crates/nu-command/tests/commands/redirection.rs @@ -127,7 +127,7 @@ fn same_target_redirection_with_too_much_stderr_not_hang_nushell() { for _ in 0..bytes { large_file_body.push('a'); } - sandbox.with_files(vec![FileWithContent("a_large_file.txt", &large_file_body)]); + sandbox.with_files(&[FileWithContent("a_large_file.txt", &large_file_body)]); nu!( cwd: dirs.test(), pipeline( @@ -220,7 +220,7 @@ fn redirection_with_pipeline_works() { let script_body = r"echo message"; let expect_body = "message"; - sandbox.with_files(vec![FileWithContent("test.sh", script_body)]); + sandbox.with_files(&[FileWithContent("test.sh", script_body)]); let actual = nu!( cwd: dirs.test(), diff --git a/crates/nu-command/tests/commands/rm.rs b/crates/nu-command/tests/commands/rm.rs index caeefc6152..b3a273ea86 100644 --- a/crates/nu-command/tests/commands/rm.rs +++ b/crates/nu-command/tests/commands/rm.rs @@ -8,7 +8,7 @@ use std::path::Path; #[test] fn removes_a_file() { Playground::setup("rm_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("i_will_be_deleted.txt")]); + sandbox.with_files(&[EmptyFile("i_will_be_deleted.txt")]); nu!( cwd: dirs.root(), @@ -26,17 +26,17 @@ fn removes_files_with_wildcard() { Playground::setup("rm_test_2", |dirs, sandbox| { sandbox .within("src") - .with_files(vec![ + .with_files(&[ EmptyFile("cli.rs"), EmptyFile("lib.rs"), EmptyFile("prelude.rs"), ]) .within("src/parser") - .with_files(vec![EmptyFile("parse.rs"), EmptyFile("parser.rs")]) + .with_files(&[EmptyFile("parse.rs"), EmptyFile("parser.rs")]) .within("src/parser/parse") - .with_files(vec![EmptyFile("token_tree.rs")]) + .with_files(&[EmptyFile("token_tree.rs")]) .within("src/parser/hir") - .with_files(vec![ + .with_files(&[ EmptyFile("baseline_parse.rs"), EmptyFile("baseline_parse_tokens.rs"), ]); @@ -67,17 +67,17 @@ fn removes_deeply_nested_directories_with_wildcard_and_recursive_flag() { Playground::setup("rm_test_3", |dirs, sandbox| { sandbox .within("src") - .with_files(vec![ + .with_files(&[ EmptyFile("cli.rs"), EmptyFile("lib.rs"), EmptyFile("prelude.rs"), ]) .within("src/parser") - .with_files(vec![EmptyFile("parse.rs"), EmptyFile("parser.rs")]) + .with_files(&[EmptyFile("parse.rs"), EmptyFile("parser.rs")]) .within("src/parser/parse") - .with_files(vec![EmptyFile("token_tree.rs")]) + .with_files(&[EmptyFile("token_tree.rs")]) .within("src/parser/hir") - .with_files(vec![ + .with_files(&[ EmptyFile("baseline_parse.rs"), EmptyFile("baseline_parse_tokens.rs"), ]); @@ -109,7 +109,7 @@ fn removes_directory_contents_without_recursive_flag_if_empty() { #[test] fn removes_directory_contents_with_recursive_flag() { Playground::setup("rm_test_5", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -127,7 +127,7 @@ fn removes_directory_contents_with_recursive_flag() { #[test] fn errors_if_attempting_to_delete_a_directory_with_content_without_recursive_flag() { Playground::setup("rm_test_6", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("some_empty_file.txt")]); + sandbox.with_files(&[EmptyFile("some_empty_file.txt")]); let actual = nu!( cwd: dirs.root(), "rm rm_test_6" @@ -179,11 +179,11 @@ fn removes_multiple_directories() { Playground::setup("rm_test_9", |dirs, sandbox| { sandbox .within("src") - .with_files(vec![EmptyFile("a.rs"), EmptyFile("b.rs")]) + .with_files(&[EmptyFile("a.rs"), EmptyFile("b.rs")]) .within("src/cli") - .with_files(vec![EmptyFile("c.rs"), EmptyFile("d.rs")]) + .with_files(&[EmptyFile("c.rs"), EmptyFile("d.rs")]) .within("test") - .with_files(vec![EmptyFile("a_test.rs"), EmptyFile("b_test.rs")]); + .with_files(&[EmptyFile("a_test.rs"), EmptyFile("b_test.rs")]); nu!( cwd: dirs.test(), @@ -200,7 +200,7 @@ fn removes_multiple_directories() { #[test] fn removes_multiple_files() { Playground::setup("rm_test_10", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -221,7 +221,7 @@ fn removes_multiple_files() { #[test] fn removes_multiple_files_with_asterisks() { Playground::setup("rm_test_11", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jt.txt"), EmptyFile("andres.toml"), @@ -242,7 +242,7 @@ fn removes_multiple_files_with_asterisks() { #[test] fn allows_doubly_specified_file() { Playground::setup("rm_test_12", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("yehuda.txt"), EmptyFile("jt.toml")]); + sandbox.with_files(&[EmptyFile("yehuda.txt"), EmptyFile("jt.toml")]); let actual = nu!( cwd: dirs.test(), @@ -260,7 +260,7 @@ fn allows_doubly_specified_file() { #[test] fn remove_files_from_two_parents_up_using_multiple_dots_and_glob() { Playground::setup("rm_test_13", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jt.txt"), EmptyFile("kevin.txt"), @@ -295,7 +295,7 @@ fn no_errors_if_attempting_to_delete_non_existent_file_with_f_flag() { #[test] fn rm_wildcard_keeps_dotfiles() { Playground::setup("rm_test_15", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); + sandbox.with_files(&[EmptyFile("foo"), EmptyFile(".bar")]); nu!( cwd: dirs.test(), @@ -310,7 +310,7 @@ fn rm_wildcard_keeps_dotfiles() { #[test] fn rm_wildcard_leading_dot_deletes_dotfiles() { Playground::setup("rm_test_16", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); + sandbox.with_files(&[EmptyFile("foo"), EmptyFile(".bar")]); nu!( cwd: dirs.test(), @@ -325,7 +325,7 @@ fn rm_wildcard_leading_dot_deletes_dotfiles() { #[test] fn removes_files_with_case_sensitive_glob_matches_by_default() { Playground::setup("glob_test", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("A0"), EmptyFile("a1")]); + sandbox.with_files(&[EmptyFile("A0"), EmptyFile("a1")]); nu!( cwd: dirs.root(), @@ -343,7 +343,7 @@ fn removes_files_with_case_sensitive_glob_matches_by_default() { #[test] fn remove_ignores_ansi() { Playground::setup("rm_test_ansi", |_dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("test.txt")]); + sandbox.with_files(&[EmptyFile("test.txt")]); let actual = nu!( cwd: sandbox.cwd(), @@ -358,7 +358,7 @@ fn removes_symlink() { let symlink_target = "symlink_target"; let symlink = "symlink"; Playground::setup("rm_test_symlink", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile(symlink_target)]); + sandbox.with_files(&[EmptyFile(symlink_target)]); #[cfg(not(windows))] std::os::unix::fs::symlink(dirs.test().join(symlink_target), dirs.test().join(symlink)) @@ -392,7 +392,7 @@ fn removes_symlink_pointing_to_directory() { #[test] fn removes_file_after_cd() { Playground::setup("rm_after_cd", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("delete.txt")]); + sandbox.with_files(&[EmptyFile("delete.txt")]); nu!( cwd: dirs.root(), @@ -431,11 +431,11 @@ fn rm_prints_filenames_on_error() { Playground::setup("rm_prints_filenames_on_error", |dirs, sandbox| { let file_names = vec!["test1.txt", "test2.txt"]; - let with_files = file_names + let with_files: Vec<_> = file_names .iter() .map(|file_name| EmptyFile(file_name)) .collect(); - sandbox.with_files(with_files); + sandbox.with_files(&with_files); let test_dir = dirs.test(); @@ -467,7 +467,7 @@ fn rm_files_inside_glob_metachars_dir() { let sub_dir = "test[]"; sandbox .within(sub_dir) - .with_files(vec![EmptyFile("test_file.txt")]); + .with_files(&[EmptyFile("test_file.txt")]); let actual = nu!( cwd: dirs.test().join(sub_dir), @@ -489,7 +489,7 @@ fn rm_files_inside_glob_metachars_dir() { #[case("a][c")] fn rm_files_with_glob_metachars(#[case] src_name: &str) { Playground::setup("rm_files_with_glob_metachars", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile(src_name)]); + sandbox.with_files(&[EmptyFile(src_name)]); let src = dirs.test().join(src_name); @@ -503,7 +503,7 @@ fn rm_files_with_glob_metachars(#[case] src_name: &str) { assert!(!src.exists()); // test with variables - sandbox.with_files(vec![EmptyFile(src_name)]); + sandbox.with_files(&[EmptyFile(src_name)]); let actual = nu!( cwd: dirs.test(), "let f = '{}'; rm $f", @@ -527,7 +527,7 @@ fn rm_files_with_glob_metachars_nw(#[case] src_name: &str) { #[test] fn force_rm_suppress_error() { Playground::setup("force_rm_suppress_error", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("test_file.txt")]); + sandbox.with_files(&[EmptyFile("test_file.txt")]); // the second rm should suppress error. let actual = nu!( @@ -542,7 +542,7 @@ fn force_rm_suppress_error() { #[test] fn rm_with_tilde() { Playground::setup("rm_tilde", |dirs, sandbox| { - sandbox.within("~tilde").with_files(vec![ + sandbox.within("~tilde").with_files(&[ EmptyFile("f1.txt"), EmptyFile("f2.txt"), EmptyFile("f3.txt"), diff --git a/crates/nu-command/tests/commands/run_external.rs b/crates/nu-command/tests/commands/run_external.rs index 9c2f0968c7..14428edcbe 100644 --- a/crates/nu-command/tests/commands/run_external.rs +++ b/crates/nu-command/tests/commands/run_external.rs @@ -21,7 +21,7 @@ fn better_empty_redirection() { #[test] fn explicit_glob() { Playground::setup("external with explicit glob", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("D&D_volume_1.txt"), EmptyFile("D&D_volume_2.txt"), EmptyFile("foo.sh"), @@ -42,7 +42,7 @@ fn explicit_glob() { #[test] fn bare_word_expand_path_glob() { Playground::setup("bare word should do the expansion", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("D&D_volume_1.txt"), EmptyFile("D&D_volume_2.txt"), EmptyFile("foo.sh"), @@ -64,7 +64,7 @@ fn bare_word_expand_path_glob() { #[test] fn backtick_expand_path_glob() { Playground::setup("backtick should do the expansion", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("D&D_volume_1.txt"), EmptyFile("D&D_volume_2.txt"), EmptyFile("foo.sh"), @@ -86,7 +86,7 @@ fn backtick_expand_path_glob() { #[test] fn single_quote_does_not_expand_path_glob() { Playground::setup("single quote do not run the expansion", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("D&D_volume_1.txt"), EmptyFile("D&D_volume_2.txt"), EmptyFile("foo.sh"), @@ -107,7 +107,7 @@ fn single_quote_does_not_expand_path_glob() { #[test] fn double_quote_does_not_expand_path_glob() { Playground::setup("double quote do not run the expansion", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("D&D_volume_1.txt"), EmptyFile("D&D_volume_2.txt"), EmptyFile("foo.sh"), @@ -251,7 +251,7 @@ fn failed_command_with_semicolon_will_not_execute_following_cmds_windows() { fn can_run_batch_files() { use nu_test_support::fs::Stub::FileWithContent; Playground::setup("run a Windows batch file", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "foo.cmd", r#" @echo off @@ -271,7 +271,7 @@ fn can_run_batch_files_without_cmd_extension() { Playground::setup( "run a Windows batch file without specifying the extension", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "foo.cmd", r#" @echo off @@ -292,7 +292,7 @@ fn can_run_batch_files_without_bat_extension() { Playground::setup( "run a Windows batch file without specifying the extension", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "foo.bat", r#" @echo off diff --git a/crates/nu-command/tests/commands/save.rs b/crates/nu-command/tests/commands/save.rs index 6739cd88fe..b5776a7bb9 100644 --- a/crates/nu-command/tests/commands/save.rs +++ b/crates/nu-command/tests/commands/save.rs @@ -6,7 +6,7 @@ use std::io::Write; #[test] fn writes_out_csv() { Playground::setup("save_test_2", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("cargo_sample.csv"); @@ -24,7 +24,7 @@ fn writes_out_csv() { #[test] fn writes_out_list() { Playground::setup("save_test_3", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("list_sample.txt"); @@ -42,7 +42,7 @@ fn writes_out_list() { #[test] fn save_append_will_create_file_if_not_exists() { Playground::setup("save_test_3", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("new-file.txt"); @@ -60,7 +60,7 @@ fn save_append_will_create_file_if_not_exists() { #[test] fn save_append_will_not_overwrite_content() { Playground::setup("save_test_4", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("new-file.txt"); @@ -86,7 +86,7 @@ fn save_append_will_not_overwrite_content() { #[test] fn save_stderr_and_stdout_to_afame_file() { Playground::setup("save_test_5", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let actual = nu!( cwd: dirs.root(), @@ -105,7 +105,7 @@ fn save_stderr_and_stdout_to_afame_file() { #[test] fn save_stderr_and_stdout_to_diff_file() { Playground::setup("save_test_6", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("log.txt"); let expected_stderr_file = dirs.test().join("err.txt"); @@ -132,7 +132,7 @@ fn save_stderr_and_stdout_to_diff_file() { #[test] fn save_string_and_stream_as_raw() { Playground::setup("save_test_7", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("temp.html"); nu!( cwd: dirs.root(), @@ -151,7 +151,7 @@ fn save_string_and_stream_as_raw() { #[test] fn save_not_override_file_by_default() { Playground::setup("save_test_8", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("log.txt")]); + sandbox.with_files(&[Stub::EmptyFile("log.txt")]); let actual = nu!( cwd: dirs.root(), @@ -164,7 +164,7 @@ fn save_not_override_file_by_default() { #[test] fn save_override_works() { Playground::setup("save_test_9", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("log.txt")]); + sandbox.with_files(&[Stub::EmptyFile("log.txt")]); let expected_file = dirs.test().join("log.txt"); nu!( @@ -179,7 +179,7 @@ fn save_override_works() { #[test] fn save_failure_not_overrides() { Playground::setup("save_test_10", |dirs, sandbox| { - sandbox.with_files(vec![Stub::FileWithContent("result.toml", "Old content")]); + sandbox.with_files(&[Stub::FileWithContent("result.toml", "Old content")]); let expected_file = dirs.test().join("result.toml"); nu!( @@ -195,7 +195,7 @@ fn save_failure_not_overrides() { #[test] fn save_append_works_on_stderr() { Playground::setup("save_test_11", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ Stub::FileWithContent("log.txt", "Old"), Stub::FileWithContent("err.txt", "Old Err"), ]); @@ -222,7 +222,7 @@ fn save_append_works_on_stderr() { #[test] fn save_not_overrides_err_by_default() { Playground::setup("save_test_12", |dirs, sandbox| { - sandbox.with_files(vec![Stub::FileWithContent("err.txt", "Old Err")]); + sandbox.with_files(&[Stub::FileWithContent("err.txt", "Old Err")]); let actual = nu!( cwd: dirs.root(), @@ -239,7 +239,7 @@ fn save_not_overrides_err_by_default() { #[test] fn save_override_works_stderr() { Playground::setup("save_test_13", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ Stub::FileWithContent("log.txt", "Old"), Stub::FileWithContent("err.txt", "Old Err"), ]); @@ -266,7 +266,7 @@ fn save_override_works_stderr() { #[test] fn save_list_stream() { Playground::setup("save_test_13", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("list_sample.txt"); @@ -283,7 +283,7 @@ fn save_list_stream() { #[test] fn writes_out_range() { Playground::setup("save_test_14", |dirs, sandbox| { - sandbox.with_files(vec![]); + sandbox.with_files(&[]); let expected_file = dirs.test().join("list_sample.json"); @@ -302,7 +302,7 @@ fn writes_out_range() { #[test] fn save_file_correct_relative_path() { Playground::setup("save_test_15", |dirs, sandbox| { - sandbox.with_files(vec![Stub::FileWithContent( + sandbox.with_files(&[Stub::FileWithContent( "test.nu", r#" export def main [] { diff --git a/crates/nu-command/tests/commands/select.rs b/crates/nu-command/tests/commands/select.rs index 028ecc3db7..8039dad9d0 100644 --- a/crates/nu-command/tests/commands/select.rs +++ b/crates/nu-command/tests/commands/select.rs @@ -119,7 +119,7 @@ fn ignores_duplicate_columns_selected() { #[test] fn selects_a_row() { Playground::setup("select_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); + sandbox.with_files(&[EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -138,7 +138,7 @@ fn selects_a_row() { #[test] fn selects_many_rows() { Playground::setup("select_test_2", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); + sandbox.with_files(&[EmptyFile("notes.txt"), EmptyFile("arepas.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( diff --git a/crates/nu-command/tests/commands/source_env.rs b/crates/nu-command/tests/commands/source_env.rs index 9facc98e42..4e8da55c78 100644 --- a/crates/nu-command/tests/commands/source_env.rs +++ b/crates/nu-command/tests/commands/source_env.rs @@ -12,7 +12,7 @@ fn sources_also_files_under_custom_lib_dirs_path() { let library_path = AbsolutePath::new(dirs.test().join("lib")); nu.with_config(&file); - nu.with_files(vec![FileWithContent( + nu.with_files(&[FileWithContent( "config.toml", &format!( r#" @@ -22,13 +22,13 @@ fn sources_also_files_under_custom_lib_dirs_path() { ), )]); - nu.within("lib").with_files(vec![FileWithContent( + nu.within("lib").with_files(&[FileWithContent( "my_library.nu", r#" source-env my_library/main.nu "#, )]); - nu.within("lib/my_library").with_files(vec![FileWithContent( + nu.within("lib/my_library").with_files(&[FileWithContent( "main.nu", r#" $env.hello = "hello nu" @@ -55,7 +55,7 @@ fn try_source_foo_with_double_quotes_in(testdir: &str, playdir: &str) { foo_file.push_str("/foo.nu"); sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); + sandbox.with_files(&[FileWithContent(&foo_file, "echo foo")]); let cmd = String::from("source-env ") + r#"""# + foo_file.as_str() + r#"""#; @@ -72,7 +72,7 @@ fn try_source_foo_with_single_quotes_in(testdir: &str, playdir: &str) { foo_file.push_str("/foo.nu"); sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); + sandbox.with_files(&[FileWithContent(&foo_file, "echo foo")]); let cmd = String::from("source-env ") + r#"'"# + foo_file.as_str() + r#"'"#; @@ -89,7 +89,7 @@ fn try_source_foo_without_quotes_in(testdir: &str, playdir: &str) { foo_file.push_str("/foo.nu"); sandbox.mkdir(&testdir); - sandbox.with_files(vec![FileWithContent(&foo_file, "echo foo")]); + sandbox.with_files(&[FileWithContent(&foo_file, "echo foo")]); let cmd = String::from("source-env ") + foo_file.as_str(); @@ -148,7 +148,7 @@ fn can_source_dynamic_path() { Playground::setup("can_source_dynamic_path", |dirs, sandbox| { let foo_file = "foo.nu"; - sandbox.with_files(vec![FileWithContent(foo_file, "echo foo")]); + sandbox.with_files(&[FileWithContent(foo_file, "echo foo")]); let cmd = format!("let file = `{foo_file}`; source-env $file"); let actual = nu!(cwd: dirs.test(), &cmd); @@ -160,7 +160,7 @@ fn can_source_dynamic_path() { #[test] fn source_env_eval_export_env() { Playground::setup("source_env_eval_export_env", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { $env.FOO = 'foo' } @@ -178,7 +178,7 @@ fn source_env_eval_export_env() { #[test] fn source_env_eval_export_env_hide() { Playground::setup("source_env_eval_export_env", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { hide-env FOO } @@ -202,7 +202,7 @@ fn source_env_do_cd() { Playground::setup("source_env_do_cd", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" cd test1/test2 @@ -225,7 +225,7 @@ fn source_env_do_cd_file_relative() { Playground::setup("source_env_do_cd_file_relative", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" cd ($env.FILE_PWD | path join '..') @@ -248,7 +248,7 @@ fn source_env_dont_cd_overlay() { Playground::setup("source_env_dont_cd_overlay", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" overlay new spam @@ -271,7 +271,7 @@ fn source_env_dont_cd_overlay() { #[test] fn source_env_is_scoped() { Playground::setup("source_env_is_scoped", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def no-name-similar-to-this [] { 'no-name-similar-to-this' } @@ -296,7 +296,7 @@ fn source_env_is_scoped() { #[test] fn source_env_const_file() { Playground::setup("source_env_const_file", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" $env.FOO = 'foo' diff --git a/crates/nu-command/tests/commands/split_by.rs b/crates/nu-command/tests/commands/split_by.rs index ab4b7d5459..ab4631d079 100644 --- a/crates/nu-command/tests/commands/split_by.rs +++ b/crates/nu-command/tests/commands/split_by.rs @@ -36,7 +36,7 @@ fn errors_if_no_input() { #[test] fn errors_if_non_record_input() { Playground::setup("split_by_test_2", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("los.txt"), EmptyFile("tres.txt"), EmptyFile("amigos.txt"), diff --git a/crates/nu-command/tests/commands/split_column.rs b/crates/nu-command/tests/commands/split_column.rs index 9728df1ddd..544c238cfa 100644 --- a/crates/nu-command/tests/commands/split_column.rs +++ b/crates/nu-command/tests/commands/split_column.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn to_column() { Playground::setup("split_column_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ FileWithContentToBeTrimmed( "sample.txt", r#" diff --git a/crates/nu-command/tests/commands/split_row.rs b/crates/nu-command/tests/commands/split_row.rs index 3560ea9b5d..3622525a30 100644 --- a/crates/nu-command/tests/commands/split_row.rs +++ b/crates/nu-command/tests/commands/split_row.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn to_row() { Playground::setup("split_row_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ FileWithContentToBeTrimmed( "sample.txt", r#" diff --git a/crates/nu-command/tests/commands/str_/into_string.rs b/crates/nu-command/tests/commands/str_/into_string.rs index afc0d227cb..a84d1006e6 100644 --- a/crates/nu-command/tests/commands/str_/into_string.rs +++ b/crates/nu-command/tests/commands/str_/into_string.rs @@ -50,7 +50,7 @@ fn from_string() { #[test] fn from_filename() { Playground::setup("from_filename", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "sample.toml", r#" [dependency] @@ -70,7 +70,7 @@ fn from_filename() { #[test] fn from_filesize() { Playground::setup("from_filesize", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "sample.toml", r#" [dependency] diff --git a/crates/nu-command/tests/commands/str_/mod.rs b/crates/nu-command/tests/commands/str_/mod.rs index 382f2bf20f..9f1e90e853 100644 --- a/crates/nu-command/tests/commands/str_/mod.rs +++ b/crates/nu-command/tests/commands/str_/mod.rs @@ -8,7 +8,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn trims() { Playground::setup("str_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [dependency] @@ -39,7 +39,7 @@ fn error_trim_multiple_chars() { #[test] fn capitalizes() { Playground::setup("str_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [dependency] @@ -59,7 +59,7 @@ fn capitalizes() { #[test] fn downcases() { Playground::setup("str_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [dependency] @@ -86,7 +86,7 @@ fn non_ascii_downcase() { #[test] fn upcases() { Playground::setup("str_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -114,7 +114,7 @@ fn non_ascii_upcase() { #[ignore = "Playgrounds are not supported in nu-cmd-extra"] fn camelcases() { Playground::setup("str_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [dependency] @@ -165,7 +165,7 @@ fn converts_to_float() { #[test] fn find_and_replaces() { Playground::setup("str_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [fortune.teller] @@ -189,7 +189,7 @@ fn find_and_replaces() { #[test] fn find_and_replaces_without_passing_field() { Playground::setup("str_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [fortune.teller] @@ -233,7 +233,7 @@ fn regex_error_in_pattern() { #[test] fn substrings_the_input() { Playground::setup("str_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [fortune.teller] @@ -257,7 +257,7 @@ fn substrings_the_input() { #[test] fn substring_errors_if_start_index_is_greater_than_end_index() { Playground::setup("str_test_9", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [fortune.teller] @@ -282,7 +282,7 @@ fn substring_errors_if_start_index_is_greater_than_end_index() { #[test] fn substrings_the_input_and_returns_the_string_if_end_index_exceeds_length() { Playground::setup("str_test_10", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -306,7 +306,7 @@ fn substrings_the_input_and_returns_the_string_if_end_index_exceeds_length() { #[test] fn substrings_the_input_and_returns_blank_if_start_index_exceeds_length() { Playground::setup("str_test_11", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -330,7 +330,7 @@ fn substrings_the_input_and_returns_blank_if_start_index_exceeds_length() { #[test] fn substrings_the_input_and_treats_start_index_as_zero_if_blank_start_index_given() { Playground::setup("str_test_12", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -354,7 +354,7 @@ fn substrings_the_input_and_treats_start_index_as_zero_if_blank_start_index_give #[test] fn substrings_the_input_and_treats_end_index_as_length_if_blank_end_index_given() { Playground::setup("str_test_13", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] diff --git a/crates/nu-command/tests/commands/table.rs b/crates/nu-command/tests/commands/table.rs index 130d87c434..afc9b613d4 100644 --- a/crates/nu-command/tests/commands/table.rs +++ b/crates/nu-command/tests/commands/table.rs @@ -505,7 +505,7 @@ fn external_with_too_much_stdout_should_not_hang_nu() { for _ in 0..bytes { large_file_body.push('a'); } - sandbox.with_files(vec![FileWithContent("a_large_file.txt", &large_file_body)]); + sandbox.with_files(&[FileWithContent("a_large_file.txt", &large_file_body)]); let actual = nu!( cwd: dirs.test(), pipeline( @@ -536,7 +536,7 @@ fn table_index_0() { #[test] fn test_expand_big_0() { Playground::setup("test_expand_big_0", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -1820,7 +1820,7 @@ fn table_expande_with_no_header_internally_1() { #[test] fn test_collapse_big_0() { Playground::setup("test_expand_big_0", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] diff --git a/crates/nu-command/tests/commands/touch.rs b/crates/nu-command/tests/commands/touch.rs index d7f5cb875a..26d0325729 100644 --- a/crates/nu-command/tests/commands/touch.rs +++ b/crates/nu-command/tests/commands/touch.rs @@ -39,7 +39,7 @@ fn creates_two_files() { #[test] fn change_modified_time_of_file_to_today() { Playground::setup("change_time_test_9", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("file.txt")]); + sandbox.with_files(&[Stub::EmptyFile("file.txt")]); let path = dirs.test().join("file.txt"); // Set file.txt's times to the past before the test to make sure `touch` actually changes the mtime to today @@ -69,7 +69,7 @@ fn change_modified_time_of_file_to_today() { #[test] fn change_access_time_of_file_to_today() { Playground::setup("change_time_test_18", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("file.txt")]); + sandbox.with_files(&[Stub::EmptyFile("file.txt")]); let path = dirs.test().join("file.txt"); // Set file.txt's times to the past before the test to make sure `touch` actually changes the atime to today @@ -99,7 +99,7 @@ fn change_access_time_of_file_to_today() { #[test] fn change_modified_and_access_time_of_file_to_today() { Playground::setup("change_time_test_27", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("file.txt")]); + sandbox.with_files(&[Stub::EmptyFile("file.txt")]); let path = dirs.test().join("file.txt"); filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap(); @@ -143,7 +143,7 @@ fn change_file_times_if_exists_with_no_create() { Playground::setup( "change_file_times_if_exists_with_no_create", |dirs, sandbox| { - sandbox.with_files(vec![Stub::EmptyFile("file.txt")]); + sandbox.with_files(&[Stub::EmptyFile("file.txt")]); let path = dirs.test().join("file.txt"); filetime::set_file_times(&path, TIME_ONE, TIME_ONE).unwrap(); @@ -208,7 +208,7 @@ fn creates_file_four_dots_quotation_marks() { #[test] fn change_file_times_to_reference_file() { Playground::setup("change_dir_times_to_reference_dir", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ Stub::EmptyFile("reference_file"), Stub::EmptyFile("target_file"), ]); @@ -253,7 +253,7 @@ fn change_file_times_to_reference_file() { #[test] fn change_file_mtime_to_reference() { Playground::setup("change_file_mtime_to_reference", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ Stub::EmptyFile("reference_file"), Stub::EmptyFile("target_file"), ]); diff --git a/crates/nu-command/tests/commands/ucp.rs b/crates/nu-command/tests/commands/ucp.rs index d434d77824..453786ad4e 100644 --- a/crates/nu-command/tests/commands/ucp.rs +++ b/crates/nu-command/tests/commands/ucp.rs @@ -113,7 +113,7 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r Playground::setup("ucp_test_4", |dirs, sandbox| { sandbox .within("originals") - .with_files(vec![ + .with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), @@ -151,19 +151,19 @@ fn deep_copies_with_recursive_flag_impl(progress: bool) { Playground::setup("ucp_test_5", |dirs, sandbox| { sandbox .within("originals") - .with_files(vec![EmptyFile("manifest.txt")]) + .with_files(&[EmptyFile("manifest.txt")]) .within("originals/contributors") - .with_files(vec![ + .with_files(&[ EmptyFile("yehuda.txt"), EmptyFile("jttxt"), EmptyFile("andres.txt"), ]) .within("originals/contributors/JT") - .with_files(vec![EmptyFile("errors.txt"), EmptyFile("multishells.txt")]) + .with_files(&[EmptyFile("errors.txt"), EmptyFile("multishells.txt")]) .within("originals/contributors/andres") - .with_files(vec![EmptyFile("coverage.txt"), EmptyFile("commands.txt")]) + .with_files(&[EmptyFile("coverage.txt"), EmptyFile("commands.txt")]) .within("originals/contributors/yehuda") - .with_files(vec![EmptyFile("defer-evaluation.txt")]) + .with_files(&[EmptyFile("defer-evaluation.txt")]) .mkdir("expected"); let expected_dir = dirs.test().join("expected").join("originals"); @@ -324,7 +324,7 @@ fn copy_files_using_glob_two_parents_up_using_multiple_dots() { fn copy_files_using_glob_two_parents_up_using_multiple_dots_imp(progress: bool) { Playground::setup("ucp_test_9", |dirs, sandbox| { - sandbox.within("foo").within("bar").with_files(vec![ + sandbox.within("foo").within("bar").with_files(&[ EmptyFile("jtjson"), EmptyFile("andres.xml"), EmptyFile("yehuda.yaml"), @@ -363,7 +363,7 @@ fn copy_file_and_dir_from_two_parents_up_using_multiple_dots_to_current_dir_recu progress: bool, ) { Playground::setup("ucp_test_10", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("hello_there")]); + sandbox.with_files(&[EmptyFile("hello_there")]); sandbox.mkdir("hello_again"); sandbox.within("foo").mkdir("bar"); @@ -390,7 +390,7 @@ fn copy_to_non_existing_dir() { fn copy_to_non_existing_dir_impl(progress: bool) { Playground::setup("ucp_test_11", |_dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("empty_file")]); + sandbox.with_files(&[EmptyFile("empty_file")]); let progress_flag = if progress { "-p" } else { "" }; let actual = nu!( @@ -413,7 +413,7 @@ fn copy_dir_contains_symlink_ignored_impl(progress: bool) { Playground::setup("ucp_test_12", |_dirs, sandbox| { sandbox .within("tmp_dir") - .with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")]) + .with_files(&[EmptyFile("hello_there"), EmptyFile("good_bye")]) .within("tmp_dir") .symlink("good_bye", "dangle_symlink"); @@ -446,7 +446,7 @@ fn copy_dir_contains_symlink_impl(progress: bool) { Playground::setup("ucp_test_13", |_dirs, sandbox| { sandbox .within("tmp_dir") - .with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")]) + .with_files(&[EmptyFile("hello_there"), EmptyFile("good_bye")]) .within("tmp_dir") .symlink("good_bye", "dangle_symlink"); @@ -477,7 +477,7 @@ fn copy_dir_symlink_file_body_not_changed_impl(progress: bool) { Playground::setup("ucp_test_14", |_dirs, sandbox| { sandbox .within("tmp_dir") - .with_files(vec![EmptyFile("hello_there"), EmptyFile("good_bye")]) + .with_files(&[EmptyFile("hello_there"), EmptyFile("good_bye")]) .within("tmp_dir") .symlink("good_bye", "dangle_symlink"); @@ -507,7 +507,7 @@ fn copy_identical_file() { fn copy_identical_file_impl(progress: bool) { Playground::setup("ucp_test_15", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("same.txt")]); + sandbox.with_files(&[EmptyFile("same.txt")]); let progress_flag = if progress { "-p" } else { "" }; @@ -538,7 +538,7 @@ fn copy_ignores_ansi() { fn copy_ignores_ansi_impl(progress: bool) { Playground::setup("ucp_test_16", |_dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("test.txt")]); + sandbox.with_files(&[EmptyFile("test.txt")]); let progress_flag = if progress { "-p" } else { "" }; @@ -563,7 +563,7 @@ fn copy_file_not_exists_dst() { #[cfg(unix)] fn copy_file_not_exists_dst_impl(progress: bool) { Playground::setup("ucp_test_17", |_dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("valid.txt")]); + sandbox.with_files(&[EmptyFile("valid.txt")]); let progress_flag = if progress { "-p" } else { "" }; @@ -589,7 +589,7 @@ fn copy_file_with_read_permission() { fn copy_file_with_read_permission_impl(progress: bool) { Playground::setup("ucp_test_18", |_dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("valid.txt"), FileWithPermission("invalid_prem.txt", false), ]); @@ -775,7 +775,7 @@ fn test_cp_arg_force() { Playground::setup("ucp_test_24", |dirs, sandbox| { let src = dirs.fixtures.join("cp").join(TEST_HELLO_WORLD_SOURCE); let src_hash = get_file_hash(src.display()); - sandbox.with_files(vec![FileWithPermission("invalid_prem.txt", false)]); + sandbox.with_files(&[FileWithPermission("invalid_prem.txt", false)]); nu!( cwd: dirs.root(), @@ -827,7 +827,7 @@ fn test_cp_nested_directory_to_itself_disallowed() { #[test] fn test_cp_same_file_force() { Playground::setup("ucp_test_27", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("f")]); + sandbox.with_files(&[EmptyFile("f")]); let actual = nu!( cwd: dirs.test(), "cp --force {} {}", @@ -862,7 +862,7 @@ fn test_cp_arg_no_clobber() { #[test] fn test_cp_arg_no_clobber_twice() { Playground::setup("ucp_test_29", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("source.txt"), FileWithContent("source_with_body.txt", "some-body"), ]); @@ -961,7 +961,7 @@ fn test_cp_only_source_no_dest() { #[test] fn test_cp_with_vars() { Playground::setup("ucp_test_33", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("input")]); + sandbox.with_files(&[EmptyFile("input")]); nu!( cwd: dirs.test(), "let src = 'input'; let dst = 'target'; cp $src $dst", @@ -974,7 +974,7 @@ fn test_cp_with_vars() { fn test_cp_destination_after_cd() { Playground::setup("ucp_test_34", |dirs, sandbox| { sandbox.mkdir("test"); - sandbox.with_files(vec![EmptyFile("test/file.txt")]); + sandbox.with_files(&[EmptyFile("test/file.txt")]); nu!( cwd: dirs.test(), // Defining variable avoid path expansion of cp argument. @@ -992,7 +992,7 @@ fn test_cp_destination_after_cd() { #[case("a][c")] fn copies_files_with_glob_metachars(#[case] src_name: &str) { Playground::setup("ucp_test_34", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( src_name, "What is the sound of one hand clapping?", )]); @@ -1026,7 +1026,7 @@ fn copies_files_with_glob_metachars(#[case] src_name: &str) { #[case("a][c")] fn copies_files_with_glob_metachars_when_input_are_variables(#[case] src_name: &str) { Playground::setup("ucp_test_35", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( src_name, "What is the sound of one hand clapping?", )]); @@ -1069,7 +1069,7 @@ fn test_cp_preserve_timestamps() { // Preserve timestamp and mode Playground::setup("ucp_test_35", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("file.txt")]); + sandbox.with_files(&[EmptyFile("file.txt")]); let actual = nu!( cwd: dirs.test(), " @@ -1093,7 +1093,7 @@ fn test_cp_preserve_only_timestamps() { // Preserve timestamps and discard all other attributes including mode Playground::setup("ucp_test_35", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("file.txt")]); + sandbox.with_files(&[EmptyFile("file.txt")]); let actual = nu!( cwd: dirs.test(), " @@ -1118,7 +1118,7 @@ fn test_cp_preserve_nothing() { // Preserve no attributes Playground::setup("ucp_test_35", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("file.txt")]); + sandbox.with_files(&[EmptyFile("file.txt")]); let actual = nu!( cwd: dirs.test(), " @@ -1142,7 +1142,7 @@ fn test_cp_inside_glob_metachars_dir() { let sub_dir = "test[]"; sandbox .within(sub_dir) - .with_files(vec![FileWithContent("test_file.txt", "hello")]); + .with_files(&[FileWithContent("test_file.txt", "hello")]); let actual = nu!( cwd: dirs.test().join(sub_dir), @@ -1163,7 +1163,7 @@ fn test_cp_inside_glob_metachars_dir() { fn test_cp_to_customized_home_directory() { Playground::setup("cp_to_home", |dirs, sandbox| { std::env::set_var("HOME", dirs.test()); - sandbox.with_files(vec![EmptyFile("test_file.txt")]); + sandbox.with_files(&[EmptyFile("test_file.txt")]); let actual = nu!(cwd: dirs.test(), "mkdir test; cp test_file.txt ~/test/"); assert!(actual.err.is_empty()); @@ -1177,7 +1177,7 @@ fn test_cp_to_customized_home_directory() { #[test] fn cp_with_tilde() { Playground::setup("cp_tilde", |dirs, sandbox| { - sandbox.within("~tilde").with_files(vec![ + sandbox.within("~tilde").with_files(&[ EmptyFile("f1.txt"), EmptyFile("f2.txt"), EmptyFile("f3.txt"), @@ -1218,7 +1218,7 @@ fn copy_file_with_update_flag() { fn copy_file_with_update_flag_impl(progress: bool) { Playground::setup("cp_test_36", |_dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("valid.txt"), FileWithContent("newer_valid.txt", "body"), ]); @@ -1234,7 +1234,7 @@ fn copy_file_with_update_flag_impl(progress: bool) { // create a file after assert to make sure that newest_valid.txt is newest std::thread::sleep(std::time::Duration::from_secs(1)); - sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); + sandbox.with_files(&[FileWithContent("newest_valid.txt", "newest_body")]); let actual = nu!(cwd: sandbox.cwd(), "cp {} -u newest_valid.txt valid.txt; open valid.txt", progress_flag); assert_eq!(actual.out, "newest_body"); @@ -1249,7 +1249,7 @@ fn cp_with_cd() { Playground::setup("cp_test_37", |_dirs, sandbox| { sandbox .mkdir("tmp_dir") - .with_files(vec![FileWithContent("tmp_dir/file.txt", "body")]); + .with_files(&[FileWithContent("tmp_dir/file.txt", "body")]); let actual = nu!( cwd: sandbox.cwd(), diff --git a/crates/nu-command/tests/commands/use_.rs b/crates/nu-command/tests/commands/use_.rs index 9d98e34fab..8cb783f96b 100644 --- a/crates/nu-command/tests/commands/use_.rs +++ b/crates/nu-command/tests/commands/use_.rs @@ -9,7 +9,7 @@ fn use_module_file_within_block() { Playground::setup("use_test_1", |dirs, nu| { let file = AbsolutePath::new(dirs.test().join("spam.nu")); - nu.with_files(vec![FileWithContent( + nu.with_files(&[FileWithContent( &file.to_string(), r#" export def foo [] { @@ -39,7 +39,7 @@ fn use_keeps_doc_comments() { Playground::setup("use_doc_comments", |dirs, nu| { let file = AbsolutePath::new(dirs.test().join("spam.nu")); - nu.with_files(vec![FileWithContent( + nu.with_files(&[FileWithContent( &file.to_string(), r#" # this is my foo command @@ -68,7 +68,7 @@ fn use_keeps_doc_comments() { #[test] fn use_eval_export_env() { Playground::setup("use_eval_export_env", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { $env.FOO = 'foo' } @@ -86,7 +86,7 @@ fn use_eval_export_env() { #[test] fn use_eval_export_env_hide() { Playground::setup("use_eval_export_env", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { hide-env FOO } @@ -106,7 +106,7 @@ fn use_do_cd() { Playground::setup("use_do_cd", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" export-env { cd test1/test2 } @@ -126,7 +126,7 @@ fn use_do_cd_file_relative() { Playground::setup("use_do_cd_file_relative", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" export-env { cd ($env.FILE_PWD | path join '..') } @@ -146,7 +146,7 @@ fn use_dont_cd_overlay() { Playground::setup("use_dont_cd_overlay", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", r#" export-env { @@ -168,7 +168,7 @@ fn use_dont_cd_overlay() { #[test] fn use_export_env_combined() { Playground::setup("use_is_scoped", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def foo [] { 'foo' } diff --git a/crates/nu-command/tests/commands/zip.rs b/crates/nu-command/tests/commands/zip.rs index b8915cb896..e116a1ac92 100644 --- a/crates/nu-command/tests/commands/zip.rs +++ b/crates/nu-command/tests/commands/zip.rs @@ -17,7 +17,7 @@ export def expect [ #[test] fn zips_two_tables() { Playground::setup("zip_test_1", |dirs, nu| { - nu.with_files(vec![FileWithContent( + nu.with_files(&[FileWithContent( "zip_test.nu", &format!("{ZIP_POWERED_TEST_ASSERTION_SCRIPT}\n"), )]); diff --git a/crates/nu-command/tests/format_conversions/csv.rs b/crates/nu-command/tests/format_conversions/csv.rs index 8b332d6269..5915b3c4d4 100644 --- a/crates/nu-command/tests/format_conversions/csv.rs +++ b/crates/nu-command/tests/format_conversions/csv.rs @@ -15,7 +15,7 @@ fn table_to_csv_text_and_from_csv_text_back_into_table() { #[test] fn table_to_csv_text() { Playground::setup("filter_to_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "csv_text_sample.txt", r#" importer,shipper,tariff_item,name,origin @@ -47,7 +47,7 @@ fn table_to_csv_text() { #[test] fn table_to_csv_text_skipping_headers_after_conversion() { Playground::setup("filter_to_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "csv_text_sample.txt", r#" importer,shipper,tariff_item,name,origin @@ -77,7 +77,7 @@ fn table_to_csv_text_skipping_headers_after_conversion() { #[test] fn infers_types() { Playground::setup("filter_from_csv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_cuatro_mosqueteros.csv", r#" first_name,last_name,rusty_luck,d @@ -104,7 +104,7 @@ fn infers_types() { #[test] fn from_csv_text_to_table() { Playground::setup("filter_from_csv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -131,7 +131,7 @@ fn from_csv_text_to_table() { #[test] fn from_csv_text_with_separator_to_table() { Playground::setup("filter_from_csv_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name;last_name;rusty_luck @@ -158,7 +158,7 @@ fn from_csv_text_with_separator_to_table() { #[test] fn from_csv_text_with_tab_separator_to_table() { Playground::setup("filter_from_csv_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck @@ -185,7 +185,7 @@ fn from_csv_text_with_tab_separator_to_table() { #[test] fn from_csv_text_with_comments_to_table() { Playground::setup("filter_from_csv_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" # This is a comment @@ -215,7 +215,7 @@ fn from_csv_text_with_comments_to_table() { #[test] fn from_csv_text_with_custom_quotes_to_table() { Playground::setup("filter_from_csv_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -242,7 +242,7 @@ fn from_csv_text_with_custom_quotes_to_table() { #[test] fn from_csv_text_with_custom_escapes_to_table() { Playground::setup("filter_from_csv_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -269,7 +269,7 @@ fn from_csv_text_with_custom_escapes_to_table() { #[test] fn from_csv_text_skipping_headers_to_table() { Playground::setup("filter_from_csv_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_amigos.txt", r#" Andrés,Robalino,1 @@ -295,7 +295,7 @@ fn from_csv_text_skipping_headers_to_table() { #[test] fn from_csv_text_with_missing_columns_to_table() { Playground::setup("filter_from_csv_test_9", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -323,7 +323,7 @@ fn from_csv_text_with_missing_columns_to_table() { #[test] fn from_csv_text_with_multiple_char_separator() { Playground::setup("filter_from_csv_test_10", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -350,7 +350,7 @@ fn from_csv_text_with_multiple_char_separator() { #[test] fn from_csv_text_with_wrong_type_separator() { Playground::setup("filter_from_csv_test_11", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name,last_name,rusty_luck @@ -410,7 +410,7 @@ fn string_to_csv_error() { #[test] fn parses_csv_with_unicode_sep() { Playground::setup("filter_from_csv_unicode_sep_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name;last_name;rusty_luck @@ -437,7 +437,7 @@ fn parses_csv_with_unicode_sep() { #[test] fn parses_csv_with_unicode_x1f_sep() { Playground::setup("filter_from_csv_unicode_sep_x1f_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_namelast_namerusty_luck diff --git a/crates/nu-command/tests/format_conversions/json.rs b/crates/nu-command/tests/format_conversions/json.rs index be3476e222..1989000df6 100644 --- a/crates/nu-command/tests/format_conversions/json.rs +++ b/crates/nu-command/tests/format_conversions/json.rs @@ -20,7 +20,7 @@ fn table_to_json_text_and_from_json_text_back_into_table() { #[test] fn from_json_text_to_table() { Playground::setup("filter_from_json_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "katz.txt", r#" { @@ -46,7 +46,7 @@ fn from_json_text_to_table() { #[test] fn from_json_text_to_table_strict() { Playground::setup("filter_from_json_test_1_strict", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "katz.txt", r#" { @@ -72,7 +72,7 @@ fn from_json_text_to_table_strict() { #[test] fn from_json_text_recognizing_objects_independently_to_table() { Playground::setup("filter_from_json_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "katz.txt", r#" {"name": "Yehuda", "rusty_luck": 1} @@ -99,7 +99,7 @@ fn from_json_text_recognizing_objects_independently_to_table() { #[test] fn from_json_text_recognizing_objects_independently_to_table_strict() { Playground::setup("filter_from_json_test_2_strict", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "katz.txt", r#" {"name": "Yehuda", "rusty_luck": 1} @@ -126,7 +126,7 @@ fn from_json_text_recognizing_objects_independently_to_table_strict() { #[test] fn table_to_json_text() { Playground::setup("filter_to_json_test", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "sample.txt", r#" JonAndrehudaTZ,3 @@ -155,7 +155,7 @@ fn table_to_json_text() { #[test] fn table_to_json_text_strict() { Playground::setup("filter_to_json_test_strict", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "sample.txt", r#" JonAndrehudaTZ,3 diff --git a/crates/nu-command/tests/format_conversions/ssv.rs b/crates/nu-command/tests/format_conversions/ssv.rs index 859ba01fc9..a673b122fb 100644 --- a/crates/nu-command/tests/format_conversions/ssv.rs +++ b/crates/nu-command/tests/format_conversions/ssv.rs @@ -5,7 +5,7 @@ use nu_test_support::{nu, pipeline}; #[test] fn from_ssv_text_to_table() { Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "oc_get_svc.txt", r#" NAME LABELS SELECTOR IP PORT(S) @@ -32,7 +32,7 @@ fn from_ssv_text_to_table() { #[test] fn from_ssv_text_to_table_with_separator_specified() { Playground::setup("filter_from_ssv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "oc_get_svc.txt", r#" NAME LABELS SELECTOR IP PORT(S) @@ -59,7 +59,7 @@ fn from_ssv_text_to_table_with_separator_specified() { #[test] fn from_ssv_text_treating_first_line_as_data_with_flag() { Playground::setup("filter_from_ssv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "oc_get_svc.txt", r#" docker-registry docker-registry=default docker-registry=default 172.30.78.158 5000/TCP diff --git a/crates/nu-command/tests/format_conversions/tsv.rs b/crates/nu-command/tests/format_conversions/tsv.rs index ca71c25e7a..9627d0d0be 100644 --- a/crates/nu-command/tests/format_conversions/tsv.rs +++ b/crates/nu-command/tests/format_conversions/tsv.rs @@ -25,7 +25,7 @@ fn table_to_tsv_text_and_from_tsv_text_back_into_table_using_csv_separator() { #[test] fn table_to_tsv_text() { Playground::setup("filter_to_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "tsv_text_sample.txt", r#" importer shipper tariff_item name origin @@ -54,7 +54,7 @@ fn table_to_tsv_text() { #[test] fn table_to_tsv_text_skipping_headers_after_conversion() { Playground::setup("filter_to_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "tsv_text_sample.txt", r#" importer shipper tariff_item name origin @@ -81,7 +81,7 @@ fn table_to_tsv_text_skipping_headers_after_conversion() { #[test] fn from_tsv_text_to_table() { Playground::setup("filter_from_tsv_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_amigos.txt", r#" first Name Last Name rusty_luck @@ -108,7 +108,7 @@ fn from_tsv_text_to_table() { #[test] fn from_tsv_text_with_comments_to_table() { Playground::setup("filter_from_tsv_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" # This is a comment @@ -138,7 +138,7 @@ fn from_tsv_text_with_comments_to_table() { #[test] fn from_tsv_text_with_custom_quotes_to_table() { Playground::setup("filter_from_tsv_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck @@ -165,7 +165,7 @@ fn from_tsv_text_with_custom_quotes_to_table() { #[test] fn from_tsv_text_with_custom_escapes_to_table() { Playground::setup("filter_from_tsv_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck @@ -192,7 +192,7 @@ fn from_tsv_text_with_custom_escapes_to_table() { #[test] fn from_tsv_text_skipping_headers_to_table() { Playground::setup("filter_from_tsv_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_amigos.txt", r#" Andrés Robalino 1 @@ -218,7 +218,7 @@ fn from_tsv_text_skipping_headers_to_table() { #[test] fn from_tsv_text_with_missing_columns_to_table() { Playground::setup("filter_from_tsv_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck @@ -246,7 +246,7 @@ fn from_tsv_text_with_missing_columns_to_table() { #[test] fn from_tsv_text_with_multiple_char_comment() { Playground::setup("filter_from_tsv_test_7", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck @@ -271,7 +271,7 @@ fn from_tsv_text_with_multiple_char_comment() { #[test] fn from_tsv_text_with_wrong_type_comment() { Playground::setup("filter_from_csv_test_8", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "los_tres_caballeros.txt", r#" first_name last_name rusty_luck diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index cb1d1de110..cc31dda23a 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -49,46 +49,52 @@ pub enum FlatShape { VarDecl(VarId), } +impl FlatShape { + pub fn as_str(&self) -> &str { + match self { + FlatShape::And => "shape_and", + FlatShape::Binary => "shape_binary", + FlatShape::Block => "shape_block", + FlatShape::Bool => "shape_bool", + FlatShape::Closure => "shape_closure", + FlatShape::Custom(_) => "shape_custom", + FlatShape::DateTime => "shape_datetime", + FlatShape::Directory => "shape_directory", + FlatShape::External => "shape_external", + FlatShape::ExternalArg => "shape_externalarg", + FlatShape::ExternalResolved => "shape_external_resolved", + FlatShape::Filepath => "shape_filepath", + FlatShape::Flag => "shape_flag", + FlatShape::Float => "shape_float", + FlatShape::Garbage => "shape_garbage", + FlatShape::GlobPattern => "shape_globpattern", + FlatShape::Int => "shape_int", + FlatShape::InternalCall(_) => "shape_internalcall", + FlatShape::Keyword => "shape_keyword", + FlatShape::List => "shape_list", + FlatShape::Literal => "shape_literal", + FlatShape::MatchPattern => "shape_match_pattern", + FlatShape::Nothing => "shape_nothing", + FlatShape::Operator => "shape_operator", + FlatShape::Or => "shape_or", + FlatShape::Pipe => "shape_pipe", + FlatShape::Range => "shape_range", + FlatShape::RawString => "shape_raw_string", + FlatShape::Record => "shape_record", + FlatShape::Redirection => "shape_redirection", + FlatShape::Signature => "shape_signature", + FlatShape::String => "shape_string", + FlatShape::StringInterpolation => "shape_string_interpolation", + FlatShape::Table => "shape_table", + FlatShape::Variable(_) => "shape_variable", + FlatShape::VarDecl(_) => "shape_vardecl", + } + } +} + impl Display for FlatShape { fn fmt(&self, f: &mut Formatter) -> Result { - match self { - FlatShape::And => write!(f, "shape_and"), - FlatShape::Binary => write!(f, "shape_binary"), - FlatShape::Block => write!(f, "shape_block"), - FlatShape::Bool => write!(f, "shape_bool"), - FlatShape::Closure => write!(f, "shape_closure"), - FlatShape::Custom(_) => write!(f, "shape_custom"), - FlatShape::DateTime => write!(f, "shape_datetime"), - FlatShape::Directory => write!(f, "shape_directory"), - FlatShape::External => write!(f, "shape_external"), - FlatShape::ExternalArg => write!(f, "shape_externalarg"), - FlatShape::ExternalResolved => write!(f, "shape_external_resolved"), - FlatShape::Filepath => write!(f, "shape_filepath"), - FlatShape::Flag => write!(f, "shape_flag"), - FlatShape::Float => write!(f, "shape_float"), - FlatShape::Garbage => write!(f, "shape_garbage"), - FlatShape::GlobPattern => write!(f, "shape_globpattern"), - FlatShape::Int => write!(f, "shape_int"), - FlatShape::InternalCall(_) => write!(f, "shape_internalcall"), - FlatShape::Keyword => write!(f, "shape_keyword"), - FlatShape::List => write!(f, "shape_list"), - FlatShape::Literal => write!(f, "shape_literal"), - FlatShape::MatchPattern => write!(f, "shape_match_pattern"), - FlatShape::Nothing => write!(f, "shape_nothing"), - FlatShape::Operator => write!(f, "shape_operator"), - FlatShape::Or => write!(f, "shape_or"), - FlatShape::Pipe => write!(f, "shape_pipe"), - FlatShape::Range => write!(f, "shape_range"), - FlatShape::RawString => write!(f, "shape_raw_string"), - FlatShape::Record => write!(f, "shape_record"), - FlatShape::Redirection => write!(f, "shape_redirection"), - FlatShape::Signature => write!(f, "shape_signature"), - FlatShape::String => write!(f, "shape_string"), - FlatShape::StringInterpolation => write!(f, "shape_string_interpolation"), - FlatShape::Table => write!(f, "shape_table"), - FlatShape::Variable(_) => write!(f, "shape_variable"), - FlatShape::VarDecl(_) => write!(f, "shape_vardecl"), - } + f.write_str(self.as_str()) } } diff --git a/crates/nu-table/src/types/general.rs b/crates/nu-table/src/types/general.rs index ee09248fb1..4a6cd302e8 100644 --- a/crates/nu-table/src/types/general.rs +++ b/crates/nu-table/src/types/general.rs @@ -99,7 +99,7 @@ fn table(input: &[Value], opts: &TableOpts<'_>) -> TableResult { .filter(|header| header != INDEX_COLUMN_NAME) .collect(); - let table = to_table_with_header(input, headers, with_index, row_offset, opts)?; + let table = to_table_with_header(input, &headers, with_index, row_offset, opts)?; let table = table.map(|table| TableOutput::new(table, true, with_index)); Ok(table) @@ -107,7 +107,7 @@ fn table(input: &[Value], opts: &TableOpts<'_>) -> TableResult { fn to_table_with_header( input: &[Value], - headers: Vec, + headers: &[String], with_index: bool, row_offset: usize, opts: &TableOpts<'_>, diff --git a/crates/nu-test-support/src/macros.rs b/crates/nu-test-support/src/macros.rs index d79c358885..c18dd5ac81 100644 --- a/crates/nu-test-support/src/macros.rs +++ b/crates/nu-test-support/src/macros.rs @@ -284,7 +284,7 @@ pub fn nu_run_test(opts: NuOpts, commands: impl AsRef, with_std: bool) -> O command.arg("--no-std-lib"); } command - .arg(format!("-c {}", escape_quote_string(commands))) + .arg(format!("-c {}", escape_quote_string(&commands))) .stdout(Stdio::piped()) .stderr(Stdio::piped()); @@ -353,7 +353,7 @@ where let plugin_path = nu_path::canonicalize_with(&plugin, &test_bins) .unwrap_or_else(|_| panic!("failed to canonicalize plugin {} path", &plugin)); let plugin_path = plugin_path.to_string_lossy(); - escape_quote_string(plugin_path.into_owned()) + escape_quote_string(&plugin_path) }) .collect(); let plugins_arg = format!("[{}]", plugin_paths_quoted.join(",")); @@ -397,7 +397,7 @@ where Outcome::new(out, err.into_owned(), output.status) } -fn escape_quote_string(input: String) -> String { +fn escape_quote_string(input: &str) -> String { let mut output = String::with_capacity(input.len() + 2); output.push('"'); diff --git a/crates/nu-test-support/src/playground/play.rs b/crates/nu-test-support/src/playground/play.rs index 6e229e0c8f..902997200e 100644 --- a/crates/nu-test-support/src/playground/play.rs +++ b/crates/nu-test-support/src/playground/play.rs @@ -199,7 +199,7 @@ impl<'a> Playground<'a> { self } - pub fn with_files(&mut self, files: Vec) -> &mut Self { + pub fn with_files(&mut self, files: &[Stub]) -> &mut Self { let endl = fs::line_ending(); files diff --git a/tests/modules/mod.rs b/tests/modules/mod.rs index 2e868c3e5d..c556d6fa7a 100644 --- a/tests/modules/mod.rs +++ b/tests/modules/mod.rs @@ -7,7 +7,7 @@ use pretty_assertions::assert_eq; fn module_private_import_decl() { Playground::setup("module_private_import_decl", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " use spam.nu foo-helper @@ -15,7 +15,7 @@ fn module_private_import_decl() { export def foo [] { foo-helper } ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def get-foo [] { "foo" } @@ -35,7 +35,7 @@ fn module_private_import_decl() { fn module_private_import_alias() { Playground::setup("module_private_import_alias", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " use spam.nu foo-helper @@ -43,7 +43,7 @@ fn module_private_import_alias() { export def foo [] { foo-helper } ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export alias foo-helper = echo "foo" @@ -62,13 +62,13 @@ fn module_private_import_alias() { fn module_private_import_decl_not_public() { Playground::setup("module_private_import_decl_not_public", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " use spam.nu foo-helper ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def get-foo [] { "foo" } @@ -88,13 +88,13 @@ fn module_private_import_decl_not_public() { fn module_public_import_decl() { Playground::setup("module_public_import_decl", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export use spam.nu foo ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def foo-helper [] { "foo" } @@ -114,13 +114,13 @@ fn module_public_import_decl() { fn module_public_import_alias() { Playground::setup("module_public_import_alias", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export use spam.nu foo ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export alias foo = echo "foo" @@ -139,25 +139,25 @@ fn module_public_import_alias() { fn module_nested_imports() { Playground::setup("module_nested_imports", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export use spam.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", " export use spam2.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam2.nu", " export use spam3.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam3.nu", r#" export def foo [] { "foo" } @@ -183,25 +183,25 @@ fn module_nested_imports_in_dirs() { .mkdir("spam") .mkdir("spam/spam2") .mkdir("spam/spam3") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export use spam/spam.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam.nu", " export use spam2/spam2.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam2/spam2.nu", " export use ../spam3/spam3.nu [ foo bar ] ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam3/spam3.nu", r#" export def foo [] { "foo" } @@ -224,13 +224,13 @@ fn module_nested_imports_in_dirs() { fn module_public_import_decl_prefixed() { Playground::setup("module_public_import_decl", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export use spam.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" def foo-helper [] { "foo" } @@ -253,26 +253,26 @@ fn module_nested_imports_in_dirs_prefixed() { .mkdir("spam") .mkdir("spam/spam2") .mkdir("spam/spam3") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", r#" export use spam/spam.nu [ "spam2 foo" "spam2 spam3 bar" ] "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam.nu", " export use spam2/spam2.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam2/spam2.nu", " export use ../spam3/spam3.nu export use ../spam3/spam3.nu foo ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam/spam3/spam3.nu", r#" export def foo [] { "foo" } @@ -295,7 +295,7 @@ fn module_nested_imports_in_dirs_prefixed() { fn module_import_env_1() { Playground::setup("module_import_env_1", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export-env { source-env spam.nu } @@ -303,7 +303,7 @@ fn module_import_env_1() { export def foo [] { $env.FOO_HELPER } ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { $env.FOO_HELPER = "foo" } @@ -322,13 +322,13 @@ fn module_import_env_1() { fn module_import_env_2() { Playground::setup("module_import_env_2", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " export-env { source-env spam.nu } ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export-env { $env.FOO = "foo" } @@ -346,7 +346,7 @@ fn module_import_env_2() { #[test] fn module_cyclical_imports_0() { Playground::setup("module_cyclical_imports_0", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", " use eggs.nu @@ -364,7 +364,7 @@ fn module_cyclical_imports_0() { #[test] fn module_cyclical_imports_1() { Playground::setup("module_cyclical_imports_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", " use spam.nu @@ -383,13 +383,13 @@ fn module_cyclical_imports_1() { fn module_cyclical_imports_2() { Playground::setup("module_cyclical_imports_2", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", " use eggs.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "eggs.nu", " use spam.nu @@ -408,19 +408,19 @@ fn module_cyclical_imports_2() { fn module_cyclical_imports_3() { Playground::setup("module_cyclical_imports_3", |dirs, sandbox| { sandbox - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "spam.nu", " use eggs.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "eggs.nu", " use bacon.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "bacon.nu", " use spam.nu @@ -438,7 +438,7 @@ fn module_cyclical_imports_3() { #[test] fn module_import_const_file() { Playground::setup("module_import_const_file", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export def foo [] { "foo" } @@ -456,7 +456,7 @@ fn module_import_const_file() { #[test] fn module_import_const_module_name() { Playground::setup("module_import_const_file", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam.nu", r#" export def foo [] { "foo" } diff --git a/tests/overlays/mod.rs b/tests/overlays/mod.rs index c5ddf81e33..15697f467d 100644 --- a/tests/overlays/mod.rs +++ b/tests/overlays/mod.rs @@ -873,7 +873,7 @@ fn overlay_use_do_cd() { Playground::setup("overlay_use_do_cd", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", " export-env { cd test1/test2 } @@ -896,7 +896,7 @@ fn overlay_use_do_cd_file_relative() { Playground::setup("overlay_use_do_cd_file_relative", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", " export-env { cd ($env.FILE_PWD | path join '..') } @@ -919,7 +919,7 @@ fn overlay_use_dont_cd_overlay() { Playground::setup("overlay_use_dont_cd_overlay", |dirs, sandbox| { sandbox .mkdir("test1/test2") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "test1/test2/spam.nu", " export-env { diff --git a/tests/parsing/mod.rs b/tests/parsing/mod.rs index 3bbed9b7c4..5a6b55fc44 100644 --- a/tests/parsing/mod.rs +++ b/tests/parsing/mod.rs @@ -93,7 +93,7 @@ fn parse_file_relative_to_parsed_file_simple() { sandbox .mkdir("lol") .mkdir("lol/lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol/lol.nu", " use ../lol_shell.nu @@ -101,7 +101,7 @@ fn parse_file_relative_to_parsed_file_simple() { $env.LOL = (lol_shell ls) ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol_shell.nu", r#" export def ls [] { "lol" } @@ -123,7 +123,7 @@ fn parse_file_relative_to_parsed_file_simple() { #[test] fn predecl_signature_single_inp_out_type() { Playground::setup("predecl_signature_single_inp_out_type", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam1.nu", " def main [] { foo } @@ -143,7 +143,7 @@ fn predecl_signature_multiple_inp_out_types() { Playground::setup( "predecl_signature_multiple_inp_out_types", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "spam2.nu", " def main [] { foo } @@ -166,7 +166,7 @@ fn parse_file_relative_to_parsed_file() { sandbox .mkdir("lol") .mkdir("lol/lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol/lol.nu", " source-env ../../foo.nu @@ -176,13 +176,13 @@ fn parse_file_relative_to_parsed_file() { $env.LOL = $'($env.FOO) (lol_shell ls) (ls)' ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol_shell.nu", r#" export def ls [] { "lol" } "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", " $env.FOO = 'foo' @@ -206,19 +206,19 @@ fn parse_file_relative_to_parsed_file_dont_use_cwd_1() { Playground::setup("relative_files", |dirs, sandbox| { sandbox .mkdir("lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol.nu", " source-env foo.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/foo.nu", " $env.FOO = 'good' ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", " $env.FOO = 'bad' @@ -242,13 +242,13 @@ fn parse_file_relative_to_parsed_file_dont_use_cwd_2() { Playground::setup("relative_files", |dirs, sandbox| { sandbox .mkdir("lol") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "lol/lol.nu", " source-env foo.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", " $env.FOO = 'bad' diff --git a/tests/path/canonicalize.rs b/tests/path/canonicalize.rs index cf40a0024c..f714480779 100644 --- a/tests/path/canonicalize.rs +++ b/tests/path/canonicalize.rs @@ -8,7 +8,7 @@ use std::path::Path; #[test] fn canonicalize_path() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let mut spam = dirs.test().to_owned(); spam.push("spam.txt"); @@ -23,7 +23,7 @@ fn canonicalize_path() { #[test] fn canonicalize_unicode_path() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("🚒.txt")]); + sandbox.with_files(&[EmptyFile("🚒.txt")]); let mut spam = dirs.test().to_owned(); spam.push("🚒.txt"); @@ -45,7 +45,7 @@ fn canonicalize_non_utf8_path() { #[test] fn canonicalize_path_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("spam.txt", dirs.test()).expect("Failed to canonicalize"); let mut expected = dirs.test().to_owned(); @@ -59,7 +59,7 @@ fn canonicalize_path_relative_to() { fn canonicalize_unicode_path_relative_to_unicode_path_with_spaces() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("e-$ èрт🚒♞中片-j"); - sandbox.with_files(vec![EmptyFile("e-$ èрт🚒♞中片-j/🚒.txt")]); + sandbox.with_files(&[EmptyFile("e-$ èрт🚒♞中片-j/🚒.txt")]); let mut relative_to = dirs.test().to_owned(); relative_to.push("e-$ èрт🚒♞中片-j"); @@ -81,7 +81,7 @@ fn canonicalize_non_utf8_path_relative_to_non_utf8_path_with_spaces() { #[test] fn canonicalize_absolute_path_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let mut absolute_path = dirs.test().to_owned(); absolute_path.push("spam.txt"); @@ -116,7 +116,7 @@ fn canonicalize_many_dots() { #[test] fn canonicalize_path_with_dot_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("./spam.txt", dirs.test()).expect("Failed to canonicalize"); let mut expected = dirs.test().to_owned(); @@ -129,7 +129,7 @@ fn canonicalize_path_with_dot_relative_to() { #[test] fn canonicalize_path_with_many_dots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("././/.//////./././//.////spam.txt", dirs.test()) .expect("Failed to canonicalize"); @@ -155,7 +155,7 @@ fn canonicalize_double_dot() { fn canonicalize_path_with_double_dot_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("foo/../spam.txt", dirs.test()).expect("Failed to canonicalize"); @@ -170,7 +170,7 @@ fn canonicalize_path_with_double_dot_relative_to() { fn canonicalize_path_with_many_double_dots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("foo/bar/baz/../../../spam.txt", dirs.test()) .expect("Failed to canonicalize"); @@ -205,7 +205,7 @@ fn canonicalize_ndots2() { fn canonicalize_path_with_3_ndots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("foo/bar/.../spam.txt", dirs.test()).expect("Failed to canonicalize"); @@ -220,7 +220,7 @@ fn canonicalize_path_with_3_ndots_relative_to() { fn canonicalize_path_with_many_3_ndots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz/eggs/sausage/bacon"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with( "foo/bar/baz/eggs/sausage/bacon/.../.../.../spam.txt", @@ -238,7 +238,7 @@ fn canonicalize_path_with_many_3_ndots_relative_to() { fn canonicalize_path_with_4_ndots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with("foo/bar/baz/..../spam.txt", dirs.test()) .expect("Failed to canonicalize"); @@ -253,7 +253,7 @@ fn canonicalize_path_with_4_ndots_relative_to() { fn canonicalize_path_with_many_4_ndots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz/eggs/sausage/bacon"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let actual = canonicalize_with( "foo/bar/baz/eggs/sausage/bacon/..../..../spam.txt", @@ -271,7 +271,7 @@ fn canonicalize_path_with_many_4_ndots_relative_to() { fn canonicalize_path_with_way_too_many_dots_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz/eggs/sausage/bacon/vikings"); - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); let mut relative_to = dirs.test().to_owned(); relative_to.push("foo/bar/baz/eggs/sausage/bacon/vikings"); @@ -289,7 +289,7 @@ fn canonicalize_path_with_way_too_many_dots_relative_to() { fn canonicalize_unicode_path_with_way_too_many_dots_relative_to_unicode_path_with_spaces() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/áčěéí +šř=é/baz/eggs/e-$ èрт🚒♞中片-j/bacon/öäöä öäöä"); - sandbox.with_files(vec![EmptyFile("🚒.txt")]); + sandbox.with_files(&[EmptyFile("🚒.txt")]); let mut relative_to = dirs.test().to_owned(); relative_to.push("foo/áčěéí +šř=é/baz/eggs/e-$ èрт🚒♞中片-j/bacon/öäöä öäöä"); @@ -329,7 +329,7 @@ fn canonicalize_tilde_relative_to() { #[test] fn canonicalize_symlink() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); sandbox.symlink("spam.txt", "link_to_spam.txt"); let mut symlink_path = dirs.test().to_owned(); @@ -348,7 +348,7 @@ fn canonicalize_symlink() { #[test] fn canonicalize_symlink_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); sandbox.symlink("spam.txt", "link_to_spam.txt"); let actual = @@ -379,7 +379,7 @@ fn canonicalize_symlink_loop_relative_to_should_fail() { #[test] fn canonicalize_nested_symlink_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { - sandbox.with_files(vec![EmptyFile("spam.txt")]); + sandbox.with_files(&[EmptyFile("spam.txt")]); sandbox.symlink("spam.txt", "link_to_spam.txt"); sandbox.symlink("link_to_spam.txt", "link_to_link_to_spam.txt"); @@ -397,7 +397,7 @@ fn canonicalize_nested_symlink_relative_to() { fn canonicalize_nested_symlink_within_symlink_dir_relative_to() { Playground::setup("nu_path_test_1", |dirs, sandbox| { sandbox.mkdir("foo/bar/baz"); - sandbox.with_files(vec![EmptyFile("foo/bar/baz/spam.txt")]); + sandbox.with_files(&[EmptyFile("foo/bar/baz/spam.txt")]); sandbox.symlink("foo/bar/baz/spam.txt", "foo/bar/link_to_spam.txt"); sandbox.symlink("foo/bar/link_to_spam.txt", "foo/link_to_link_to_spam.txt"); sandbox.symlink("foo", "link_to_foo"); diff --git a/tests/plugins/core_inc.rs b/tests/plugins/core_inc.rs index 28017c4b23..64890dd32d 100644 --- a/tests/plugins/core_inc.rs +++ b/tests/plugins/core_inc.rs @@ -26,7 +26,7 @@ fn chooses_highest_increment_if_given_more_than_one() { #[test] fn by_one_with_field_passed() { Playground::setup("plugin_inc_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -47,7 +47,7 @@ fn by_one_with_field_passed() { #[test] fn by_one_with_no_field_passed() { Playground::setup("plugin_inc_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -68,7 +68,7 @@ fn by_one_with_no_field_passed() { #[test] fn semversion_major_inc() { Playground::setup("plugin_inc_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -89,7 +89,7 @@ fn semversion_major_inc() { #[test] fn semversion_minor_inc() { Playground::setup("plugin_inc_test_4", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -110,7 +110,7 @@ fn semversion_minor_inc() { #[test] fn semversion_patch_inc() { Playground::setup("plugin_inc_test_5", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] @@ -131,7 +131,7 @@ fn semversion_patch_inc() { #[test] fn semversion_without_passing_field() { Playground::setup("plugin_inc_test_6", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" [package] diff --git a/tests/plugins/formats/ics.rs b/tests/plugins/formats/ics.rs index c503f6569d..2ab827d0be 100644 --- a/tests/plugins/formats/ics.rs +++ b/tests/plugins/formats/ics.rs @@ -6,7 +6,7 @@ use pretty_assertions::assert_eq; #[test] fn infers_types() { Playground::setup("filter_from_ics_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "calendar.ics", r#" BEGIN:VCALENDAR @@ -58,7 +58,7 @@ fn infers_types() { #[test] fn from_ics_text_to_table() { Playground::setup("filter_from_ics_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "calendar.txt", r#" BEGIN:VCALENDAR @@ -102,7 +102,7 @@ fn from_ics_text_to_table() { #[test] fn from_ics_text_with_linebreak_to_table() { Playground::setup("filter_from_ics_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "calendar.txt", r#"BEGIN:VCALENDAR BEGIN:VEVENT diff --git a/tests/plugins/formats/ini.rs b/tests/plugins/formats/ini.rs index cd467d5559..eee592dac6 100644 --- a/tests/plugins/formats/ini.rs +++ b/tests/plugins/formats/ini.rs @@ -33,7 +33,7 @@ fn parses_utf16_ini() { #[test] fn read_ini_with_missing_session() { Playground::setup("from ini with missiong session", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "some_missing.ini", r#" min-width=450 diff --git a/tests/plugins/formats/vcf.rs b/tests/plugins/formats/vcf.rs index d57269bbdd..b2012ab184 100644 --- a/tests/plugins/formats/vcf.rs +++ b/tests/plugins/formats/vcf.rs @@ -6,7 +6,7 @@ use pretty_assertions::assert_eq; #[test] fn infers_types() { Playground::setup("filter_from_vcf_test_1", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "contacts.vcf", r" BEGIN:VCARD @@ -46,7 +46,7 @@ fn infers_types() { #[test] fn from_vcf_text_to_table() { Playground::setup("filter_from_vcf_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "contacts.txt", r" BEGIN:VCARD @@ -86,7 +86,7 @@ fn from_vcf_text_to_table() { #[test] fn from_vcf_text_with_linebreak_to_table() { Playground::setup("filter_from_vcf_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "contacts.txt", r"BEGIN:VCARD VERSION:3.0 diff --git a/tests/plugins/registry_file.rs b/tests/plugins/registry_file.rs index 674be48f15..3f7da6dd03 100644 --- a/tests/plugins/registry_file.rs +++ b/tests/plugins/registry_file.rs @@ -136,7 +136,7 @@ fn plugin_add_to_custom_path() { fn plugin_rm_then_restart_nu() { let example_plugin_path = example_plugin_path(); Playground::setup("plugin rm from custom path", |dirs, playground| { - playground.with_files(vec![ + playground.with_files(&[ Stub::FileWithContent("config.nu", ""), Stub::FileWithContent("env.nu", ""), ]); @@ -318,7 +318,7 @@ fn plugin_rm_using_filename() { fn warning_on_invalid_plugin_item() { let example_plugin_path = example_plugin_path(); Playground::setup("warning on invalid plugin item", |dirs, playground| { - playground.with_files(vec![ + playground.with_files(&[ Stub::FileWithContent("config.nu", ""), Stub::FileWithContent("env.nu", ""), ]); @@ -380,7 +380,7 @@ fn warning_on_invalid_plugin_item() { #[test] fn plugin_use_error_not_found() { Playground::setup("plugin use error not found", |dirs, playground| { - playground.with_files(vec![ + playground.with_files(&[ Stub::FileWithContent("config.nu", ""), Stub::FileWithContent("env.nu", ""), ]); diff --git a/tests/scope/mod.rs b/tests/scope/mod.rs index c6ff308802..bfcbb14958 100644 --- a/tests/scope/mod.rs +++ b/tests/scope/mod.rs @@ -109,7 +109,7 @@ fn correct_scope_modules_fields() { "#; Playground::setup("correct_scope_modules_fields", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]); + sandbox.with_files(&[FileWithContent("spam.nu", module_setup)]); let inp = &[ "use spam.nu", @@ -191,7 +191,7 @@ fn correct_scope_aliases_fields() { "#; Playground::setup("correct_scope_aliases_fields", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]); + sandbox.with_files(&[FileWithContent("spam.nu", module_setup)]); let inp = &[ "use spam.nu", @@ -248,7 +248,7 @@ fn correct_scope_externs_fields() { "#; Playground::setup("correct_scope_aliases_fields", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent("spam.nu", module_setup)]); + sandbox.with_files(&[FileWithContent("spam.nu", module_setup)]); let inp = &[ "use spam.nu", diff --git a/tests/shell/environment/env.rs b/tests/shell/environment/env.rs index f44d634b4d..7061761c70 100644 --- a/tests/shell/environment/env.rs +++ b/tests/shell/environment/env.rs @@ -129,7 +129,7 @@ fn passes_with_env_env_var_to_external_process() { #[test] fn has_file_pwd() { Playground::setup("has_file_pwd", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent("spam.nu", "$env.FILE_PWD")]); + sandbox.with_files(&[FileWithContent("spam.nu", "$env.FILE_PWD")]); let actual = nu!(cwd: dirs.test(), "nu spam.nu"); @@ -140,7 +140,7 @@ fn has_file_pwd() { #[test] fn has_file_loc() { Playground::setup("has_file_pwd", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent("spam.nu", "$env.CURRENT_FILE")]); + sandbox.with_files(&[FileWithContent("spam.nu", "$env.CURRENT_FILE")]); let actual = nu!(cwd: dirs.test(), "nu spam.nu"); @@ -154,7 +154,7 @@ fn has_file_loc() { #[serial] fn passes_env_from_local_cfg_to_external_process() { Playground::setup("autoenv_dir", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( ".nu-env", r#"[env] FOO = "foo" diff --git a/tests/shell/mod.rs b/tests/shell/mod.rs index 7f15d3027c..ba7465f5e7 100644 --- a/tests/shell/mod.rs +++ b/tests/shell/mod.rs @@ -65,7 +65,7 @@ fn nu_lib_dirs_repl() { Playground::setup("nu_lib_dirs_repl", |dirs, sandbox| { sandbox .mkdir("scripts") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "scripts/foo.nu", r#" $env.FOO = "foo" @@ -90,13 +90,13 @@ fn nu_lib_dirs_script() { Playground::setup("nu_lib_dirs_script", |dirs, sandbox| { sandbox .mkdir("scripts") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "scripts/foo.nu", r#" $env.FOO = "foo" "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " source-env foo.nu @@ -121,7 +121,7 @@ fn nu_lib_dirs_relative_repl() { Playground::setup("nu_lib_dirs_relative_repl", |dirs, sandbox| { sandbox .mkdir("scripts") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "scripts/foo.nu", r#" $env.FOO = "foo" @@ -147,13 +147,13 @@ fn const_nu_lib_dirs_relative() { Playground::setup("const_nu_lib_dirs_relative", |dirs, sandbox| { sandbox .mkdir("scripts") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "scripts/foo.nu", r#" $env.FOO = "foo" "#, )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "main.nu", " const NU_LIB_DIRS = [ 'scripts' ] @@ -174,13 +174,13 @@ fn nu_lib_dirs_relative_script() { Playground::setup("nu_lib_dirs_relative_script", |dirs, sandbox| { sandbox .mkdir("scripts") - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "scripts/main.nu", " source-env ../foo.nu ", )]) - .with_files(vec![FileWithContentToBeTrimmed( + .with_files(&[FileWithContentToBeTrimmed( "foo.nu", r#" $env.FOO = "foo" @@ -288,7 +288,7 @@ fn run_with_no_newline() { fn main_script_can_have_subcommands1() { Playground::setup("main_subcommands", |dirs, sandbox| { sandbox.mkdir("main_subcommands"); - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "script.nu", r#"def "main foo" [x: int] { print ($x + 100) @@ -309,7 +309,7 @@ fn main_script_can_have_subcommands1() { fn main_script_can_have_subcommands2() { Playground::setup("main_subcommands", |dirs, sandbox| { sandbox.mkdir("main_subcommands"); - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "script.nu", r#"def "main foo" [x: int] { print ($x + 100) @@ -330,7 +330,7 @@ fn main_script_can_have_subcommands2() { fn source_empty_file() { Playground::setup("source_empty_file", |dirs, sandbox| { sandbox.mkdir("source_empty_file"); - sandbox.with_files(vec![FileWithContent("empty.nu", "")]); + sandbox.with_files(&[FileWithContent("empty.nu", "")]); let actual = nu!(cwd: dirs.test(), pipeline("nu empty.nu")); assert!(actual.out.is_empty()); diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 4b9427c32c..8d8bf137cc 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -168,7 +168,7 @@ fn err_pipe_with_failed_external_works() { #[test] fn dont_run_glob_if_pass_variable_to_external() { Playground::setup("dont_run_glob", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("jt_likes_cake.txt"), EmptyFile("andres_likes_arepas.txt"), ]); @@ -182,7 +182,7 @@ fn dont_run_glob_if_pass_variable_to_external() { #[test] fn run_glob_if_pass_variable_to_external() { Playground::setup("run_glob_on_external", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("jt_likes_cake.txt"), EmptyFile("andres_likes_arepas.txt"), ]); @@ -202,7 +202,7 @@ mod it_evaluation { #[test] fn takes_rows_of_nu_value_strings() { Playground::setup("it_argument_test_1", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("jt_likes_cake.txt"), EmptyFile("andres_likes_arepas.txt"), ]); @@ -225,7 +225,7 @@ mod it_evaluation { #[test] fn takes_rows_of_nu_value_lines() { Playground::setup("it_argument_test_2", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "nu_candies.txt", " AndrásWithKitKatzz @@ -258,7 +258,7 @@ mod it_evaluation { #[test] fn supports_fetching_given_a_column_path_to_it() { Playground::setup("it_argument_test_3", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( "sample.toml", r#" nu_party_venue = "zion" @@ -349,7 +349,7 @@ mod external_words { #[case("$ sign.toml", r#""$ sign.toml""#)] fn external_arg_with_special_characters(#[case] path: &str, #[case] nu_path_argument: &str) { Playground::setup("external_arg_with_quotes", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContent( + sandbox.with_files(&[FileWithContent( path, r#" nu_party_venue = "zion" @@ -479,7 +479,7 @@ mod external_command_arguments { Playground::setup( "expands_table_of_primitives_to_positional_arguments", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("jt_likes_cake.txt"), EmptyFile("andres_likes_arepas.txt"), EmptyFile("ferris_not_here.txt"), @@ -505,7 +505,7 @@ mod external_command_arguments { Playground::setup( "expands_table_of_primitives_to_positional_arguments", |dirs, sandbox| { - sandbox.with_files(vec![ + sandbox.with_files(&[ EmptyFile("jt_likes_cake.txt"), EmptyFile("andres_likes_arepas.txt"), EmptyFile("ferris_not_here.txt"), @@ -531,7 +531,7 @@ mod external_command_arguments { |dirs, sandbox| { sandbox.mkdir("cd"); - sandbox.with_files(vec![EmptyFile("cd/jt_likes_cake.txt")]); + sandbox.with_files(&[EmptyFile("cd/jt_likes_cake.txt")]); let actual = nu!( cwd: dirs.test(), pipeline( diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 06163639d7..7bc75b07ad 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -29,7 +29,7 @@ fn takes_rows_of_nu_value_strings_and_pipes_it_to_stdin_of_external() { #[test] fn treats_dot_dot_as_path_not_range() { Playground::setup("dot_dot_dir", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "nu_times.csv", " name,rusty_luck,origin @@ -83,7 +83,7 @@ fn for_loop() { #[test] fn subexpression_handles_dot() { Playground::setup("subexpression_handles_dot", |dirs, sandbox| { - sandbox.with_files(vec![FileWithContentToBeTrimmed( + sandbox.with_files(&[FileWithContentToBeTrimmed( "nu_times.csv", " name,rusty_luck,origin From a1287f7b3fa29d813fc9e3db7c7a73832d903e58 Mon Sep 17 00:00:00 2001 From: Maxim Uvarov Date: Sat, 4 May 2024 09:14:55 +0800 Subject: [PATCH 02/15] add more tests to the `polars` plugin (#12719) # Description I added some more tests to our mighty `polars` ~~, yet I don't know how to add expected results in some of them. I would like to ask for help.~~ ~~My experiments are in the last commit: [polars: experiments](https://github.com/nushell/nushell/commit/f7e5e72019ee55b0e6745c1dc405c9a37ced67d1). Without those experiments `cargo test` goes well.~~ UPD. I moved out my unsuccessful test experiments into a separate [branch](https://github.com/maxim-uvarov/nushell/blob/polars-tests-broken2/). So, this branch seems ready for a merge. @ayax79, maybe you'll find time for me please? It's not urgent for sure. P.S. I'm very new to git. Please feel free to give me any suggestions on how I should use it better --- .../src/dataframe/eager/sample.rs | 34 +++++++++- .../src/dataframe/lazy/to_lazy.rs | 10 ++- .../src/dataframe/series/cumulative.rs | 65 +++++++++++++------ .../src/dataframe/series/date/as_date.rs | 28 ++++++-- .../src/dataframe/series/date/as_datetime.rs | 24 +++++++ .../src/dataframe/series/shift.rs | 54 ++++++++++----- 6 files changed, 169 insertions(+), 46 deletions(-) diff --git a/crates/nu_plugin_polars/src/dataframe/eager/sample.rs b/crates/nu_plugin_polars/src/dataframe/eager/sample.rs index 48ca05959a..59f9ad6eee 100644 --- a/crates/nu_plugin_polars/src/dataframe/eager/sample.rs +++ b/crates/nu_plugin_polars/src/dataframe/eager/sample.rs @@ -1,14 +1,14 @@ use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; use nu_protocol::{ - Category, Example, LabeledError, PipelineData, ShellError, Signature, Spanned, SyntaxShape, - Type, + Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, Spanned, + SyntaxShape, Type, Value, }; use polars::prelude::NamedFrom; use polars::series::Series; use crate::{values::CustomValueSupport, PolarsPlugin}; -use super::super::values::NuDataFrame; +use super::super::values::{Column, NuDataFrame}; #[derive(Clone)] pub struct SampleDF; @@ -66,6 +66,23 @@ impl PluginCommand for SampleDF { "[[a b]; [1 2] [3 4] [5 6]] | polars into-df | polars sample --fraction 0.5 --replace", result: None, // No expected value because sampling is random }, + Example { + description: "Shows sample row using using predefined seed 1", + example: + "[[a b]; [1 2] [3 4] [5 6]] | polars into-df | polars sample --seed 1 --n-rows 1", + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new("a".to_string(), vec![Value::test_int(5)]), + Column::new("b".to_string(), vec![Value::test_int(6)]), + ], + None, + ) + .expect("should not fail") + .into_value(Span::test_data()), + ) + }, + ] } @@ -133,3 +150,14 @@ fn command( let df = NuDataFrame::new(false, df?); df.to_pipeline_data(plugin, engine, call.head) } + +#[cfg(test)] +mod test { + use super::*; + use crate::test::test_polars_plugin_command; + + #[test] + fn test_examples() -> Result<(), ShellError> { + test_polars_plugin_command(&SampleDF) + } +} diff --git a/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs b/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs index 2437699b54..c4e013ac6a 100644 --- a/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs +++ b/crates/nu_plugin_polars/src/dataframe/lazy/to_lazy.rs @@ -33,10 +33,16 @@ impl PluginCommand for ToLazyFrame { fn examples(&self) -> Vec { vec![Example { - description: "Takes a dictionary and creates a lazy dataframe", + description: "Takes a table and creates a lazyframe", example: "[[a b];[1 2] [3 4]] | polars into-lazy", result: None, - }] + }, + Example { + description: "Takes a table, creates a lazyframe, assigns column 'b' type str, displays the schema", + example: "[[a b];[1 2] [3 4]] | polars into-lazy --schema {b: str} | polars schema", + result: None + }, + ] } fn run( diff --git a/crates/nu_plugin_polars/src/dataframe/series/cumulative.rs b/crates/nu_plugin_polars/src/dataframe/series/cumulative.rs index ad4740663e..7455297b59 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/cumulative.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/cumulative.rs @@ -67,27 +67,50 @@ impl PluginCommand for Cumulative { } fn examples(&self) -> Vec { - vec![Example { - description: "Cumulative sum for a series", - example: "[1 2 3 4 5] | polars into-df | polars cumulative sum", - result: Some( - NuDataFrame::try_from_columns( - vec![Column::new( - "0_cumulative_sum".to_string(), - vec![ - Value::test_int(1), - Value::test_int(3), - Value::test_int(6), - Value::test_int(10), - Value::test_int(15), - ], - )], - None, - ) - .expect("simple df for test should not fail") - .into_value(Span::test_data()), - ), - }] + vec![ + Example { + description: "Cumulative sum for a series", + example: "[1 2 3 4 5] | polars into-df | polars cumulative sum", + result: Some( + NuDataFrame::try_from_columns( + vec![Column::new( + "0_cumulative_sum".to_string(), + vec![ + Value::test_int(1), + Value::test_int(3), + Value::test_int(6), + Value::test_int(10), + Value::test_int(15), + ], + )], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + Example { + description: "Cumulative sum for a series in reverse order", + example: "[1 2 3 4 5] | polars into-df | polars cumulative sum --reverse", + result: Some( + NuDataFrame::try_from_columns( + vec![Column::new( + "0_cumulative_sum".to_string(), + vec![ + Value::test_int(15), + Value::test_int(14), + Value::test_int(12), + Value::test_int(9), + Value::test_int(5), + ], + )], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + ] } fn run( diff --git a/crates/nu_plugin_polars/src/dataframe/series/date/as_date.rs b/crates/nu_plugin_polars/src/dataframe/series/date/as_date.rs index 5228a25e51..414853d291 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/date/as_date.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/date/as_date.rs @@ -41,11 +41,18 @@ impl PluginCommand for AsDate { } fn examples(&self) -> Vec { - vec![Example { - description: "Converts string to date", - example: r#"["2021-12-30" "2021-12-31"] | polars into-df | polars as-date "%Y-%m-%d""#, - result: None, - }] + vec![ + Example { + description: "Converts string to date", + example: r#"["2021-12-30" "2021-12-31"] | polars into-df | polars as-date "%Y-%m-%d""#, + result: None, // help is needed on how to provide results + }, + Example { + description: "Converts string to date", + example: r#"["2021-12-30" "2021-12-31 21:00:00"] | polars into-df | polars as-date "%Y-%m-%d" --not-exact"#, + result: None, + }, + ] } fn run( @@ -99,3 +106,14 @@ fn command( let df = NuDataFrame::try_from_series_vec(vec![res], call.head)?; df.to_pipeline_data(plugin, engine, call.head) } + +#[cfg(test)] +mod test { + use super::*; + use crate::test::test_polars_plugin_command; + + #[test] + fn test_examples() -> Result<(), ShellError> { + test_polars_plugin_command(&AsDate) + } +} diff --git a/crates/nu_plugin_polars/src/dataframe/series/date/as_datetime.rs b/crates/nu_plugin_polars/src/dataframe/series/date/as_datetime.rs index 2cbea57507..8e01fda6ac 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/date/as_datetime.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/date/as_datetime.rs @@ -116,6 +116,30 @@ impl PluginCommand for AsDateTime { .into_value(Span::test_data()), ), }, + Example { + description: "Converts string to datetime using the `--not-exact` flag even with excessive symbols", + example: r#"["2021-12-30 00:00:00 GMT+4"] | polars into-df | polars as-datetime "%Y-%m-%d %H:%M:%S" --not-exact"#, + result: Some( + NuDataFrame::try_from_columns( + vec![Column::new( + "datetime".to_string(), + vec![ + Value::date( + DateTime::parse_from_str( + "2021-12-30 00:00:00 +0000", + "%Y-%m-%d %H:%M:%S %z", + ) + .expect("date calculation should not fail in test"), + Span::test_data(), + ), + ], + )], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, ] } diff --git a/crates/nu_plugin_polars/src/dataframe/series/shift.rs b/crates/nu_plugin_polars/src/dataframe/series/shift.rs index 9b5f8b2f63..64e8fe5b62 100644 --- a/crates/nu_plugin_polars/src/dataframe/series/shift.rs +++ b/crates/nu_plugin_polars/src/dataframe/series/shift.rs @@ -45,21 +45,45 @@ impl PluginCommand for Shift { } fn examples(&self) -> Vec { - vec![Example { - description: "Shifts the values by a given period", - example: "[1 2 2 3 3] | polars into-df | polars shift 2 | polars drop-nulls", - result: Some( - NuDataFrame::try_from_columns( - vec![Column::new( - "0".to_string(), - vec![Value::test_int(1), Value::test_int(2), Value::test_int(2)], - )], - None, - ) - .expect("simple df for test should not fail") - .into_value(Span::test_data()), - ), - }] + vec![ + Example { + description: "Shifts the values by a given period", + example: "[1 2 2 3 3] | polars into-df | polars shift 2 | polars drop-nulls", + result: Some( + NuDataFrame::try_from_columns( + vec![Column::new( + "0".to_string(), + vec![Value::test_int(1), Value::test_int(2), Value::test_int(2)], + )], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + Example { + description: "Shifts the values by a given period, fill absent values with 0", + example: + "[1 2 2 3 3] | polars into-lazy | polars shift 2 --fill 0 | polars collect", + result: Some( + NuDataFrame::try_from_columns( + vec![Column::new( + "0".to_string(), + vec![ + Value::test_int(0), + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(2), + ], + )], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + ] } fn run( From 35a0f7a36991ab7ec3b4da5c6e681de240d58526 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee Date: Sat, 4 May 2024 06:47:50 +0530 Subject: [PATCH 03/15] fix: prevent relative directory traversal from crashing (#12438) - fixes #11922 - fixes #12203 # Description This is a rewrite for some parts of the recursive completion system. The Rust `std::path` structures often ignores things like a trailing `.` because for a complete path, it implies the current directory. We are replacing the use of some of these structs for Strings. A side effect is the slashes being normalized in Windows. For example if we were to type `foo/bar/b`, it would complete it to `foo\bar\baz` because a backward slash is the main separator in windows. # User-Facing Changes Relative paths are preserved. `..`s in the paths won't eagerly show completions from the parent path. For example, `asd/foo/../b` will now complete to `asd/foo/../bar` instead of `asd/bar`. # Tests + Formatting # After Submitting --- .../src/completions/completion_common.rs | 191 +++++++++--------- crates/nu-cli/tests/completions.rs | 21 +- 2 files changed, 117 insertions(+), 95 deletions(-) diff --git a/crates/nu-cli/src/completions/completion_common.rs b/crates/nu-cli/src/completions/completion_common.rs index 5f927976a2..4a8b0d57ac 100644 --- a/crates/nu-cli/src/completions/completion_common.rs +++ b/crates/nu-cli/src/completions/completion_common.rs @@ -7,40 +7,65 @@ use nu_protocol::{ Span, }; use nu_utils::get_ls_colors; -use std::{ - ffi::OsStr, - path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP}, +use std::path::{ + is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR, }; +#[derive(Clone, Default)] +pub struct PathBuiltFromString { + parts: Vec, + isdir: bool, +} + fn complete_rec( - partial: &[String], + partial: &[&str], + built: &PathBuiltFromString, cwd: &Path, options: &CompletionOptions, dir: bool, isdir: bool, -) -> Vec { +) -> Vec { let mut completions = vec![]; - if let Ok(result) = cwd.read_dir() { - for entry in result.filter_map(|e| e.ok()) { - let entry_name = entry.file_name().to_string_lossy().into_owned(); - let path = entry.path(); + if let Some((&base, rest)) = partial.split_first() { + if (base == "." || base == "..") && (isdir || !rest.is_empty()) { + let mut built = built.clone(); + built.parts.push(base.to_string()); + built.isdir = true; + return complete_rec(rest, &built, cwd, options, dir, isdir); + } + } - if !dir || path.is_dir() { - match partial.first() { - Some(base) if matches(base, &entry_name, options) => { - let partial = &partial[1..]; - if !partial.is_empty() || isdir { - completions.extend(complete_rec(partial, &path, options, dir, isdir)); - if entry_name.eq(base) { - break; - } + let mut built_path = cwd.to_path_buf(); + for part in &built.parts { + built_path.push(part); + } + + let Ok(result) = built_path.read_dir() else { + return completions; + }; + + for entry in result.filter_map(|e| e.ok()) { + let entry_name = entry.file_name().to_string_lossy().into_owned(); + let entry_isdir = entry.path().is_dir(); + let mut built = built.clone(); + built.parts.push(entry_name.clone()); + built.isdir = entry_isdir; + + if !dir || entry_isdir { + match partial.split_first() { + Some((base, rest)) => { + if matches(base, &entry_name, options) { + if !rest.is_empty() || isdir { + completions + .extend(complete_rec(rest, &built, cwd, options, dir, isdir)); } else { - completions.push(path) + completions.push(built); } } - None => completions.push(path), - _ => {} + } + None => { + completions.push(built); } } } @@ -48,33 +73,23 @@ fn complete_rec( completions } +#[derive(Debug)] enum OriginalCwd { None, - Home(PathBuf), - Some(PathBuf), - // referencing a single local file - Local(PathBuf), + Home, + Prefix(String), } impl OriginalCwd { - fn apply(&self, p: &Path) -> String { - let mut ret = match self { - Self::None => p.to_string_lossy().into_owned(), - Self::Some(base) => pathdiff::diff_paths(p, base) - .unwrap_or(p.to_path_buf()) - .to_string_lossy() - .into_owned(), - Self::Home(home) => match p.strip_prefix(home) { - Ok(suffix) => format!("~{}{}", SEP, suffix.to_string_lossy()), - _ => p.to_string_lossy().into_owned(), - }, - Self::Local(base) => Path::new(".") - .join(pathdiff::diff_paths(p, base).unwrap_or(p.to_path_buf())) - .to_string_lossy() - .into_owned(), + fn apply(&self, mut p: PathBuiltFromString) -> String { + match self { + Self::None => {} + Self::Home => p.parts.insert(0, "~".to_string()), + Self::Prefix(s) => p.parts.insert(0, s.clone()), }; - if p.is_dir() { + let mut ret = p.parts.join(MAIN_SEPARATOR_STR); + if p.isdir { ret.push(SEP); } ret @@ -116,79 +131,67 @@ pub fn complete_item( }; get_ls_colors(ls_colors_env_str) }); + + let mut cwd = cwd_pathbuf.clone(); + let mut prefix_len = 0; let mut original_cwd = OriginalCwd::None; - let mut components_vec: Vec = Path::new(&partial).components().collect(); - // Path components that end with a single "." get normalized away, - // so if the partial path ends in a literal "." we must add it back in manually - if partial.ends_with('.') && partial.len() > 1 { - components_vec.push(Component::Normal(OsStr::new("."))); - }; - let mut components = components_vec.into_iter().peekable(); - - let mut cwd = match components.peek().cloned() { + let mut components = Path::new(&partial).components().peekable(); + match components.peek().cloned() { Some(c @ Component::Prefix(..)) => { // windows only by definition components.next(); if let Some(Component::RootDir) = components.peek().cloned() { components.next(); }; - [c, Component::RootDir].iter().collect() + cwd = [c, Component::RootDir].iter().collect(); + prefix_len = c.as_os_str().len(); + original_cwd = OriginalCwd::Prefix(c.as_os_str().to_string_lossy().into_owned()); } Some(c @ Component::RootDir) => { components.next(); - PathBuf::from(c.as_os_str()) + // This is kind of a hack. When joining an empty string with the rest, + // we add the slash automagically + cwd = PathBuf::from(c.as_os_str()); + prefix_len = 1; + original_cwd = OriginalCwd::Prefix(String::new()); } Some(Component::Normal(home)) if home.to_string_lossy() == "~" => { components.next(); - original_cwd = OriginalCwd::Home(home_dir().unwrap_or(cwd_pathbuf.clone())); - home_dir().unwrap_or(cwd_pathbuf) - } - Some(Component::CurDir) => { - components.next(); - original_cwd = match components.peek().cloned() { - Some(Component::Normal(_)) | None => OriginalCwd::Local(cwd_pathbuf.clone()), - _ => OriginalCwd::Some(cwd_pathbuf.clone()), - }; - cwd_pathbuf - } - _ => { - original_cwd = OriginalCwd::Some(cwd_pathbuf.clone()); - cwd_pathbuf + cwd = home_dir().unwrap_or(cwd_pathbuf); + prefix_len = 1; + original_cwd = OriginalCwd::Home; } + _ => {} }; - let mut partial = vec![]; + let after_prefix = &partial[prefix_len..]; + let partial: Vec<_> = after_prefix + .strip_prefix(is_separator) + .unwrap_or(after_prefix) + .split(is_separator) + .filter(|s| !s.is_empty()) + .collect(); - for component in components { - match component { - Component::Prefix(..) => unreachable!(), - Component::RootDir => unreachable!(), - Component::CurDir => {} - Component::ParentDir => { - if partial.pop().is_none() { - cwd.pop(); - } - } - Component::Normal(c) => partial.push(c.to_string_lossy().into_owned()), - } - } - - complete_rec(partial.as_slice(), &cwd, options, want_directory, isdir) - .into_iter() - .map(|p| { - let path = original_cwd.apply(&p); - let style = ls_colors.as_ref().map(|lsc| { - lsc.style_for_path_with_metadata( - &path, - std::fs::symlink_metadata(&path).ok().as_ref(), - ) + complete_rec( + partial.as_slice(), + &PathBuiltFromString::default(), + &cwd, + options, + want_directory, + isdir, + ) + .into_iter() + .map(|p| { + let path = original_cwd.apply(p); + let style = ls_colors.as_ref().map(|lsc| { + lsc.style_for_path_with_metadata(&path, std::fs::symlink_metadata(&path).ok().as_ref()) .map(lscolors::Style::to_nu_ansi_term_style) .unwrap_or_default() - }); - (span, escape_path(path, want_directory), style) - }) - .collect() + }); + (span, escape_path(path, want_directory), style) + }) + .collect() } // Fix files or folders with quotes or hashes diff --git a/crates/nu-cli/tests/completions.rs b/crates/nu-cli/tests/completions.rs index 611dbfd35e..a22d770010 100644 --- a/crates/nu-cli/tests/completions.rs +++ b/crates/nu-cli/tests/completions.rs @@ -334,7 +334,26 @@ fn partial_completions() { let suggestions = completer.complete(&target_dir, target_dir.len()); // Create the expected values - let expected_paths: Vec = vec![file(dir.join("final_partial").join("somefile"))]; + let expected_paths: Vec = vec![ + file( + dir.join("partial_a") + .join("..") + .join("final_partial") + .join("somefile"), + ), + file( + dir.join("partial_b") + .join("..") + .join("final_partial") + .join("somefile"), + ), + file( + dir.join("partial_c") + .join("..") + .join("final_partial") + .join("somefile"), + ), + ]; // Match the results match_suggestions(expected_paths, suggestions); From 709b2479d98db033ac2644d27dec2341ab2be68a Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Sat, 4 May 2024 02:38:37 -0700 Subject: [PATCH 04/15] Fix trailing slash in PWD set by `cd` (#12760) # Description Fixes #12758. #12662 introduced a bug where calling `cd` with a path with a trailing slash would cause `PWD` to be set to a path including a trailing slash, which is not allowed. This adds a helper to `nu_path` to remove this, and uses it in the `cd` command to clean it up before setting `PWD`. # Tests + Formatting I added some tests to make sure we don't regress on this in the future. - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` --- crates/nu-command/src/filesystem/cd.rs | 3 + crates/nu-command/tests/commands/cd.rs | 27 +++++++ crates/nu-path/src/components.rs | 17 +--- crates/nu-path/src/lib.rs | 2 + crates/nu-path/src/trailing_slash.rs | 108 +++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 crates/nu-path/src/trailing_slash.rs diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 50ad0b35a1..f90e9bfd2a 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -100,6 +100,9 @@ impl Command for Cd { } }; + // Strip the trailing slash from the new path. This is required for PWD. + let path = nu_path::strip_trailing_slash(&path); + // Set OLDPWD. // We're using `Stack::get_env_var()` instead of `EngineState::cwd()` to avoid a conversion roundtrip. if let Some(oldpwd) = stack.get_env_var(engine_state, "PWD") { diff --git a/crates/nu-command/tests/commands/cd.rs b/crates/nu-command/tests/commands/cd.rs index fa9ea382f2..c7c30528e8 100644 --- a/crates/nu-command/tests/commands/cd.rs +++ b/crates/nu-command/tests/commands/cd.rs @@ -26,6 +26,16 @@ fn filesystem_change_from_current_directory_using_relative_path() { }) } +#[test] +fn filesystem_change_from_current_directory_using_relative_path_with_trailing_slash() { + Playground::setup("cd_test_1_slash", |dirs, _| { + // Intentionally not using correct path sep because this should work on Windows + let actual = nu!( cwd: dirs.root(), "cd cd_test_1_slash/; $env.PWD"); + + assert_eq!(PathBuf::from(actual.out), *dirs.test()); + }) +} + #[test] fn filesystem_change_from_current_directory_using_absolute_path() { Playground::setup("cd_test_2", |dirs, _| { @@ -42,6 +52,23 @@ fn filesystem_change_from_current_directory_using_absolute_path() { }) } +#[test] +fn filesystem_change_from_current_directory_using_absolute_path_with_trailing_slash() { + Playground::setup("cd_test_2", |dirs, _| { + let actual = nu!( + cwd: dirs.test(), + r#" + cd '{}{}' + $env.PWD + "#, + dirs.formats().display(), + std::path::MAIN_SEPARATOR_STR, + ); + + assert_eq!(PathBuf::from(actual.out), dirs.formats()); + }) +} + #[test] fn filesystem_switch_back_to_previous_working_directory() { Playground::setup("cd_test_3", |dirs, sandbox| { diff --git a/crates/nu-path/src/components.rs b/crates/nu-path/src/components.rs index b7f60598c2..9cb74dc373 100644 --- a/crates/nu-path/src/components.rs +++ b/crates/nu-path/src/components.rs @@ -24,15 +24,13 @@ //! `Path::join()`. It works because `PathBuf::push("")` will add a trailing //! slash when the original path doesn't have one. -#[cfg(unix)] -use std::os::unix::ffi::OsStrExt; -#[cfg(windows)] -use std::os::windows::ffi::OsStrExt; use std::{ ffi::OsStr, path::{Component, Path}, }; +use crate::trailing_slash::has_trailing_slash; + /// Like `Path::components()`, but produces an extra empty component at the end /// when `path` contains a trailing slash. /// @@ -63,17 +61,6 @@ pub fn components(path: &Path) -> impl Iterator { })) } -#[cfg(windows)] -fn has_trailing_slash(path: &Path) -> bool { - let last = path.as_os_str().encode_wide().last(); - last == Some(b'\\' as u16) || last == Some(b'/' as u16) -} -#[cfg(unix)] -fn has_trailing_slash(path: &Path) -> bool { - let last = path.as_os_str().as_bytes().last(); - last == Some(&b'/') -} - #[cfg(test)] mod test { //! We'll go through every variant of Component, with or without trailing diff --git a/crates/nu-path/src/lib.rs b/crates/nu-path/src/lib.rs index e4baf36e76..6c064d4b57 100644 --- a/crates/nu-path/src/lib.rs +++ b/crates/nu-path/src/lib.rs @@ -4,8 +4,10 @@ pub mod dots; pub mod expansions; mod helpers; mod tilde; +mod trailing_slash; pub use components::components; pub use expansions::{canonicalize_with, expand_path_with, expand_to_real_path, locate_in_dirs}; pub use helpers::{config_dir, config_dir_old, home_dir}; pub use tilde::expand_tilde; +pub use trailing_slash::{has_trailing_slash, strip_trailing_slash}; diff --git a/crates/nu-path/src/trailing_slash.rs b/crates/nu-path/src/trailing_slash.rs new file mode 100644 index 0000000000..4daf5d45ef --- /dev/null +++ b/crates/nu-path/src/trailing_slash.rs @@ -0,0 +1,108 @@ +use std::{ + borrow::Cow, + path::{Path, PathBuf}, +}; + +/// Strip any trailing slashes from a non-root path. This is required in some contexts, for example +/// for the `PWD` environment variable. +pub fn strip_trailing_slash(path: &Path) -> Cow { + if has_trailing_slash(path) { + // If there are, the safest thing to do is have Rust parse the path for us and build it + // again. This will correctly handle a root directory, but it won't add the trailing slash. + let mut out = PathBuf::with_capacity(path.as_os_str().len()); + out.extend(path.components()); + Cow::Owned(out) + } else { + // The path is safe and doesn't contain any trailing slashes. + Cow::Borrowed(path) + } +} + +/// `true` if the path has a trailing slash, including if it's the root directory. +#[cfg(windows)] +pub fn has_trailing_slash(path: &Path) -> bool { + use std::os::windows::ffi::OsStrExt; + + let last = path.as_os_str().encode_wide().last(); + last == Some(b'\\' as u16) || last == Some(b'/' as u16) +} + +/// `true` if the path has a trailing slash, including if it's the root directory. +#[cfg(unix)] +pub fn has_trailing_slash(path: &Path) -> bool { + use std::os::unix::ffi::OsStrExt; + + let last = path.as_os_str().as_bytes().last(); + last == Some(&b'/') +} + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg_attr(not(unix), ignore = "only for Unix")] + #[test] + fn strip_root_unix() { + assert_eq!(Path::new("/"), strip_trailing_slash(Path::new("/"))); + } + + #[cfg_attr(not(unix), ignore = "only for Unix")] + #[test] + fn strip_non_trailing_unix() { + assert_eq!( + Path::new("/foo/bar"), + strip_trailing_slash(Path::new("/foo/bar")) + ); + } + + #[cfg_attr(not(unix), ignore = "only for Unix")] + #[test] + fn strip_trailing_unix() { + assert_eq!( + Path::new("/foo/bar"), + strip_trailing_slash(Path::new("/foo/bar/")) + ); + } + + #[cfg_attr(not(windows), ignore = "only for Windows")] + #[test] + fn strip_root_windows() { + assert_eq!(Path::new(r"C:\"), strip_trailing_slash(Path::new(r"C:\"))); + } + + #[cfg_attr(not(windows), ignore = "only for Windows")] + #[test] + fn strip_non_trailing_windows() { + assert_eq!( + Path::new(r"C:\foo\bar"), + strip_trailing_slash(Path::new(r"C:\foo\bar")) + ); + } + + #[cfg_attr(not(windows), ignore = "only for Windows")] + #[test] + fn strip_non_trailing_windows_unc() { + assert_eq!( + Path::new(r"\\foo\bar"), + strip_trailing_slash(Path::new(r"\\foo\bar")) + ); + } + + #[cfg_attr(not(windows), ignore = "only for Windows")] + #[test] + fn strip_trailing_windows() { + assert_eq!( + Path::new(r"C:\foo\bar"), + strip_trailing_slash(Path::new(r"C:\foo\bar\")) + ); + } + + #[cfg_attr(not(windows), ignore = "only for Windows")] + #[test] + fn strip_trailing_windows_unc() { + assert_eq!( + Path::new(r"\\foo\bar"), + strip_trailing_slash(Path::new(r"\\foo\bar\")) + ); + } +} From 0d6fbdde4adc927c62549f8f75d15a87044a10b7 Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Sat, 4 May 2024 18:05:54 +0800 Subject: [PATCH 05/15] Fix PWD cannot point to root paths (#12761) PR https://github.com/nushell/nushell/pull/12603 made it so that PWD can never contain a trailing slash. However, a root path (such as `/` or `C:\`) technically counts as "having a trailing slash", so now `cd /` doesn't work. I feel dumb for missing such an obvious edge case. Let's just merge this quickly before anyone else finds out... EDIT: It appears I'm too late. --- crates/nu-protocol/src/engine/engine_state.rs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index cab3dcc48a..5012754b3b 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -923,8 +923,8 @@ impl EngineState { } /// Returns the current working directory, which is guaranteed to be an - /// absolute path without trailing slashes, but might contain symlink - /// components. + /// absolute path without trailing slashes (unless it's the root path), but + /// might contain symlink components. /// /// If `stack` is supplied, also considers modifications to the working /// directory on the stack that have yet to be merged into the engine state. @@ -941,6 +941,11 @@ impl EngineState { }) } + // Helper function to check if a path is a root path. + fn is_root(path: &Path) -> bool { + path.parent().is_none() + } + // Helper function to check if a path has trailing slashes. fn has_trailing_slash(path: &Path) -> bool { nu_path::components(path).last() @@ -958,7 +963,9 @@ impl EngineState { if let Value::String { val, .. } = pwd { let path = PathBuf::from(val); - if has_trailing_slash(&path) { + // Technically, a root path counts as "having trailing slashes", but + // for the purpose of PWD, a root path is acceptable. + if !is_root(&path) && has_trailing_slash(&path) { error("$env.PWD contains trailing slashes") } else if !path.is_absolute() { error("$env.PWD is not an absolute path") @@ -1235,6 +1242,18 @@ mod test_cwd { engine_state.cwd(None).unwrap_err(); } + #[test] + fn pwd_points_to_root() { + #[cfg(windows)] + let root = Path::new(r"C:\"); + #[cfg(not(windows))] + let root = Path::new("/"); + + let engine_state = engine_state_with_pwd(root); + let cwd = engine_state.cwd(None).unwrap(); + assert_path_eq!(cwd, root); + } + #[test] fn pwd_points_to_normal_file() { let file = NamedTempFile::new().unwrap(); From 1e71cd4777eab5421b113cbdda0acfaa336576c6 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sat, 4 May 2024 12:56:16 +0000 Subject: [PATCH 06/15] Bump `base64` to 0.22.1 (#12757) # Description Bumps `base64` to 0.22.1 which fixes the alphabet used for binhex encoding and decoding. This required updating some test expected output. Related to PR #12469 where `base64` was also bumped and ran into the failing tests. # User-Facing Changes Bug fix, but still changes binhex encoding and decoding output. # Tests + Formatting Updated test expected output. --- Cargo.lock | 6 +++--- crates/nu-command/src/strings/encode_decode/base64.rs | 4 ++-- .../nu-command/src/strings/encode_decode/encode_base64.rs | 2 +- crates/nu-command/tests/commands/hash_/mod.rs | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fcf93f136..2151350cc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,9 +346,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -2919,7 +2919,7 @@ name = "nu-command" version = "0.93.1" dependencies = [ "alphanumeric-sort", - "base64 0.22.0", + "base64 0.22.1", "bracoxide", "brotli 5.0.0", "byteorder", diff --git a/crates/nu-command/src/strings/encode_decode/base64.rs b/crates/nu-command/src/strings/encode_decode/base64.rs index 0f91a96466..1c257e1200 100644 --- a/crates/nu-command/src/strings/encode_decode/base64.rs +++ b/crates/nu-command/src/strings/encode_decode/base64.rs @@ -281,7 +281,7 @@ mod tests { #[test] fn base64_decode_binhex() { - let word = Value::test_string("A5\"KC9jRB@IIF'8bF!"); + let word = Value::test_string(r#"B5"LD@jSCAJJG'9cG!"#); let expected = Value::binary(b"a binhex test".as_slice(), Span::test_data()); let actual = action( @@ -304,7 +304,7 @@ mod tests { #[test] fn base64_decode_binhex_with_new_line_input() { - let word = Value::test_string("A5\"KC9jRB\n@IIF'8bF!"); + let word = Value::test_string("B5\"LD@jSC\nAJJG'9cG!"); let expected = Value::binary(b"a binhex test".as_slice(), Span::test_data()); let actual = action( diff --git a/crates/nu-command/src/strings/encode_decode/encode_base64.rs b/crates/nu-command/src/strings/encode_decode/encode_base64.rs index 04e1fcf6d1..090941b76b 100644 --- a/crates/nu-command/src/strings/encode_decode/encode_base64.rs +++ b/crates/nu-command/src/strings/encode_decode/encode_base64.rs @@ -65,7 +65,7 @@ impl Command for EncodeBase64 { Example { description: "Encode a string with the binhex character set", example: "'Some Data' | encode base64 --character-set binhex", - result: Some(Value::test_string(r#"7epXB5"%A@4J"#)), + result: Some(Value::test_string(r#"8fpYC5"%BA4K"#)), }, ] } diff --git a/crates/nu-command/tests/commands/hash_/mod.rs b/crates/nu-command/tests/commands/hash_/mod.rs index 21d4dc0dd6..76ae86f6e7 100644 --- a/crates/nu-command/tests/commands/hash_/mod.rs +++ b/crates/nu-command/tests/commands/hash_/mod.rs @@ -15,7 +15,7 @@ fn base64_encode_characterset_binhex() { echo 'username:password' | encode base64 --character-set binhex "#); - assert_eq!(actual.out, "F@0NEPjJD97kE\'&bEhFZEP3"); + assert_eq!(actual.out, "GA0PFQjKE@8kF'&cFhG[FQ3"); } #[test] @@ -31,9 +31,9 @@ fn error_when_invalid_character_set_given() { #[test] fn base64_decode_characterset_binhex() { - let actual = nu!(r#" - echo "F@0NEPjJD97kE'&bEhFZEP3" | decode base64 --character-set binhex --binary | decode utf-8 - "#); + let actual = nu!( + r#""GA0PFQjKE@8kF'&cFhG[FQ3" | decode base64 --character-set binhex --binary | decode utf-8"# + ); assert_eq!(actual.out, "username:password"); } From 3ae6fe2114ac2d0b8f70a99017a67da104c3c2e2 Mon Sep 17 00:00:00 2001 From: Maxime Jacob Date: Sat, 4 May 2024 09:12:44 -0400 Subject: [PATCH 07/15] Enable columns with spaces for into_sqlite by adding quotes to column names (#12759) # Description Spaces were causing an issue with into_sqlite when they appeared in column names. This is because the column names were not properly wrapped with backticks that allow sqlite to properly interpret the column. The issue has been addressed by adding backticks to the column names of into sqlite. The output of the column names when using open is unchanged, and the column names appear without backticks as expected. fixes #12700 # User-Facing Changes N/A # Tests + Formatting Formatting has been respected. Repro steps from the issue have been done, and ran multiple times. New values get added to the correct columns as expected. --- .../nu-command/src/database/commands/into_sqlite.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/nu-command/src/database/commands/into_sqlite.rs b/crates/nu-command/src/database/commands/into_sqlite.rs index 1b4d0b8073..7f61b6bc06 100644 --- a/crates/nu-command/src/database/commands/into_sqlite.rs +++ b/crates/nu-command/src/database/commands/into_sqlite.rs @@ -269,7 +269,8 @@ fn insert_in_transaction( let insert_statement = format!( "INSERT INTO [{}] ({}) VALUES ({})", table_name, - Itertools::intersperse(val.columns().map(String::as_str), ", ").collect::(), + Itertools::intersperse(val.columns().map(|c| format!("`{}`", c)), ", ".to_string()) + .collect::(), Itertools::intersperse(itertools::repeat_n("?", val.len()), ", ").collect::(), ); @@ -390,8 +391,12 @@ fn get_columns_with_sqlite_types( let mut columns: Vec<(String, &'static str)> = vec![]; for (c, v) in record { - if !columns.iter().any(|(name, _)| name == c) { - columns.push((c.clone(), nu_value_to_sqlite_type(v)?)); + if !columns + .iter() + .map(|name| (format!("`{}`", name.0), name.1)) + .any(|(name, _)| name == *c) + { + columns.push((format!("`{}`", c), nu_value_to_sqlite_type(v)?)); } } From 8eefb7313e23cad630ff86747a258c94bbfa19f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Sat, 4 May 2024 17:00:44 +0200 Subject: [PATCH 08/15] Minimize future false positive typos (#12751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Make typos config more strict: ignore false positives where they occur. 1. Ignore only files with typos 2. Add regexp-s with context 3. Ignore variable names only in Rust code 4. Ignore only 1 "identifier" 5. Check dot files 🎁 Extra bonus: fix typos!! --- .github/workflows/ci.yml | 2 +- crates/nu-command/src/date/utils.rs | 2 +- crates/nu-command/tests/commands/table.rs | 6 ++-- crates/nu-json/src/de.rs | 4 +-- crates/nu-std/CONTRIBUTING.md | 2 +- tests/shell/pipeline/commands/external.rs | 2 +- typos.toml | 34 +++++++++++++++-------- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 619ff1e9ae..5aec3f923a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,7 +168,7 @@ jobs: # Using macOS 13 runner because 14 is based on the M1 and has half as much RAM (7 GB, # instead of 14 GB) which is too little for us right now. # - # Failure occuring with clippy for rust 1.77.2 + # Failure occurring with clippy for rust 1.77.2 platform: [windows-latest, macos-13, ubuntu-20.04] runs-on: ${{ matrix.platform }} diff --git a/crates/nu-command/src/date/utils.rs b/crates/nu-command/src/date/utils.rs index f58b2a517c..4616dc887b 100644 --- a/crates/nu-command/src/date/utils.rs +++ b/crates/nu-command/src/date/utils.rs @@ -8,7 +8,7 @@ pub(crate) fn parse_date_from_string( match dtparse::parse(input) { Ok((native_dt, fixed_offset)) => { let offset = match fixed_offset { - Some(fo) => fo, + Some(offset) => offset, None => *(Local::now().offset()), }; match offset.from_local_datetime(&native_dt) { diff --git a/crates/nu-command/tests/commands/table.rs b/crates/nu-command/tests/commands/table.rs index afc9b613d4..a986c7b15b 100644 --- a/crates/nu-command/tests/commands/table.rs +++ b/crates/nu-command/tests/commands/table.rs @@ -2562,12 +2562,12 @@ fn create_theme_output(theme: &str) -> Vec { } fn theme_cmd(theme: &str, footer: bool, then: &str) -> String { - let mut with_foorter = String::new(); + let mut with_footer = String::new(); if footer { - with_foorter = "$env.config.footer_mode = \"always\"".to_string(); + with_footer = "$env.config.footer_mode = \"always\"".to_string(); } - format!("$env.config.table.mode = {theme}; $env.config.table.header_on_separator = true; {with_foorter}; {then}") + format!("$env.config.table.mode = {theme}; $env.config.table.header_on_separator = true; {with_footer}; {then}") } #[test] diff --git a/crates/nu-json/src/de.rs b/crates/nu-json/src/de.rs index 6fcfbbf7d7..fff4da0d6f 100644 --- a/crates/nu-json/src/de.rs +++ b/crates/nu-json/src/de.rs @@ -260,8 +260,8 @@ where } _ => { if chf == b'-' || chf.is_ascii_digit() { - let mut pn = ParseNumber::new(self.str_buf.iter().copied()); - match pn.parse(false) { + let mut parser = ParseNumber::new(self.str_buf.iter().copied()); + match parser.parse(false) { Ok(Number::F64(v)) => { self.rdr.uneat_char(ch); return visitor.visit_f64(v); diff --git a/crates/nu-std/CONTRIBUTING.md b/crates/nu-std/CONTRIBUTING.md index 9108956a76..1677a31de1 100644 --- a/crates/nu-std/CONTRIBUTING.md +++ b/crates/nu-std/CONTRIBUTING.md @@ -13,7 +13,7 @@ You'll generally find the team members on [Discord `#standard-library` channel][discord#standard-library] and can have preliminary discussions there to clarify the issues involved. -You can open a [Github issue][new-issue] to have a more focused discussion of +You can open a [GitHub issue][new-issue] to have a more focused discussion of your idea. Generally, we think the standard library should contain items that are relevant diff --git a/tests/shell/pipeline/commands/external.rs b/tests/shell/pipeline/commands/external.rs index 8d8bf137cc..88d443e4fd 100644 --- a/tests/shell/pipeline/commands/external.rs +++ b/tests/shell/pipeline/commands/external.rs @@ -286,7 +286,7 @@ mod stdin_evaluation { fn does_not_panic_with_no_newline_in_stream() { let actual = nu!(pipeline( r#" - nu --testbin nonu "wheres the nuline?" | length + nu --testbin nonu "where's the nuline?" | length "# )); diff --git a/typos.toml b/typos.toml index a8c81542e9..92fecd5cb6 100644 --- a/typos.toml +++ b/typos.toml @@ -1,17 +1,27 @@ [files] -extend-exclude = ["crates/nu-command/tests/commands/table.rs", "*.tsv", "*.json", "*.txt", "tests/fixtures/formats/*"] +extend-exclude = [ + ".git/", + "crates/nu-cmd-extra/assets/228_themes.json", + "tests/fixtures/formats/", +] +ignore-hidden = false -[default.extend-words] -# Ignore false-positives +[default] +extend-ignore-re = [ + "Plasticos Rival", + "│ in_custom_valu │", + "│ ine │", + ":es\\|ful\\(", + "\\\\u\\{e7ba\\}", + "([0-9a-f][0-9a-f] ){4}", + "--find ba\\b", + "0x\\[ba be\\]", + "\\)BaR'", +] + +[type.rust.extend-words] nd = "nd" -pn = "pn" -fo = "fo" -ful = "ful" -ons = "ons" -ba = "ba" -Plasticos = "Plasticos" -IIF = "IIF" numer = "numer" + +[default.extend-identifiers] ratatui = "ratatui" -doas = "doas" -wheres = "wheres" From 349d02ced017aaf11104077dd1b6e7cfd9e17878 Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Sat, 4 May 2024 17:16:40 +0200 Subject: [PATCH 09/15] Pin `base64` to the fixed patch version (#12762) Followup to #12757 Always ensure that the `Cargo.toml` specifies the full minimum version required to have the correct behavior or used features. Otherwise a missing semver specifier is equal to `0` and could downgrade. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7fbc95a239..9cf4fcf947 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ members = [ alphanumeric-sort = "1.5" ansi-str = "0.8" anyhow = "1.0.82" -base64 = "0.22" +base64 = "0.22.1" bracoxide = "0.1.2" brotli = "5.0" byteorder = "1.5" From 0bfbe8c372f80dabe064039843810cd8c818642a Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Sat, 4 May 2024 20:16:20 +0200 Subject: [PATCH 10/15] Specify the required minimum `chrono` version (#12766) See #12765 and h/t to @FMOtalleb in https://discord.com/channels/601130461678272522/855947301380947968/1236286905843454032 `Duration/TimeDelta::try_milliseconds` was added in `0.4.34` https://github.com/chronotope/chrono/releases/tag/v0.4.34 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9cf4fcf947..ce259b06e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ byteorder = "1.5" bytesize = "1.3" calamine = "0.24.0" chardetng = "0.1.17" -chrono = { default-features = false, version = "0.4" } +chrono = { default-features = false, version = "0.4.34" } chrono-humanize = "0.2.3" chrono-tz = "0.8" crossbeam-channel = "0.5.8" From 9181fca8592720253f2b48de92a92423b0b7dba4 Mon Sep 17 00:00:00 2001 From: Stefan Holderbach Date: Sun, 5 May 2024 00:51:08 +0200 Subject: [PATCH 11/15] Update `interprocess` to 2.0.1 (#12769) Fixes #12755 See https://github.com/kotauskas/interprocess/issues/63 and https://github.com/kotauskas/interprocess/pull/62 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2151350cc6..83a5b41b60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2013,9 +2013,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d5f0e3c218e7a86a6712fd3adc84672304f9e839402b866685b9117a077c37f" +checksum = "7c7fb8583fab9503654385e2bafda123376445a77027a1b106dd7e44cf51122f" dependencies = [ "libc", "recvmsg", diff --git a/Cargo.toml b/Cargo.toml index ce259b06e1..11f393a5ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ heck = "0.5.0" human-date-parser = "0.1.1" indexmap = "2.2" indicatif = "0.17" -interprocess = "2.0.0" +interprocess = "2.0.1" is_executable = "1.0" itertools = "0.12" libc = "0.2" From 2f8e397365503ba3c2c56cd3ef4dc5ae1bd4be5e Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sun, 5 May 2024 08:43:20 +0000 Subject: [PATCH 12/15] Refactor flattening to reduce intermediate allocations (#12756) # Description Our current flattening code creates a bunch of intermediate `Vec`s for each function call. These intermediate `Vec`s are then usually appended to the current `output` `Vec`. By instead passing a mutable reference of the `output` `Vec` to each flattening function, this `Vec` can be reused/appended to directly thereby eliminating the need for intermediate `Vec`s in most cases. --- crates/nu-parser/src/flatten.rs | 459 +++++++++++++------------------- 1 file changed, 192 insertions(+), 267 deletions(-) diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index cc31dda23a..3484c53d0f 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -98,44 +98,98 @@ impl Display for FlatShape { } } -pub fn flatten_block(working_set: &StateWorkingSet, block: &Block) -> Vec<(Span, FlatShape)> { - let mut output = vec![]; +/* +The `_into` functions below (e.g., `flatten_block_into`) take an existing `output` `Vec` +and append more data to it. This is to reduce the number of intermediate `Vec`s. +The non-`into` functions (e.g., `flatten_block`) are part of the crate's public API +and return a new `Vec` instead of modifying an existing one. +*/ +fn flatten_block_into( + working_set: &StateWorkingSet, + block: &Block, + output: &mut Vec<(Span, FlatShape)>, +) { for pipeline in &block.pipelines { - output.extend(flatten_pipeline(working_set, pipeline)); + flatten_pipeline_into(working_set, pipeline, output); } - output } -pub fn flatten_expression( +fn flatten_pipeline_into( + working_set: &StateWorkingSet, + pipeline: &Pipeline, + output: &mut Vec<(Span, FlatShape)>, +) { + for expr in &pipeline.elements { + flatten_pipeline_element_into(working_set, expr, output) + } +} + +fn flatten_pipeline_element_into( + working_set: &StateWorkingSet, + pipeline_element: &PipelineElement, + output: &mut Vec<(Span, FlatShape)>, +) { + if let Some(span) = pipeline_element.pipe { + output.push((span, FlatShape::Pipe)); + } + + flatten_expression_into(working_set, &pipeline_element.expr, output); + + if let Some(redirection) = pipeline_element.redirection.as_ref() { + match redirection { + PipelineRedirection::Single { target, .. } => { + output.push((target.span(), FlatShape::Redirection)); + if let Some(expr) = target.expr() { + flatten_expression_into(working_set, expr, output); + } + } + PipelineRedirection::Separate { out, err } => { + let (out, err) = if out.span() <= err.span() { + (out, err) + } else { + (err, out) + }; + + output.push((out.span(), FlatShape::Redirection)); + if let Some(expr) = out.expr() { + flatten_expression_into(working_set, expr, output); + } + output.push((err.span(), FlatShape::Redirection)); + if let Some(expr) = err.expr() { + flatten_expression_into(working_set, expr, output); + } + } + } + } +} + +fn flatten_expression_into( working_set: &StateWorkingSet, expr: &Expression, -) -> Vec<(Span, FlatShape)> { + output: &mut Vec<(Span, FlatShape)>, +) { if let Some(custom_completion) = &expr.custom_completion { - return vec![(expr.span, FlatShape::Custom(*custom_completion))]; + output.push((expr.span, FlatShape::Custom(*custom_completion))); + return; } match &expr.expr { Expr::BinaryOp(lhs, op, rhs) => { - let mut output = vec![]; - output.extend(flatten_expression(working_set, lhs)); - output.extend(flatten_expression(working_set, op)); - output.extend(flatten_expression(working_set, rhs)); - output + flatten_expression_into(working_set, lhs, output); + flatten_expression_into(working_set, op, output); + flatten_expression_into(working_set, rhs, output); } - Expr::UnaryNot(inner_expr) => { - let mut output = vec![( + Expr::UnaryNot(expr) => { + output.push(( Span::new(expr.span.start, expr.span.start + 3), FlatShape::Operator, - )]; - output.extend(flatten_expression(working_set, inner_expr)); - output + )); + flatten_expression_into(working_set, expr, output); } Expr::Closure(block_id) => { let outer_span = expr.span; - let mut output = vec![]; - let block = working_set.get_block(*block_id); let flattened = flatten_block(working_set, block); @@ -160,16 +214,12 @@ pub fn flatten_expression( output.extend(flattened); if let Some(last) = last { - output.push(last) + output.push(last); } - - output } Expr::Block(block_id) | Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => { let outer_span = expr.span; - let mut output = vec![]; - let flattened = flatten_block(working_set, working_set.get_block(*block_id)); if let Some(first) = flattened.first() { @@ -190,150 +240,99 @@ pub fn flatten_expression( output.extend(flattened); if let Some(last) = last { - output.push(last) + output.push(last); } - - output } Expr::Call(call) => { - let mut output = vec![]; - if call.head.end != 0 { // Make sure we don't push synthetic calls output.push((call.head, FlatShape::InternalCall(call.decl_id))); } - let mut args = vec![]; + let arg_start = output.len(); for arg in &call.arguments { match arg { Argument::Positional(positional) | Argument::Unknown(positional) => { - let flattened = flatten_expression(working_set, positional); - args.extend(flattened); + flatten_expression_into(working_set, positional, output) } Argument::Named(named) => { if named.0.span.end != 0 { // Ignore synthetic flags - args.push((named.0.span, FlatShape::Flag)); + output.push((named.0.span, FlatShape::Flag)); } if let Some(expr) = &named.2 { - args.extend(flatten_expression(working_set, expr)); + flatten_expression_into(working_set, expr, output); } } Argument::Spread(expr) => { - args.push(( + output.push(( Span::new(expr.span.start - 3, expr.span.start), FlatShape::Operator, )); - args.extend(flatten_expression(working_set, expr)); + flatten_expression_into(working_set, expr, output); } } } // sort these since flags and positional args can be intermixed - args.sort(); - - output.extend(args); - output + output[arg_start..].sort(); } Expr::ExternalCall(head, args) => { - let mut output = vec![]; - - match **head { - Expression { - expr: Expr::String(..), - span, - .. - } => { - output.push((span, FlatShape::External)); - } - _ => { - output.extend(flatten_expression(working_set, head)); - } + if let Expr::String(..) = &head.expr { + output.push((head.span, FlatShape::External)); + } else { + flatten_expression_into(working_set, head, output); } for arg in args.as_ref() { - //output.push((*arg, FlatShape::ExternalArg)); match arg { - ExternalArgument::Regular(expr) => match expr { - Expression { - expr: Expr::String(..), - span, - .. - } => { - output.push((*span, FlatShape::ExternalArg)); + ExternalArgument::Regular(expr) => { + if let Expr::String(..) = &expr.expr { + output.push((expr.span, FlatShape::ExternalArg)); + } else { + flatten_expression_into(working_set, expr, output); } - _ => { - output.extend(flatten_expression(working_set, expr)); - } - }, + } ExternalArgument::Spread(expr) => { output.push(( Span::new(expr.span.start - 3, expr.span.start), FlatShape::Operator, )); - output.extend(flatten_expression(working_set, expr)); + flatten_expression_into(working_set, expr, output); } } } - - output - } - Expr::Garbage => { - vec![(expr.span, FlatShape::Garbage)] - } - Expr::Nothing => { - vec![(expr.span, FlatShape::Nothing)] - } - Expr::DateTime(_) => { - vec![(expr.span, FlatShape::DateTime)] - } - Expr::Binary(_) => { - vec![(expr.span, FlatShape::Binary)] - } - Expr::Int(_) => { - vec![(expr.span, FlatShape::Int)] - } - Expr::Float(_) => { - vec![(expr.span, FlatShape::Float)] } + Expr::Garbage => output.push((expr.span, FlatShape::Garbage)), + Expr::Nothing => output.push((expr.span, FlatShape::Nothing)), + Expr::DateTime(_) => output.push((expr.span, FlatShape::DateTime)), + Expr::Binary(_) => output.push((expr.span, FlatShape::Binary)), + Expr::Int(_) => output.push((expr.span, FlatShape::Int)), + Expr::Float(_) => output.push((expr.span, FlatShape::Float)), Expr::MatchBlock(matches) => { - let mut output = vec![]; - - for match_ in matches { - output.extend(flatten_pattern(&match_.0)); - output.extend(flatten_expression(working_set, &match_.1)); + for (pattern, expr) in matches { + flatten_pattern_into(pattern, output); + flatten_expression_into(working_set, expr, output); } - - output } Expr::ValueWithUnit(value) => { - let mut output = flatten_expression(working_set, &value.expr); + flatten_expression_into(working_set, &value.expr, output); output.push((value.unit.span, FlatShape::String)); - - output } Expr::CellPath(cell_path) => { - let mut output = vec![]; - for path_element in &cell_path.members { - match path_element { - PathMember::String { span, .. } => output.push((*span, FlatShape::String)), - PathMember::Int { span, .. } => output.push((*span, FlatShape::Int)), - } - } - output + output.extend(cell_path.members.iter().map(|member| match *member { + PathMember::String { span, .. } => (span, FlatShape::String), + PathMember::Int { span, .. } => (span, FlatShape::Int), + })); } Expr::FullCellPath(cell_path) => { - let mut output = vec![]; - output.extend(flatten_expression(working_set, &cell_path.head)); - for path_element in &cell_path.tail { - match path_element { - PathMember::String { span, .. } => output.push((*span, FlatShape::String)), - PathMember::Int { span, .. } => output.push((*span, FlatShape::Int)), - } - } - output + flatten_expression_into(working_set, &cell_path.head, output); + output.extend(cell_path.tail.iter().map(|member| match *member { + PathMember::String { span, .. } => (span, FlatShape::String), + PathMember::Int { span, .. } => (span, FlatShape::Int), + })); } Expr::ImportPattern(import_pattern) => { - let mut output = vec![(import_pattern.head.span, FlatShape::String)]; + output.push((import_pattern.head.span, FlatShape::String)); for member in &import_pattern.members { match member { @@ -342,50 +341,33 @@ pub fn flatten_expression( output.push((*span, FlatShape::String)) } ImportPatternMember::List { names } => { - for (_, span) in names { - output.push((*span, FlatShape::String)); - } + output.extend(names.iter().map(|&(_, span)| (span, FlatShape::String))) } } } - - output - } - Expr::Overlay(_) => { - vec![(expr.span, FlatShape::String)] } + Expr::Overlay(_) => output.push((expr.span, FlatShape::String)), Expr::Range(range) => { - let mut output = vec![]; if let Some(f) = &range.from { - output.extend(flatten_expression(working_set, f)); + flatten_expression_into(working_set, f, output); } if let Some(s) = &range.next { - output.extend(vec![(range.operator.next_op_span, FlatShape::Operator)]); - output.extend(flatten_expression(working_set, s)); + output.push((range.operator.next_op_span, FlatShape::Operator)); + flatten_expression_into(working_set, s, output); } - output.extend(vec![(range.operator.span, FlatShape::Operator)]); + output.push((range.operator.span, FlatShape::Operator)); if let Some(t) = &range.to { - output.extend(flatten_expression(working_set, t)); + flatten_expression_into(working_set, t, output); } - output - } - Expr::Bool(_) => { - vec![(expr.span, FlatShape::Bool)] - } - Expr::Filepath(_, _) => { - vec![(expr.span, FlatShape::Filepath)] - } - Expr::Directory(_, _) => { - vec![(expr.span, FlatShape::Directory)] - } - Expr::GlobPattern(_, _) => { - vec![(expr.span, FlatShape::GlobPattern)] } + Expr::Bool(_) => output.push((expr.span, FlatShape::Bool)), + Expr::Filepath(_, _) => output.push((expr.span, FlatShape::Filepath)), + Expr::Directory(_, _) => output.push((expr.span, FlatShape::Directory)), + Expr::GlobPattern(_, _) => output.push((expr.span, FlatShape::GlobPattern)), Expr::List(list) => { let outer_span = expr.span; let mut last_end = outer_span.start; - let mut output = vec![]; for item in list { match item { ListItem::Item(expr) => { @@ -404,11 +386,11 @@ pub fn flatten_expression( output.extend(flattened); } ListItem::Spread(_, expr) => { - let mut output = vec![( + output.push(( Span::new(expr.span.start, expr.span.start + 3), FlatShape::Operator, - )]; - output.extend(flatten_expression(working_set, expr)); + )); + flatten_expression_into(working_set, expr, output); } } } @@ -416,37 +398,32 @@ pub fn flatten_expression( if last_end < outer_span.end { output.push((Span::new(last_end, outer_span.end), FlatShape::List)); } - output } Expr::StringInterpolation(exprs) => { - let mut output = vec![]; + let mut flattened = vec![]; for expr in exprs { - output.extend(flatten_expression(working_set, expr)); + flatten_expression_into(working_set, expr, &mut flattened); } - if let Some(first) = output.first() { + if let Some(first) = flattened.first() { if first.0.start != expr.span.start { // If we aren't a bare word interpolation, also highlight the outer quotes - output.insert( - 0, - ( - Span::new(expr.span.start, expr.span.start + 2), - FlatShape::StringInterpolation, - ), - ); output.push(( + Span::new(expr.span.start, expr.span.start + 2), + FlatShape::StringInterpolation, + )); + flattened.push(( Span::new(expr.span.end - 1, expr.span.end), FlatShape::StringInterpolation, )); } } - output + output.extend(flattened); } Expr::Record(list) => { let outer_span = expr.span; let mut last_end = outer_span.start; - let mut output = vec![]; for l in list { match l { RecordItem::Pair(key, val) => { @@ -483,50 +460,38 @@ pub fn flatten_expression( output.push((*op_span, FlatShape::Operator)); last_end = op_span.end; - let flattened_inner = flatten_expression(working_set, record); - if let Some(first) = flattened_inner.first() { + let flattened = flatten_expression(working_set, record); + if let Some(first) = flattened.first() { if first.0.start > last_end { output .push((Span::new(last_end, first.0.start), FlatShape::Record)); } } - if let Some(last) = flattened_inner.last() { + if let Some(last) = flattened.last() { last_end = last.0.end; } - output.extend(flattened_inner); + output.extend(flattened); } } } if last_end < outer_span.end { output.push((Span::new(last_end, outer_span.end), FlatShape::Record)); } - - output } Expr::Keyword(kw) => { - let mut output = vec![(kw.span, FlatShape::Keyword)]; - output.extend(flatten_expression(working_set, &kw.expr)); - output - } - Expr::Operator(_) => { - vec![(expr.span, FlatShape::Operator)] - } - Expr::Signature(_) => { - vec![(expr.span, FlatShape::Signature)] - } - Expr::String(_) => { - vec![(expr.span, FlatShape::String)] - } - Expr::RawString(_) => { - vec![(expr.span, FlatShape::RawString)] + output.push((kw.span, FlatShape::Keyword)); + flatten_expression_into(working_set, &kw.expr, output); } + Expr::Operator(_) => output.push((expr.span, FlatShape::Operator)), + Expr::Signature(_) => output.push((expr.span, FlatShape::Signature)), + Expr::String(_) => output.push((expr.span, FlatShape::String)), + Expr::RawString(_) => output.push((expr.span, FlatShape::RawString)), Expr::Table(table) => { let outer_span = expr.span; let mut last_end = outer_span.start; - let mut output = vec![]; - for e in table.columns.as_ref() { - let flattened = flatten_expression(working_set, e); + for col in table.columns.as_ref() { + let flattened = flatten_expression(working_set, col); if let Some(first) = flattened.first() { if first.0.start > last_end { output.push((Span::new(last_end, first.0.start), FlatShape::Table)); @@ -559,83 +524,17 @@ pub fn flatten_expression( if last_end < outer_span.end { output.push((Span::new(last_end, outer_span.end), FlatShape::Table)); } - - output - } - Expr::Var(var_id) => { - vec![(expr.span, FlatShape::Variable(*var_id))] - } - Expr::VarDecl(var_id) => { - vec![(expr.span, FlatShape::VarDecl(*var_id))] } + Expr::Var(var_id) => output.push((expr.span, FlatShape::Variable(*var_id))), + Expr::VarDecl(var_id) => output.push((expr.span, FlatShape::VarDecl(*var_id))), } } -pub fn flatten_pipeline_element( - working_set: &StateWorkingSet, - pipeline_element: &PipelineElement, -) -> Vec<(Span, FlatShape)> { - let mut output = if let Some(span) = pipeline_element.pipe { - let mut output = vec![(span, FlatShape::Pipe)]; - output.extend(flatten_expression(working_set, &pipeline_element.expr)); - output - } else { - flatten_expression(working_set, &pipeline_element.expr) - }; - - if let Some(redirection) = pipeline_element.redirection.as_ref() { - match redirection { - PipelineRedirection::Single { target, .. } => { - output.push((target.span(), FlatShape::Redirection)); - if let Some(expr) = target.expr() { - output.extend(flatten_expression(working_set, expr)); - } - } - PipelineRedirection::Separate { out, err } => { - let (out, err) = if out.span() <= err.span() { - (out, err) - } else { - (err, out) - }; - - output.push((out.span(), FlatShape::Redirection)); - if let Some(expr) = out.expr() { - output.extend(flatten_expression(working_set, expr)); - } - output.push((err.span(), FlatShape::Redirection)); - if let Some(expr) = err.expr() { - output.extend(flatten_expression(working_set, expr)); - } - } - } - } - - output -} - -pub fn flatten_pipeline( - working_set: &StateWorkingSet, - pipeline: &Pipeline, -) -> Vec<(Span, FlatShape)> { - let mut output = vec![]; - for expr in &pipeline.elements { - output.extend(flatten_pipeline_element(working_set, expr)) - } - output -} - -pub fn flatten_pattern(match_pattern: &MatchPattern) -> Vec<(Span, FlatShape)> { - let mut output = vec![]; +fn flatten_pattern_into(match_pattern: &MatchPattern, output: &mut Vec<(Span, FlatShape)>) { match &match_pattern.pattern { - Pattern::Garbage => { - output.push((match_pattern.span, FlatShape::Garbage)); - } - Pattern::IgnoreValue => { - output.push((match_pattern.span, FlatShape::Nothing)); - } - Pattern::IgnoreRest => { - output.push((match_pattern.span, FlatShape::Nothing)); - } + Pattern::Garbage => output.push((match_pattern.span, FlatShape::Garbage)), + Pattern::IgnoreValue => output.push((match_pattern.span, FlatShape::Nothing)), + Pattern::IgnoreRest => output.push((match_pattern.span, FlatShape::Nothing)), Pattern::List(items) => { if let Some(first) = items.first() { if let Some(last) = items.last() { @@ -644,7 +543,7 @@ pub fn flatten_pattern(match_pattern: &MatchPattern) -> Vec<(Span, FlatShape)> { FlatShape::MatchPattern, )); for item in items { - output.extend(flatten_pattern(item)); + flatten_pattern_into(item, output); } output.push(( Span::new(last.span.end, match_pattern.span.end), @@ -662,8 +561,8 @@ pub fn flatten_pattern(match_pattern: &MatchPattern) -> Vec<(Span, FlatShape)> { Span::new(match_pattern.span.start, first.1.span.start), FlatShape::MatchPattern, )); - for item in items { - output.extend(flatten_pattern(&item.1)); + for (_, pattern) in items { + flatten_pattern_into(pattern, output); } output.push(( Span::new(last.1.span.end, match_pattern.span.end), @@ -674,20 +573,46 @@ pub fn flatten_pattern(match_pattern: &MatchPattern) -> Vec<(Span, FlatShape)> { output.push((match_pattern.span, FlatShape::MatchPattern)); } } - Pattern::Value(_) => { - output.push((match_pattern.span, FlatShape::MatchPattern)); - } - Pattern::Variable(var_id) => { - output.push((match_pattern.span, FlatShape::VarDecl(*var_id))); - } - Pattern::Rest(var_id) => { - output.push((match_pattern.span, FlatShape::VarDecl(*var_id))); - } + Pattern::Value(_) => output.push((match_pattern.span, FlatShape::MatchPattern)), + Pattern::Variable(var_id) => output.push((match_pattern.span, FlatShape::VarDecl(*var_id))), + Pattern::Rest(var_id) => output.push((match_pattern.span, FlatShape::VarDecl(*var_id))), Pattern::Or(patterns) => { for pattern in patterns { - output.extend(flatten_pattern(pattern)); + flatten_pattern_into(pattern, output); } } } +} + +pub fn flatten_block(working_set: &StateWorkingSet, block: &Block) -> Vec<(Span, FlatShape)> { + let mut output = Vec::new(); + flatten_block_into(working_set, block, &mut output); + output +} + +pub fn flatten_pipeline( + working_set: &StateWorkingSet, + pipeline: &Pipeline, +) -> Vec<(Span, FlatShape)> { + let mut output = Vec::new(); + flatten_pipeline_into(working_set, pipeline, &mut output); + output +} + +pub fn flatten_pipeline_element( + working_set: &StateWorkingSet, + pipeline_element: &PipelineElement, +) -> Vec<(Span, FlatShape)> { + let mut output = Vec::new(); + flatten_pipeline_element_into(working_set, pipeline_element, &mut output); + output +} + +pub fn flatten_expression( + working_set: &StateWorkingSet, + expr: &Expression, +) -> Vec<(Span, FlatShape)> { + let mut output = Vec::new(); + flatten_expression_into(working_set, expr, &mut output); output } From ce3bc470ba1efc53db04ebeb162171a49dac7ab5 Mon Sep 17 00:00:00 2001 From: Antoine Stevan <44101798+amtoine@users.noreply.github.com> Date: Sun, 5 May 2024 15:34:22 +0200 Subject: [PATCH 13/15] improve NUON documentation (#12717) # Description this PR - moves the documentation from `lib.rs` to `README.md` while still including it in the lib file, so that both the [crates.io page](https://crates.io/crates/nuon) and the [documentation](https://docs.rs/nuon/latest/nuon/) show the top-level doc - mention that comments are allowed in NUON - add a JSON-NUON example - put back the formatting of NOTE blocks in the doc # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nuon/README.md | 35 +++++++++++++++++++++++++++++++++++ crates/nuon/src/from.rs | 4 +++- crates/nuon/src/lib.rs | 7 +------ crates/nuon/src/to.rs | 4 +++- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 crates/nuon/README.md diff --git a/crates/nuon/README.md b/crates/nuon/README.md new file mode 100644 index 0000000000..d11aa8104c --- /dev/null +++ b/crates/nuon/README.md @@ -0,0 +1,35 @@ +Support for the NUON format. + +The NUON format is a superset of JSON designed to fit the feel of Nushell. +Some of its extra features are +- trailing commas are allowed +- commas are optional in lists +- quotes are not required around keys or any _bare_ string that do not contain spaces +- comments are allowed, though not preserved when using [`from_nuon`] + +## Example +below is some data in the JSON format +```json +{ + "name": "Some One", + "birth": "1970-01-01", + "stats": [ + 2544729499973429198, + 687051042647753531, + 6702443901704799912 + ] +} +``` + +and an equivalent piece of data written in NUON +```nuon +{ + name: "Some One", # the name of the person + birth: "1970-01-01", # their date of birth + stats: [ # some dummy "stats" about them + 2544729499973429198, + 687051042647753531, + 6702443901704799912, # note the trailing comma here... + ], # and here +} # wait, are these comments in a JSON-like document?!?! +``` diff --git a/crates/nuon/src/from.rs b/crates/nuon/src/from.rs index 457b12d5f9..862b756db7 100644 --- a/crates/nuon/src/from.rs +++ b/crates/nuon/src/from.rs @@ -7,7 +7,9 @@ use std::sync::Arc; /// convert a raw string representation of NUON data to an actual Nushell [`Value`] /// -/// > **Note** +// WARNING: please leave the following two trailing spaces, they matter for the documentation +// formatting +/// > **Note** /// > [`Span`] can be passed to [`from_nuon`] if there is context available to the caller, e.g. when /// > using this function in a command implementation such as /// [`from nuon`](https://www.nushell.sh/commands/docs/from_nuon.html). diff --git a/crates/nuon/src/lib.rs b/crates/nuon/src/lib.rs index cb86480580..891ccae62a 100644 --- a/crates/nuon/src/lib.rs +++ b/crates/nuon/src/lib.rs @@ -1,9 +1,4 @@ -//! Support for the NUON format. -//! -//! The NUON format is a superset of JSON designed to fit the feel of Nushell. -//! Some of its extra features are -//! - trailing commas are allowed -//! - quotes are not required around keys +#![doc = include_str!("../README.md")] mod from; mod to; diff --git a/crates/nuon/src/to.rs b/crates/nuon/src/to.rs index 30fe2664a2..8aeb47a097 100644 --- a/crates/nuon/src/to.rs +++ b/crates/nuon/src/to.rs @@ -39,7 +39,9 @@ pub enum ToStyle { /// convert an actual Nushell [`Value`] to a raw string representation of the NUON data /// -/// > **Note** +// WARNING: please leave the following two trailing spaces, they matter for the documentation +// formatting +/// > **Note** /// > a [`Span`] can be passed to [`to_nuon`] if there is context available to the caller, e.g. when /// > using this function in a command implementation such as [`to nuon`](https://www.nushell.sh/commands/docs/to_nuon.html). /// From 3143ded374668fc6f404fc81044c680c06cb823d Mon Sep 17 00:00:00 2001 From: Filip Andersson <17986183+FilipAndersson245@users.noreply.github.com> Date: Sun, 5 May 2024 17:53:48 +0200 Subject: [PATCH 14/15] Tango migration (#12469) # Description This PR migrates the benchmark suit to Tango. Its different compared to other framework because it require 2 binaries, to run to do A/B benchmarking, this is currently limited to Linux, Max, (Windows require rustc nightly flag), by switching between two suits it can reduce noise and run the code "almost" concurrently. I have have been in contact with the maintainer, and bases this on the dev branch, as it had a newer API simular to criterion. This framework compared to Divan also have a simple file dump system if we want to generate graphs, do other analysis on later. I think overall this crate is very nice, a lot faster to compile and run then criterion, that's for sure. --- Cargo.lock | 769 ++++++++++++++++++++++++---------------- Cargo.toml | 2 +- benches/benchmarks.rs | 792 +++++++++++++++++++++++------------------- scripts/build.rs | 7 +- toolkit.nu | 25 ++ 5 files changed, 920 insertions(+), 675 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83a5b41b60..29647b87ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,10 +72,19 @@ dependencies = [ ] [[package]] -name = "allocator-api2" -version = "0.2.16" +name = "alloca" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alphanumeric-sort" @@ -119,47 +128,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -173,17 +183,16 @@ checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arboard" -version = "3.3.2" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" +checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89" dependencies = [ "clipboard-win", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", - "thiserror", "wl-clipboard-rs", "x11rb", ] @@ -259,18 +268,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -376,7 +385,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -421,12 +430,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - [[package]] name = "block-buffer" version = "0.10.4" @@ -437,10 +440,19 @@ dependencies = [ ] [[package]] -name = "borsh" -version = "1.4.0" +name = "block2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0901fc8eb0aca4c83be0106d6f2db17d86a08dfc2c25f0e84464bf381158add6" +checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" +dependencies = [ + "objc2", +] + +[[package]] +name = "borsh" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe5b10e214954177fb1dc9fbd20a1a2608fe99e6c832033bdc7cea287a20d77" dependencies = [ "borsh-derive", "cfg_aliases", @@ -448,15 +460,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51670c3aa053938b0ee3bd67c3817e471e626151131b934038e83c5bf8de48f5" +checksum = "d7a8646f94ab393e43e8b35a2558b1624bed28b97ee09c5d15456e3c9463f46d" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "syn_derive", ] @@ -560,9 +572,9 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" @@ -581,7 +593,7 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -636,12 +648,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.92" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -688,9 +701,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -699,7 +712,7 @@ dependencies = [ "pure-rust-locales", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -761,7 +774,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "stacker", ] @@ -783,6 +796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -798,6 +812,18 @@ dependencies = [ "terminal_size", ] +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "clap_lex" version = "0.7.0" @@ -806,9 +832,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "clipboard-win" -version = "5.3.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d517d4b86184dbb111d3556a10f1c8a04da7428d2987bf1081602bf11c3aa9ee" +checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" dependencies = [ "error-code", ] @@ -824,9 +850,18 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "colorz" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc2a5df6ee18d52a36920c93a7736761c6fcffa72b9d960fd9133dd8d57c5184" +dependencies = [ + "supports-color 2.1.0", +] [[package]] name = "comfy-table" @@ -853,12 +888,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "condtype" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" - [[package]] name = "console" version = "0.15.8" @@ -1066,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1117,7 +1146,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1186,31 +1215,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "divan" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d567df2c9c2870a43f3f2bd65aaeb18dbce1c18f217c3e564b4fbaeb3ee56c" -dependencies = [ - "cfg-if", - "clap", - "condtype", - "divan-macros", - "libc", - "regex-lite", -] - -[[package]] -name = "divan-macros" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27540baf49be0d484d8f0130d7d8da3011c32a44d4fc873368154f1510e574a2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.58", -] - [[package]] name = "dlib" version = "0.5.2" @@ -1288,9 +1292,9 @@ checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "eml-parser" @@ -1310,9 +1314,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1326,7 +1330,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1407,9 +1411,9 @@ checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fd-lock" @@ -1448,7 +1452,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "windows-sys 0.52.0", ] @@ -1460,9 +1464,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -1600,7 +1604,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1717,6 +1721,23 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "glob-match" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985c9503b412198aa4197559e9a318524ebc4519c229bfa05a535828c950b9d" + +[[package]] +name = "goblin" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27c1b4369c2cd341b5de549380158b105a04c331be5db9110eef7b6d2742134" +dependencies = [ + "log", + "plain", + "scroll", +] + [[package]] name = "h2" version = "0.3.26" @@ -1742,7 +1763,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -1766,9 +1787,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -1781,7 +1802,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1959,7 +1980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -2038,6 +2059,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "is-wsl" version = "0.4.0" @@ -2069,6 +2101,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.11.0" @@ -2101,9 +2139,9 @@ checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -2232,9 +2270,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libflate" @@ -2277,7 +2315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -2288,9 +2326,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmimalloc-sys" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" +checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7" dependencies = [ "cc", "libc", @@ -2298,9 +2336,9 @@ dependencies = [ [[package]] name = "libproc" -version = "0.14.6" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb6497078a4c9c2aca63df56d8dce6eb4381d53a960f781a3a748f7ea97436d" +checksum = "ae9ea4b75e1a81675429dafe43441df1caea70081e82246a8cccf514884a88bb" dependencies = [ "bindgen", "errno", @@ -2371,9 +2409,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2391,7 +2429,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -2522,7 +2560,7 @@ dependencies = [ "cfg-if", "miette-derive", "owo-colors", - "supports-color", + "supports-color 3.0.0", "supports-hyperlinks", "supports-unicode", "terminal_size", @@ -2539,14 +2577,14 @@ checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "mimalloc" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" +checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d" dependencies = [ "libmimalloc-sys", ] @@ -2738,7 +2776,6 @@ dependencies = [ "crossterm", "ctrlc", "dirs-next", - "divan", "log", "miette", "mimalloc", @@ -2770,6 +2807,7 @@ dependencies = [ "serde_json", "serial_test", "simplelog", + "tango-bench", "tempfile", "time", "winresource", @@ -3013,7 +3051,7 @@ dependencies = [ "uu_mv", "uu_uname", "uu_whoami", - "uucore", + "uucore 0.0.25", "uuid", "v_htmlescape", "wax", @@ -3414,9 +3452,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" dependencies = [ "num-bigint", "num-complex", @@ -3551,23 +3589,58 @@ dependencies = [ ] [[package]] -name = "objc-foundation" -version = "0.1.1" +name = "objc-sys" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" + +[[package]] +name = "objc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" dependencies = [ - "block", - "objc", - "objc_id", + "objc-sys", + "objc2-encode", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-app-kit" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" dependencies = [ - "objc", + "block2", + "objc2", + "objc2-core-data", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" + +[[package]] +name = "objc2-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" +dependencies = [ + "block2", + "objc2", ] [[package]] @@ -3625,7 +3698,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3663,7 +3736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" dependencies = [ "dlv-list", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -3706,9 +3779,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -3716,15 +3789,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -3739,9 +3812,9 @@ dependencies = [ [[package]] name = "parse-zoneinfo" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" dependencies = [ "regex", ] @@ -3772,9 +3845,9 @@ checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" [[package]] name = "pest" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -3783,9 +3856,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -3793,22 +3866,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "pest_meta" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -3894,7 +3967,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3933,6 +4006,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "planus" version = "0.3.1" @@ -3944,9 +4023,9 @@ dependencies = [ [[package]] name = "platform-info" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6259c4860e53bf665016f1b2f46a8859cadfa717581dc9d597ae4069de6300f" +checksum = "d5ff316b9c4642feda973c18f0decd6c8b0919d4722566f6e4337cce0dd88217" dependencies = [ "libc", "winapi", @@ -3954,9 +4033,9 @@ dependencies = [ [[package]] name = "polars" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c352aaa0399c0863eecd879f2cbe585c9026c5cafe432f029025e4bec3adf43" +checksum = "0ea21b858b16b9c0e17a12db2800d11aa5b4bd182be6b3022eb537bbfc1f2db5" dependencies = [ "getrandom", "polars-arrow", @@ -3974,9 +4053,9 @@ dependencies = [ [[package]] name = "polars-arrow" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88d3cfc6b500f106f03a5f4d37f700deef38c5b58a2e843edb3ec31f5a0ec19" +checksum = "725b09f2b5ef31279b66e27bbab63c58d49d8f6696b66b1f46c7eaab95e80f75" dependencies = [ "ahash 0.8.11", "atoi", @@ -3992,7 +4071,7 @@ dependencies = [ "foreign_vec", "futures", "getrandom", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "itoa", "itoap", "lz4", @@ -4022,9 +4101,9 @@ dependencies = [ [[package]] name = "polars-compute" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf264bfb632aaeba859fe19a87fa051d850e72542c36177ccea71fd9cae84079" +checksum = "a796945b14b14fbb79b91ef0406e6fddca2be636e889f81ea5d6ee7d36efb4fe" dependencies = [ "bytemuck", "either", @@ -4038,9 +4117,9 @@ dependencies = [ [[package]] name = "polars-core" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cb72917958e82f29d604429ab55851f561c7cd336f7744a7360f9e50b9ac88" +checksum = "465f70d3e96b6d0b1a43c358ba451286b8c8bd56696feff020d65702aa33e35c" dependencies = [ "ahash 0.8.11", "bitflags 2.5.0", @@ -4049,7 +4128,7 @@ dependencies = [ "chrono-tz 0.8.6", "comfy-table", "either", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -4072,9 +4151,9 @@ dependencies = [ [[package]] name = "polars-error" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c18ef81979a6d9e9fdbd25ad3bf1591cbd5c474489f785af44604cf591cd636d" +checksum = "5224d5d05e6b8a6f78b75951ae1b5f82c8ab1979e11ffaf5fd41941e3d5b0757" dependencies = [ "avro-schema", "polars-arrow-format", @@ -4085,9 +4164,9 @@ dependencies = [ [[package]] name = "polars-io" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d47f2cdd8e2a2bfc71b0d30444d4c378ddc0d6f80826746fc3c731c06251b42" +checksum = "b2c8589e418cbe4a48228d64b2a8a40284a82ec3c98817c0c2bcc0267701338b" dependencies = [ "ahash 0.8.11", "async-trait", @@ -4126,14 +4205,14 @@ dependencies = [ [[package]] name = "polars-json" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af22dcdf6f94894bbedb0b0b11fbffbb1905cc6e2a43bdb3e15355f3d4cf874a" +checksum = "81224492a649a12b668480c0cf219d703f432509765d2717e72fe32ad16fc701" dependencies = [ "ahash 0.8.11", "chrono", "fallible-streaming-iterator", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "indexmap", "itoa", "num-traits", @@ -4147,9 +4226,9 @@ dependencies = [ [[package]] name = "polars-lazy" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee5683b551f5e2bb004468edec0f87fd585f436c2e5f89b292c2bfee1b6f5d4f" +checksum = "89b2632b1af668e2058d5f8f916d8fbde3cac63d03ae29a705f598e41dcfeb7f" dependencies = [ "ahash 0.8.11", "bitflags 2.5.0", @@ -4171,9 +4250,9 @@ dependencies = [ [[package]] name = "polars-ops" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f311543e0e110d385867df25f47c1c740ee0cc854feead54262a24b0246383bb" +checksum = "efdbdb4d9a92109bc2e0ce8e17af5ae8ab643bb5b7ee9d1d74f0aeffd1fbc95f" dependencies = [ "ahash 0.8.11", "argminmax", @@ -4182,7 +4261,7 @@ dependencies = [ "chrono", "chrono-tz 0.8.6", "either", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "indexmap", "jsonpath_lib_polars_vendor", @@ -4207,9 +4286,9 @@ dependencies = [ [[package]] name = "polars-parquet" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cd1f445fea8377350dfa2bd216785839ce97c826299c7e0e9557c1dbe887f" +checksum = "b421d2196f786fdfe162db614c8485f8308fe41575d4de634a39bbe460d1eb6a" dependencies = [ "ahash 0.8.11", "async-stream", @@ -4233,14 +4312,14 @@ dependencies = [ [[package]] name = "polars-pipe" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f57de92c0ca9851e89cf9374cd88029f9bb2197937c34d571ec2a7ac45cca3" +checksum = "48700f1d5bd56a15451e581f465c09541492750360f18637b196f995470a015c" dependencies = [ "crossbeam-channel", "crossbeam-queue", "enum_dispatch", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "num-traits", "polars-arrow", "polars-compute", @@ -4258,14 +4337,14 @@ dependencies = [ [[package]] name = "polars-plan" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c509bc273c402a8b1fbfa63df2b2e90ca10d30decab698c7739003817de67e1" +checksum = "2fb8e2302e20c44defd5be8cad9c96e75face63c3a5f609aced8c4ec3b3ac97d" dependencies = [ "ahash 0.8.11", "bytemuck", "chrono-tz 0.8.6", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "once_cell", "percent-encoding", "polars-arrow", @@ -4287,9 +4366,9 @@ dependencies = [ [[package]] name = "polars-row" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695a9954f5aa273e44c497c19f806177f787ccf87cd4b3044c96a5057266a861" +checksum = "a515bdc68c2ae3702e3de70d89601f3b71ca8137e282a226dddb53ee4bacfa2e" dependencies = [ "bytemuck", "polars-arrow", @@ -4299,9 +4378,9 @@ dependencies = [ [[package]] name = "polars-sql" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7cdf3b41bda70004ed3ec78652eb690aec3db5d99dfac03fbf9995fe76a7e26" +checksum = "7b4bb7cc1c04c3023d1953b2f1dec50515e8fd8169a5a2bf4967b3b082232db7" dependencies = [ "hex", "polars-arrow", @@ -4317,9 +4396,9 @@ dependencies = [ [[package]] name = "polars-time" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bdc956b63e99a5ad1dabd9d397ce9ce50f703e503a5039c972968683a953d0c" +checksum = "efc18e3ad92eec55db89d88f16c22d436559ba7030cf76f86f6ed7a754b673f1" dependencies = [ "atoi", "chrono", @@ -4338,13 +4417,13 @@ dependencies = [ [[package]] name = "polars-utils" -version = "0.39.1" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355b126757b4a87da5248ae6eb644e99b5583a11ffc2d42e13b2b856d43e84be" +checksum = "c760b6c698cfe2fbbbd93d6cfb408db14ececfe1d92445dae2229ce1b5b21ae8" dependencies = [ "ahash 0.8.11", "bytemuck", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -4470,9 +4549,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -4594,9 +4673,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -4675,9 +4754,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ "bitflags 2.5.0", ] @@ -4719,7 +4798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -4737,6 +4816,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "redox_users" version = "0.4.5" @@ -4788,7 +4876,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -4814,12 +4902,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-lite" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" - [[package]] name = "regex-syntax" version = "0.8.3" @@ -4951,7 +5033,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.58", + "syn 2.0.60", "unicode-ident", ] @@ -4990,7 +5072,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.58", + "syn 2.0.60", "walkdir", ] @@ -5054,9 +5136,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -5131,6 +5213,26 @@ dependencies = [ "tendril", ] +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "sdd" version = "0.2.0" @@ -5199,29 +5301,29 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "indexmap", "itoa", @@ -5237,7 +5339,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5276,9 +5378,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb86f9315df5df6a70eae0cc22395a44e544a0d8897586820770a35ede74449" +checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" dependencies = [ "futures", "log", @@ -5290,13 +5392,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9bb72430492e9549b0c4596725c0f82729bff861c45aa8099c0a8e67fc3b721" +checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5365,18 +5467,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "simd-json" -version = "0.13.9" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b84c23a1066e1d650ebc99aa8fb9f8ed0ab96fd36e2e836173c92fc9fb29bc" +checksum = "570c430b3d902ea083097e853263ae782dfe40857d93db019a12356c8e8143fa" dependencies = [ "ahash 0.8.11", "getrandom", @@ -5460,9 +5562,9 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -5493,7 +5595,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5608,7 +5710,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5621,7 +5723,17 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.58", + "syn 2.0.60", +] + +[[package]] +name = "supports-color" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +dependencies = [ + "is-terminal", + "is_ci", ] [[package]] @@ -5679,9 +5791,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -5697,7 +5809,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5711,9 +5823,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.9" +version = "0.30.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a84fe4cfc513b41cb2596b624e561ec9e7e1c4b46328e496ed56a53514ef2a" +checksum = "87341a165d73787554941cd5ef55ad728011566fe714e987d1b976c15dbc3a83" dependencies = [ "cfg-if", "core-foundation-sys", @@ -5736,6 +5848,27 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tango-bench" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e79d9e491b718fb52bb2052726a0e66fe89a31cc6979fe58c72c73f058c279e" +dependencies = [ + "alloca", + "anyhow", + "clap", + "colorz", + "glob-match", + "goblin", + "libloading", + "log", + "num-traits", + "rand", + "scroll", + "tempfile", + "thiserror", +] + [[package]] name = "tap" version = "1.0.1" @@ -5809,22 +5942,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -5839,9 +5972,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -5862,9 +5995,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -5957,7 +6090,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.12", ] [[package]] @@ -5995,15 +6128,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.7", ] [[package]] @@ -6106,7 +6239,7 @@ checksum = "ac73887f47b9312552aa90ef477927ff014d63d1920ca8037c6c1951eab64bb1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -6177,9 +6310,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -6195,11 +6328,11 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "ureq" -version = "2.9.6" +version = "2.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" +checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "encoding_rs", "flate2", "log", @@ -6251,7 +6384,7 @@ dependencies = [ "indicatif", "libc", "quick-error 2.0.1", - "uucore", + "uucore 0.0.26", "walkdir", "xattr", ] @@ -6263,7 +6396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "040aa4584036b2f65e05387b0ea9ac468afce1db325743ce5f350689fd9ce4ae" dependencies = [ "clap", - "uucore", + "uucore 0.0.26", ] [[package]] @@ -6275,7 +6408,7 @@ dependencies = [ "clap", "rand", "tempfile", - "uucore", + "uucore 0.0.26", ] [[package]] @@ -6287,7 +6420,7 @@ dependencies = [ "clap", "fs_extra", "indicatif", - "uucore", + "uucore 0.0.26", ] [[package]] @@ -6298,7 +6431,7 @@ checksum = "5951832d73199636bde6c0d61cf960932b3c4450142c290375bc10c7abed6db5" dependencies = [ "clap", "platform-info", - "uucore", + "uucore 0.0.26", ] [[package]] @@ -6309,7 +6442,7 @@ checksum = "e3b44166eb6335aeac42744ea368cc4c32d3f2287a4ff765a5ce44d927ab8bb4" dependencies = [ "clap", "libc", - "uucore", + "uucore 0.0.26", "windows-sys 0.48.0", ] @@ -6318,12 +6451,29 @@ name = "uucore" version = "0.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23994a722acb43dbc56877e271c9723f167ae42c4c089f909b2d7dd106c3a9b4" +dependencies = [ + "clap", + "glob", + "libc", + "nix", + "once_cell", + "os_display", + "uucore_procs", + "wild", +] + +[[package]] +name = "uucore" +version = "0.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2ea2f77699e5ff5c7e001af588ceb34cae8b5f9af5496bea5a6476aaa8e780" dependencies = [ "clap", "dunce", "glob", "libc", "nix", + "number_prefix", "once_cell", "os_display", "uucore_procs", @@ -6336,9 +6486,9 @@ dependencies = [ [[package]] name = "uucore_procs" -version = "0.0.25" +version = "0.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f51594832e53b11811446b1cd3567722e2906a589a5b19622c5c4720977309" +checksum = "1a233a488da42f3ddb0aaa8a9f75a969e3f37e4de7e909d2d23f6aa3ee401d20" dependencies = [ "proc-macro2", "quote", @@ -6347,9 +6497,9 @@ dependencies = [ [[package]] name = "uuhelp_parser" -version = "0.0.25" +version = "0.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac7a6832a5add86204d5a8d0ef41c5a11e3ddf61c0f1a508f69e7e3e1bf04e3f" +checksum = "425a23c7b7145bc7620c9c445817c37b1f78b6790aee9f208133f3c028975b60" [[package]] name = "uuid" @@ -6477,7 +6627,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -6499,7 +6649,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6643,11 +6793,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -6672,7 +6822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -6682,7 +6832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ "windows-core 0.54.0", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -6691,7 +6841,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -6701,16 +6851,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ "windows-result", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] name = "windows-result" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd19df78e5168dfb0aedc343d1d1b8d422ab2db6756d2dc3fef75035402a3f64" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -6728,7 +6878,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -6763,17 +6913,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -6790,9 +6941,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -6808,9 +6959,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -6826,9 +6977,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -6844,9 +7001,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -6862,9 +7019,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -6880,9 +7037,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -6898,9 +7055,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -6913,9 +7070,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] @@ -6977,9 +7134,9 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "gethostname", "rustix", @@ -6988,9 +7145,9 @@ dependencies = [ [[package]] name = "x11rb-protocol" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xattr" @@ -7032,7 +7189,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 11f393a5ce..beabd26e20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -227,7 +227,7 @@ nu-plugin-protocol = { path = "./crates/nu-plugin-protocol", version = "0.93.1" nu-plugin-core = { path = "./crates/nu-plugin-core", version = "0.93.1" } assert_cmd = "2.0" dirs-next = { workspace = true } -divan = "0.1.14" +tango-bench = "0.5" pretty_assertions = { workspace = true } rstest = { workspace = true, default-features = false } serial_test = "3.1" diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index e6bec2e163..859e3e2d2d 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -1,7 +1,7 @@ use nu_cli::{eval_source, evaluate_commands}; -use nu_parser::parse; use nu_plugin_core::{Encoder, EncodingType}; use nu_plugin_protocol::{PluginCallResponse, PluginOutput}; + use nu_protocol::{ engine::{EngineState, Stack}, eval_const::create_nu_constant, @@ -9,12 +9,14 @@ use nu_protocol::{ }; use nu_std::load_standard_library; use nu_utils::{get_default_config, get_default_env}; -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + rc::Rc, +}; -fn main() { - // Run registered benchmarks. - divan::main(); -} +use std::hint::black_box; + +use tango_bench::{benchmark_fn, tango_benchmarks, tango_main, IntoBenchmarks}; fn load_bench_commands() -> EngineState { nu_command::add_shell_command_context(nu_cmd_lang::create_default_context()) @@ -57,42 +59,6 @@ fn setup_engine() -> EngineState { engine_state } -fn bench_command(bencher: divan::Bencher, scaled_command: String) { - bench_command_with_custom_stack_and_engine( - bencher, - scaled_command, - Stack::new(), - setup_engine(), - ) -} - -fn bench_command_with_custom_stack_and_engine( - bencher: divan::Bencher, - scaled_command: String, - stack: nu_protocol::engine::Stack, - mut engine: EngineState, -) { - load_standard_library(&mut engine).unwrap(); - let commands = Spanned { - span: Span::unknown(), - item: scaled_command, - }; - - bencher - .with_inputs(|| engine.clone()) - .bench_values(|mut engine| { - evaluate_commands( - &commands, - &mut engine, - &mut stack.clone(), - PipelineData::empty(), - None, - false, - ) - .unwrap(); - }) -} - fn setup_stack_and_engine_from_command(command: &str) -> (Stack, EngineState) { let mut engine = setup_engine(); let commands = Spanned { @@ -114,261 +80,6 @@ fn setup_stack_and_engine_from_command(command: &str) -> (Stack, EngineState) { (stack, engine) } -// FIXME: All benchmarks live in this 1 file to speed up build times when benchmarking. -// When the *_benchmarks functions were in different files, `cargo bench` would build -// an executable for every single one - incredibly slowly. Would be nice to figure out -// a way to split things up again. - -#[divan::bench] -fn load_standard_lib(bencher: divan::Bencher) { - let engine = setup_engine(); - bencher - .with_inputs(|| engine.clone()) - .bench_values(|mut engine| { - load_standard_library(&mut engine).unwrap(); - }) -} - -#[divan::bench_group] -mod record { - - use super::*; - - fn create_flat_record_string(n: i32) -> String { - let mut s = String::from("let record = {"); - for i in 0..n { - s.push_str(&format!("col_{}: {}", i, i)); - if i < n - 1 { - s.push_str(", "); - } - } - s.push('}'); - s - } - - fn create_nested_record_string(depth: i32) -> String { - let mut s = String::from("let record = {"); - for _ in 0..depth { - s.push_str("col: {"); - } - s.push_str("col_final: 0"); - for _ in 0..depth { - s.push('}'); - } - s.push('}'); - s - } - - #[divan::bench(args = [1, 10, 100, 1000])] - fn create(bencher: divan::Bencher, n: i32) { - bench_command(bencher, create_flat_record_string(n)); - } - - #[divan::bench(args = [1, 10, 100, 1000])] - fn flat_access(bencher: divan::Bencher, n: i32) { - let (stack, engine) = setup_stack_and_engine_from_command(&create_flat_record_string(n)); - bench_command_with_custom_stack_and_engine( - bencher, - "$record.col_0 | ignore".to_string(), - stack, - engine, - ); - } - - #[divan::bench(args = [1, 2, 4, 8, 16, 32, 64, 128])] - fn nest_access(bencher: divan::Bencher, depth: i32) { - let (stack, engine) = - setup_stack_and_engine_from_command(&create_nested_record_string(depth)); - let nested_access = ".col".repeat(depth as usize); - bench_command_with_custom_stack_and_engine( - bencher, - format!("$record{} | ignore", nested_access), - stack, - engine, - ); - } -} - -#[divan::bench_group] -mod table { - - use super::*; - - fn create_example_table_nrows(n: i32) -> String { - let mut s = String::from("let table = [[foo bar baz]; "); - for i in 0..n { - s.push_str(&format!("[0, 1, {i}]")); - if i < n - 1 { - s.push_str(", "); - } - } - s.push(']'); - s - } - - #[divan::bench(args = [1, 10, 100, 1000])] - fn create(bencher: divan::Bencher, n: i32) { - bench_command(bencher, create_example_table_nrows(n)); - } - - #[divan::bench(args = [1, 10, 100, 1000])] - fn get(bencher: divan::Bencher, n: i32) { - let (stack, engine) = setup_stack_and_engine_from_command(&create_example_table_nrows(n)); - bench_command_with_custom_stack_and_engine( - bencher, - "$table | get bar | math sum | ignore".to_string(), - stack, - engine, - ); - } - - #[divan::bench(args = [1, 10, 100, 1000])] - fn select(bencher: divan::Bencher, n: i32) { - let (stack, engine) = setup_stack_and_engine_from_command(&create_example_table_nrows(n)); - bench_command_with_custom_stack_and_engine( - bencher, - "$table | select foo baz | ignore".to_string(), - stack, - engine, - ); - } -} - -#[divan::bench_group] -mod eval_commands { - use super::*; - - #[divan::bench(args = [100, 1_000, 10_000])] - fn interleave(bencher: divan::Bencher, n: i32) { - bench_command( - bencher, - format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), - ) - } - - #[divan::bench(args = [100, 1_000, 10_000])] - fn interleave_with_ctrlc(bencher: divan::Bencher, n: i32) { - let mut engine = setup_engine(); - engine.ctrlc = Some(std::sync::Arc::new(std::sync::atomic::AtomicBool::new( - false, - ))); - load_standard_library(&mut engine).unwrap(); - let commands = Spanned { - span: Span::unknown(), - item: format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), - }; - - bencher - .with_inputs(|| engine.clone()) - .bench_values(|mut engine| { - evaluate_commands( - &commands, - &mut engine, - &mut nu_protocol::engine::Stack::new(), - PipelineData::empty(), - None, - false, - ) - .unwrap(); - }) - } - - #[divan::bench(args = [1, 5, 10, 100, 1_000])] - fn for_range(bencher: divan::Bencher, n: i32) { - bench_command(bencher, format!("(for $x in (1..{}) {{ sleep 50ns }})", n)) - } - - #[divan::bench(args = [1, 5, 10, 100, 1_000])] - fn each(bencher: divan::Bencher, n: i32) { - bench_command( - bencher, - format!("(1..{}) | each {{|_| sleep 50ns }} | ignore", n), - ) - } - - #[divan::bench(args = [1, 5, 10, 100, 1_000])] - fn par_each_1t(bencher: divan::Bencher, n: i32) { - bench_command( - bencher, - format!("(1..{}) | par-each -t 1 {{|_| sleep 50ns }} | ignore", n), - ) - } - - #[divan::bench(args = [1, 5, 10, 100, 1_000])] - fn par_each_2t(bencher: divan::Bencher, n: i32) { - bench_command( - bencher, - format!("(1..{}) | par-each -t 2 {{|_| sleep 50ns }} | ignore", n), - ) - } -} - -#[divan::bench_group()] -mod parser_benchmarks { - use super::*; - - #[divan::bench()] - fn parse_default_config_file(bencher: divan::Bencher) { - let engine_state = setup_engine(); - let default_env = get_default_config().as_bytes(); - - bencher - .with_inputs(|| nu_protocol::engine::StateWorkingSet::new(&engine_state)) - .bench_refs(|working_set| parse(working_set, None, default_env, false)) - } - - #[divan::bench()] - fn parse_default_env_file(bencher: divan::Bencher) { - let engine_state = setup_engine(); - let default_env = get_default_env().as_bytes(); - - bencher - .with_inputs(|| nu_protocol::engine::StateWorkingSet::new(&engine_state)) - .bench_refs(|working_set| parse(working_set, None, default_env, false)) - } -} - -#[divan::bench_group()] -mod eval_benchmarks { - use super::*; - - #[divan::bench()] - fn eval_default_env(bencher: divan::Bencher) { - let default_env = get_default_env().as_bytes(); - let fname = "default_env.nu"; - bencher - .with_inputs(|| (setup_engine(), nu_protocol::engine::Stack::new())) - .bench_values(|(mut engine_state, mut stack)| { - eval_source( - &mut engine_state, - &mut stack, - default_env, - fname, - PipelineData::empty(), - false, - ) - }) - } - - #[divan::bench()] - fn eval_default_config(bencher: divan::Bencher) { - let default_env = get_default_config().as_bytes(); - let fname = "default_config.nu"; - bencher - .with_inputs(|| (setup_engine(), nu_protocol::engine::Stack::new())) - .bench_values(|(mut engine_state, mut stack)| { - eval_source( - &mut engine_state, - &mut stack, - default_env, - fname, - PipelineData::empty(), - false, - ) - }) - } -} - // generate a new table data with `row_cnt` rows, `col_cnt` columns. fn encoding_test_data(row_cnt: usize, col_cnt: usize) -> Value { let record = Value::test_record( @@ -380,76 +91,423 @@ fn encoding_test_data(row_cnt: usize, col_cnt: usize) -> Value { Value::list(vec![record; row_cnt], Span::test_data()) } -#[divan::bench_group()] -mod encoding_benchmarks { - use super::*; - - #[divan::bench(args = [(100, 5), (10000, 15)])] - fn json_encode(bencher: divan::Bencher, (row_cnt, col_cnt): (usize, usize)) { - let test_data = PluginOutput::CallResponse( - 0, - PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), - ); - let encoder = EncodingType::try_from_bytes(b"json").unwrap(); - bencher - .with_inputs(Vec::new) - .bench_values(|mut res| encoder.encode(&test_data, &mut res)) - } - - #[divan::bench(args = [(100, 5), (10000, 15)])] - fn msgpack_encode(bencher: divan::Bencher, (row_cnt, col_cnt): (usize, usize)) { - let test_data = PluginOutput::CallResponse( - 0, - PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), - ); - let encoder = EncodingType::try_from_bytes(b"msgpack").unwrap(); - bencher - .with_inputs(Vec::new) - .bench_values(|mut res| encoder.encode(&test_data, &mut res)) - } +fn bench_command( + name: &str, + command: &str, + stack: Stack, + engine: EngineState, +) -> impl IntoBenchmarks { + let commands = Spanned { + span: Span::unknown(), + item: command.to_string(), + }; + [benchmark_fn(name, move |b| { + let commands = commands.clone(); + let stack = stack.clone(); + let engine = engine.clone(); + b.iter(move || { + let mut stack = stack.clone(); + let mut engine = engine.clone(); + black_box( + evaluate_commands( + &commands, + &mut engine, + &mut stack, + PipelineData::empty(), + None, + false, + ) + .unwrap(), + ); + }) + })] } -#[divan::bench_group()] -mod decoding_benchmarks { - use super::*; - - #[divan::bench(args = [(100, 5), (10000, 15)])] - fn json_decode(bencher: divan::Bencher, (row_cnt, col_cnt): (usize, usize)) { - let test_data = PluginOutput::CallResponse( - 0, - PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), - ); - let encoder = EncodingType::try_from_bytes(b"json").unwrap(); - let mut res = vec![]; - encoder.encode(&test_data, &mut res).unwrap(); - bencher - .with_inputs(|| { - let mut binary_data = std::io::Cursor::new(res.clone()); - binary_data.set_position(0); - binary_data - }) - .bench_values(|mut binary_data| -> Result, _> { - encoder.decode(&mut binary_data) - }) - } - - #[divan::bench(args = [(100, 5), (10000, 15)])] - fn msgpack_decode(bencher: divan::Bencher, (row_cnt, col_cnt): (usize, usize)) { - let test_data = PluginOutput::CallResponse( - 0, - PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), - ); - let encoder = EncodingType::try_from_bytes(b"msgpack").unwrap(); - let mut res = vec![]; - encoder.encode(&test_data, &mut res).unwrap(); - bencher - .with_inputs(|| { - let mut binary_data = std::io::Cursor::new(res.clone()); - binary_data.set_position(0); - binary_data - }) - .bench_values(|mut binary_data| -> Result, _> { - encoder.decode(&mut binary_data) - }) - } +fn bench_eval_source( + name: &str, + fname: String, + source: Vec, + stack: Stack, + engine: EngineState, +) -> impl IntoBenchmarks { + [benchmark_fn(name, move |b| { + let stack = stack.clone(); + let engine = engine.clone(); + let fname = fname.clone(); + let source = source.clone(); + b.iter(move || { + let mut stack = stack.clone(); + let mut engine = engine.clone(); + let fname: &str = &fname.clone(); + let source: &[u8] = &source.clone(); + black_box(eval_source( + &mut engine, + &mut stack, + source, + fname, + PipelineData::empty(), + false, + )); + }) + })] } + +/// Load the standard library into the engine. +fn bench_load_standard_lib() -> impl IntoBenchmarks { + [benchmark_fn("load_standard_lib", move |b| { + let engine = setup_engine(); + b.iter(move || { + let mut engine = engine.clone(); + load_standard_library(&mut engine) + }) + })] +} + +fn create_flat_record_string(n: i32) -> String { + let mut s = String::from("let record = {"); + for i in 0..n { + s.push_str(&format!("col_{}: {}", i, i)); + if i < n - 1 { + s.push_str(", "); + } + } + s.push('}'); + s +} + +fn create_nested_record_string(depth: i32) -> String { + let mut s = String::from("let record = {"); + for _ in 0..depth { + s.push_str("col: {"); + } + s.push_str("col_final: 0"); + for _ in 0..depth { + s.push('}'); + } + s.push('}'); + s +} + +fn create_example_table_nrows(n: i32) -> String { + let mut s = String::from("let table = [[foo bar baz]; "); + for i in 0..n { + s.push_str(&format!("[0, 1, {i}]")); + if i < n - 1 { + s.push_str(", "); + } + } + s.push(']'); + s +} + +fn bench_record_create(n: i32) -> impl IntoBenchmarks { + bench_command( + &format!("record_create_{n}"), + &create_flat_record_string(n), + Stack::new(), + setup_engine(), + ) +} + +fn bench_record_flat_access(n: i32) -> impl IntoBenchmarks { + let setup_command = create_flat_record_string(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + &format!("record_flat_access_{n}"), + "$record.col_0 | ignore", + stack, + engine, + ) +} + +fn bench_record_nested_access(n: i32) -> impl IntoBenchmarks { + let setup_command = create_nested_record_string(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + let nested_access = ".col".repeat(n as usize); + bench_command( + &format!("record_nested_access_{n}"), + &format!("$record{} | ignore", nested_access), + stack, + engine, + ) +} + +fn bench_table_create(n: i32) -> impl IntoBenchmarks { + bench_command( + &format!("table_create_{n}"), + &create_example_table_nrows(n), + Stack::new(), + setup_engine(), + ) +} + +fn bench_table_get(n: i32) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + &format!("table_get_{n}"), + "$table | get bar | math sum | ignore", + stack, + engine, + ) +} + +fn bench_table_select(n: i32) -> impl IntoBenchmarks { + let setup_command = create_example_table_nrows(n); + let (stack, engine) = setup_stack_and_engine_from_command(&setup_command); + bench_command( + &format!("table_select_{n}"), + "$table | select foo baz | ignore", + stack, + engine, + ) +} + +fn bench_eval_interleave(n: i32) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + &format!("eval_interleave_{n}"), + &format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_interleave_with_ctrlc(n: i32) -> impl IntoBenchmarks { + let mut engine = setup_engine(); + engine.ctrlc = Some(std::sync::Arc::new(std::sync::atomic::AtomicBool::new( + false, + ))); + let stack = Stack::new(); + bench_command( + &format!("eval_interleave_with_ctrlc_{n}"), + &format!("seq 1 {n} | wrap a | interleave {{ seq 1 {n} | wrap b }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_for(n: i32) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + &format!("eval_for_{n}"), + &format!("(for $x in (1..{n}) {{ 1 }}) | ignore"), + stack, + engine, + ) +} + +fn bench_eval_each(n: i32) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + &format!("eval_each_{n}"), + &format!("(1..{n}) | each {{|_| 1 }} | ignore"), + stack, + engine, + ) +} + +fn bench_eval_par_each(n: i32) -> impl IntoBenchmarks { + let engine = setup_engine(); + let stack = Stack::new(); + bench_command( + &format!("eval_par_each_{n}"), + &format!("(1..{}) | par-each -t 2 {{|_| 1 }} | ignore", n), + stack, + engine, + ) +} + +fn bench_eval_default_config() -> impl IntoBenchmarks { + let default_env = get_default_config().as_bytes().to_vec(); + let fname = "default_config.nu".to_string(); + bench_eval_source( + "eval_default_config", + fname, + default_env, + Stack::new(), + setup_engine(), + ) +} + +fn bench_eval_default_env() -> impl IntoBenchmarks { + let default_env = get_default_env().as_bytes().to_vec(); + let fname = "default_env.nu".to_string(); + bench_eval_source( + "eval_default_env", + fname, + default_env, + Stack::new(), + setup_engine(), + ) +} + +fn encode_json(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = Rc::new(PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + )); + let encoder = Rc::new(EncodingType::try_from_bytes(b"json").unwrap()); + + [benchmark_fn( + format!("encode_json_{}_{}", row_cnt, col_cnt), + move |b| { + let encoder = encoder.clone(); + let test_data = test_data.clone(); + b.iter(move || { + let mut res = Vec::new(); + encoder.encode(&*test_data, &mut res).unwrap(); + }) + }, + )] +} + +fn encode_msgpack(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = Rc::new(PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + )); + let encoder = Rc::new(EncodingType::try_from_bytes(b"msgpack").unwrap()); + + [benchmark_fn( + format!("encode_msgpack_{}_{}", row_cnt, col_cnt), + move |b| { + let encoder = encoder.clone(); + let test_data = test_data.clone(); + b.iter(move || { + let mut res = Vec::new(); + encoder.encode(&*test_data, &mut res).unwrap(); + }) + }, + )] +} + +fn decode_json(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + ); + let encoder = EncodingType::try_from_bytes(b"json").unwrap(); + let mut res = vec![]; + encoder.encode(&test_data, &mut res).unwrap(); + + [benchmark_fn( + format!("decode_json_{}_{}", row_cnt, col_cnt), + move |b| { + let res = res.clone(); + b.iter(move || { + let mut binary_data = std::io::Cursor::new(res.clone()); + binary_data.set_position(0); + let _: Result, _> = + black_box(encoder.decode(&mut binary_data)); + }) + }, + )] +} + +fn decode_msgpack(row_cnt: usize, col_cnt: usize) -> impl IntoBenchmarks { + let test_data = PluginOutput::CallResponse( + 0, + PluginCallResponse::value(encoding_test_data(row_cnt, col_cnt)), + ); + let encoder = EncodingType::try_from_bytes(b"msgpack").unwrap(); + let mut res = vec![]; + encoder.encode(&test_data, &mut res).unwrap(); + + [benchmark_fn( + format!("decode_msgpack_{}_{}", row_cnt, col_cnt), + move |b| { + let res = res.clone(); + b.iter(move || { + let mut binary_data = std::io::Cursor::new(res.clone()); + binary_data.set_position(0); + let _: Result, _> = + black_box(encoder.decode(&mut binary_data)); + }) + }, + )] +} + +tango_benchmarks!( + bench_load_standard_lib(), + // Data types + // Record + bench_record_create(1), + bench_record_create(10), + bench_record_create(100), + bench_record_create(1_000), + bench_record_flat_access(1), + bench_record_flat_access(10), + bench_record_flat_access(100), + bench_record_flat_access(1_000), + bench_record_nested_access(1), + bench_record_nested_access(2), + bench_record_nested_access(4), + bench_record_nested_access(8), + bench_record_nested_access(16), + bench_record_nested_access(32), + bench_record_nested_access(64), + bench_record_nested_access(128), + // Table + bench_table_create(1), + bench_table_create(10), + bench_table_create(100), + bench_table_create(1_000), + bench_table_get(1), + bench_table_get(10), + bench_table_get(100), + bench_table_get(1_000), + bench_table_select(1), + bench_table_select(10), + bench_table_select(100), + bench_table_select(1_000), + // Eval + // Interleave + bench_eval_interleave(100), + bench_eval_interleave(1_000), + bench_eval_interleave(10_000), + bench_eval_interleave_with_ctrlc(100), + bench_eval_interleave_with_ctrlc(1_000), + bench_eval_interleave_with_ctrlc(10_000), + // For + bench_eval_for(1), + bench_eval_for(10), + bench_eval_for(100), + bench_eval_for(1_000), + bench_eval_for(10_000), + // Each + bench_eval_each(1), + bench_eval_each(10), + bench_eval_each(100), + bench_eval_each(1_000), + bench_eval_each(10_000), + // Par-Each + bench_eval_par_each(1), + bench_eval_par_each(10), + bench_eval_par_each(100), + bench_eval_par_each(1_000), + bench_eval_par_each(10_000), + // Config + bench_eval_default_config(), + // Env + bench_eval_default_env(), + // Encode + // Json + encode_json(100, 5), + encode_json(10000, 15), + // MsgPack + encode_msgpack(100, 5), + encode_msgpack(10000, 15), + // Decode + // Json + decode_json(100, 5), + decode_json(10000, 15), + // MsgPack + decode_msgpack(100, 5), + decode_msgpack(10000, 15) +); + +tango_main!(); diff --git a/scripts/build.rs b/scripts/build.rs index f5823043e0..beabba80dc 100644 --- a/scripts/build.rs +++ b/scripts/build.rs @@ -10,4 +10,9 @@ fn main() { } #[cfg(not(windows))] -fn main() {} +fn main() { + // Tango uses dynamic linking, to allow us to dynamically change between two bench suit at runtime. + // This is currently not supported on non nightly rust, on windows. + println!("cargo:rustc-link-arg-benches=-rdynamic"); + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/toolkit.nu b/toolkit.nu index 98fcd4400b..407998c514 100644 --- a/toolkit.nu +++ b/toolkit.nu @@ -491,6 +491,31 @@ export def cov [] { print $"Coverage generation took ($end - $start)." } + +# Benchmark the current branch against the main branch +# Ensure you have `cargo-export` installed to generate separate artifacts for each branch. +export def "benchmark-current-branch-with-main" [] { + let main = "main" + let current_branch = (git branch --show-current) + + cargo export $"target/($current_branch)" -- bench + git checkout $main + cargo export $"target/($main)" -- bench + git checkout $current_branch + ^$"./target/($current_branch)/benchmarks" compare $"./target/($main)/benchmarks" -o -s 50 +} + +# Benchmark the current branch and logs the result in `./target/samples` +# Ensure you have `cargo-export` installed to generate separate artifacts for each branch. +export def "benchmark-and-log-result" [] { + let current_branch = (git branch --show-current) + let current_dir = "./" | path expand + let res_path = $"($current_dir)/target/samples" + + cargo export $"target/($current_branch)" -- bench + ^$"./target/($current_branch)/benchmarks" compare -o -s 50 --dump $res_path +} + # Build all Windows archives and MSIs for release manually # # This builds std and full distributions for both aarch64 and x86_64. From e879d4ecaf75cb5dff02fb9f19a39848a477b916 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Sun, 5 May 2024 16:00:59 +0000 Subject: [PATCH 15/15] `ListStream` touchup (#12524) # Description Does some misc changes to `ListStream`: - Moves it into its own module/file separate from `RawStream`. - `ListStream`s now have an associated `Span`. - This required changes to `ListStreamInfo` in `nu-plugin`. Note sure if this is a breaking change for the plugin protocol. - Hides the internals of `ListStream` but also adds a few more methods. - This includes two functions to more easily alter a stream (these take a `ListStream` and return a `ListStream` instead of having to go through the whole `into_pipeline_data(..)` route). - `map`: takes a `FnMut(Value) -> Value` - `modify`: takes a function to modify the inner stream. --- .../nu-cli/src/commands/history/history_.rs | 4 +- .../src/extra/filters/each_while.rs | 4 +- .../src/extra/filters/update_cells.rs | 2 +- .../src/extra/strings/format/command.rs | 5 +- crates/nu-cmd-lang/src/core_commands/do_.rs | 36 +-- crates/nu-cmd-lang/src/core_commands/for_.rs | 7 +- .../src/core_commands/scope/aliases.rs | 7 +- .../src/core_commands/scope/commands.rs | 7 +- .../src/core_commands/scope/externs.rs | 7 +- .../src/core_commands/scope/modules.rs | 7 +- .../src/core_commands/scope/variables.rs | 7 +- .../nu-cmd-plugin/src/commands/plugin/list.rs | 44 ++-- .../src/conversions/into/cell_path.rs | 2 +- .../nu-command/src/conversions/into/value.rs | 2 +- .../src/database/commands/into_sqlite.rs | 4 +- crates/nu-command/src/date/list_timezone.rs | 8 +- crates/nu-command/src/debug/explain.rs | 10 +- crates/nu-command/src/debug/metadata_set.rs | 12 +- crates/nu-command/src/filesystem/du.rs | 4 +- crates/nu-command/src/filesystem/glob.rs | 18 +- crates/nu-command/src/filesystem/ls.rs | 6 +- crates/nu-command/src/filesystem/open.rs | 5 +- crates/nu-command/src/filesystem/rm.rs | 2 +- crates/nu-command/src/filters/append.rs | 2 +- crates/nu-command/src/filters/columns.rs | 73 +++--- crates/nu-command/src/filters/drop/column.rs | 5 +- crates/nu-command/src/filters/drop/nth.rs | 12 +- crates/nu-command/src/filters/each.rs | 4 +- crates/nu-command/src/filters/empty.rs | 5 +- crates/nu-command/src/filters/enumerate.rs | 8 +- crates/nu-command/src/filters/every.rs | 2 +- crates/nu-command/src/filters/filter.rs | 6 +- crates/nu-command/src/filters/find.rs | 19 +- crates/nu-command/src/filters/first.rs | 13 +- crates/nu-command/src/filters/get.rs | 2 +- crates/nu-command/src/filters/group.rs | 8 +- crates/nu-command/src/filters/insert.rs | 62 ++--- crates/nu-command/src/filters/interleave.rs | 2 +- crates/nu-command/src/filters/items.rs | 2 +- crates/nu-command/src/filters/lines.rs | 14 +- crates/nu-command/src/filters/merge.rs | 25 +- crates/nu-command/src/filters/move_.rs | 28 +-- crates/nu-command/src/filters/par_each.rs | 9 +- crates/nu-command/src/filters/prepend.rs | 2 +- crates/nu-command/src/filters/range.rs | 9 +- crates/nu-command/src/filters/reverse.rs | 8 +- crates/nu-command/src/filters/select.rs | 16 +- crates/nu-command/src/filters/shuffle.rs | 8 +- crates/nu-command/src/filters/skip/skip_.rs | 2 +- .../nu-command/src/filters/skip/skip_until.rs | 2 +- .../nu-command/src/filters/skip/skip_while.rs | 2 +- crates/nu-command/src/filters/sort.rs | 15 +- crates/nu-command/src/filters/sort_by.rs | 16 +- crates/nu-command/src/filters/take/take_.rs | 20 +- .../nu-command/src/filters/take/take_until.rs | 2 +- .../nu-command/src/filters/take/take_while.rs | 2 +- crates/nu-command/src/filters/tee.rs | 20 +- crates/nu-command/src/filters/transpose.rs | 2 +- crates/nu-command/src/filters/update.rs | 59 ++--- crates/nu-command/src/filters/upsert.rs | 59 ++--- crates/nu-command/src/filters/values.rs | 8 +- crates/nu-command/src/filters/where_.rs | 2 +- crates/nu-command/src/filters/window.rs | 8 +- crates/nu-command/src/filters/wrap.rs | 4 +- crates/nu-command/src/filters/zip.rs | 2 +- crates/nu-command/src/formats/from/json.rs | 7 +- crates/nu-command/src/formats/from/msgpack.rs | 9 +- crates/nu-command/src/formats/to/text.rs | 6 +- crates/nu-command/src/generators/generate.rs | 2 +- crates/nu-command/src/generators/seq.rs | 55 ++--- crates/nu-command/src/help/help_aliases.rs | 9 +- crates/nu-command/src/help/help_commands.rs | 9 +- crates/nu-command/src/help/help_escapes.rs | 6 +- crates/nu-command/src/help/help_externs.rs | 9 +- crates/nu-command/src/help/help_modules.rs | 9 +- crates/nu-command/src/help/help_operators.rs | 6 +- crates/nu-command/src/math/utils.rs | 2 +- crates/nu-command/src/platform/ansi/ansi_.rs | 10 +- crates/nu-command/src/random/dice.rs | 5 +- crates/nu-command/src/strings/char_.rs | 13 +- .../nu-command/src/strings/detect_columns.rs | 6 +- crates/nu-command/src/strings/parse.rs | 56 ++--- crates/nu-command/src/strings/split/list.rs | 7 +- crates/nu-command/src/system/complete.rs | 2 +- crates/nu-command/src/system/ps.rs | 2 +- .../nu-command/src/system/registry_query.rs | 2 +- crates/nu-command/src/system/run_external.rs | 29 ++- crates/nu-command/src/system/which_.rs | 7 +- crates/nu-command/src/viewers/table.rs | 111 ++++----- crates/nu-explore/src/nu_common/value.rs | 6 +- crates/nu-plugin-core/src/interface/mod.rs | 11 +- crates/nu-plugin-core/src/interface/tests.rs | 45 ++-- crates/nu-plugin-engine/src/interface/mod.rs | 26 +- .../nu-plugin-engine/src/interface/tests.rs | 44 +++- crates/nu-plugin-protocol/src/lib.rs | 1 + crates/nu-plugin-test-support/src/lib.rs | 2 +- .../nu-plugin-test-support/src/plugin_test.rs | 2 +- .../tests/lowercase/mod.rs | 2 +- crates/nu-plugin/src/plugin/interface/mod.rs | 22 +- .../nu-plugin/src/plugin/interface/tests.rs | 33 ++- crates/nu-protocol/src/eval_base.rs | 18 +- .../src/pipeline_data/list_stream.rs | 156 ++++++++++++ crates/nu-protocol/src/pipeline_data/mod.rs | 223 +++++++++--------- .../{stream.rs => raw_stream.rs} | 69 ------ .../src/commands/generate.rs | 6 +- crates/nu_plugin_example/src/commands/seq.rs | 7 +- 106 files changed, 957 insertions(+), 874 deletions(-) create mode 100644 crates/nu-protocol/src/pipeline_data/list_stream.rs rename crates/nu-protocol/src/pipeline_data/{stream.rs => raw_stream.rs} (74%) diff --git a/crates/nu-cli/src/commands/history/history_.rs b/crates/nu-cli/src/commands/history/history_.rs index 4572aaba35..8b0714216e 100644 --- a/crates/nu-cli/src/commands/history/history_.rs +++ b/crates/nu-cli/src/commands/history/history_.rs @@ -107,7 +107,7 @@ impl Command for History { file: history_path.display().to_string(), span: head, })? - .into_pipeline_data(ctrlc)), + .into_pipeline_data(head, ctrlc)), HistoryFileFormat::Sqlite => Ok(history_reader .and_then(|h| { h.search(SearchQuery::everything(SearchDirection::Forward, None)) @@ -122,7 +122,7 @@ impl Command for History { file: history_path.display().to_string(), span: head, })? - .into_pipeline_data(ctrlc)), + .into_pipeline_data(head, ctrlc)), } } } else { diff --git a/crates/nu-cmd-extra/src/extra/filters/each_while.rs b/crates/nu-cmd-extra/src/extra/filters/each_while.rs index 4e9741ef92..2dda815d43 100644 --- a/crates/nu-cmd-extra/src/extra/filters/each_while.rs +++ b/crates/nu-cmd-extra/src/extra/filters/each_while.rs @@ -87,7 +87,7 @@ impl Command for EachWhile { Err(_) => None, }) .fuse() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { @@ -108,7 +108,7 @@ impl Command for EachWhile { } }) .fuse() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } // This match allows non-iterables to be accepted, // which is currently considered undesirable (Nov 2022). diff --git a/crates/nu-cmd-extra/src/extra/filters/update_cells.rs b/crates/nu-cmd-extra/src/extra/filters/update_cells.rs index d117d7fad2..9fe9bfe389 100644 --- a/crates/nu-cmd-extra/src/extra/filters/update_cells.rs +++ b/crates/nu-cmd-extra/src/extra/filters/update_cells.rs @@ -108,7 +108,7 @@ impl Command for UpdateCells { columns, span: head, } - .into_pipeline_data(engine_state.ctrlc.clone()) + .into_pipeline_data(head, engine_state.ctrlc.clone()) .set_metadata(metadata)) } } diff --git a/crates/nu-cmd-extra/src/extra/strings/format/command.rs b/crates/nu-cmd-extra/src/extra/strings/format/command.rs index 437bbc14c9..932b5ccb7f 100644 --- a/crates/nu-cmd-extra/src/extra/strings/format/command.rs +++ b/crates/nu-cmd-extra/src/extra/strings/format/command.rs @@ -238,10 +238,7 @@ fn format( } } - Ok(PipelineData::ListStream( - ListStream::from_stream(list.into_iter(), None), - None, - )) + Ok(ListStream::new(list.into_iter(), head_span, engine_state.ctrlc.clone()).into()) } // Unwrapping this ShellError is a bit unfortunate. // Ideally, its Span would be preserved. diff --git a/crates/nu-cmd-lang/src/core_commands/do_.rs b/crates/nu-cmd-lang/src/core_commands/do_.rs index c2b630e08d..b057880cf3 100644 --- a/crates/nu-cmd-lang/src/core_commands/do_.rs +++ b/crates/nu-cmd-lang/src/core_commands/do_.rs @@ -62,6 +62,7 @@ impl Command for Do { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let block: Closure = call.req(engine_state, caller_stack, 0)?; let rest: Vec = call.rest(engine_state, caller_stack, 1)?; let ignore_all_errors = call.has_flag(engine_state, caller_stack, "ignore-errors")?; @@ -75,7 +76,7 @@ impl Command for Do { let mut callee_stack = caller_stack.captures_to_stack_preserve_out_dest(block.captures); let block = engine_state.get_block(block.block_id); - bind_args_to(&mut callee_stack, &block.signature, rest, call.head)?; + bind_args_to(&mut callee_stack, &block.signature, rest, head)?; let eval_block_with_early_return = get_eval_block_with_early_return(engine_state); let result = eval_block_with_early_return(engine_state, &mut callee_stack, block, input); @@ -117,7 +118,7 @@ impl Command for Do { None, ) }) - .err_span(call.head) + .err_span(head) }) .transpose()?; @@ -148,13 +149,9 @@ impl Command for Do { None }; - let mut exit_code_ctrlc = None; let exit_code: Vec = match exit_code { None => vec![], - Some(exit_code_stream) => { - exit_code_ctrlc.clone_from(&exit_code_stream.ctrlc); - exit_code_stream.into_iter().collect() - } + Some(exit_code_stream) => exit_code_stream.into_iter().collect(), }; if let Some(Value::Int { val: code, .. }) = exit_code.last() { if *code != 0 { @@ -174,10 +171,7 @@ impl Command for Do { span, None, )), - exit_code: Some(ListStream::from_stream( - exit_code.into_iter(), - exit_code_ctrlc, - )), + exit_code: Some(ListStream::new(exit_code.into_iter(), span, None)), span, metadata, trim_end_newline, @@ -205,21 +199,15 @@ impl Command for Do { Ok(PipelineData::Value(Value::Error { .. }, ..)) | Err(_) if ignore_shell_errors => { Ok(PipelineData::empty()) } - Ok(PipelineData::ListStream(ls, metadata)) if ignore_shell_errors => { - // check if there is a `Value::Error` in given list stream first. - let mut values = vec![]; - let ctrlc = ls.ctrlc.clone(); - for v in ls { - if let Value::Error { .. } = v { - values.push(Value::nothing(call.head)); + Ok(PipelineData::ListStream(stream, metadata)) if ignore_shell_errors => { + let stream = stream.map(move |value| { + if let Value::Error { .. } = value { + Value::nothing(head) } else { - values.push(v) + value } - } - Ok(PipelineData::ListStream( - ListStream::from_stream(values.into_iter(), ctrlc), - metadata, - )) + }); + Ok(PipelineData::ListStream(stream, metadata)) } r => r, } diff --git a/crates/nu-cmd-lang/src/core_commands/for_.rs b/crates/nu-cmd-lang/src/core_commands/for_.rs index e4e15e74dc..64e6c0a6ba 100644 --- a/crates/nu-cmd-lang/src/core_commands/for_.rs +++ b/crates/nu-cmd-lang/src/core_commands/for_.rs @@ -1,5 +1,4 @@ use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression}; -use nu_protocol::ListStream; #[derive(Clone)] pub struct For; @@ -88,7 +87,11 @@ impl Command for For { let span = value.span(); match value { Value::List { vals, .. } => { - for (idx, x) in ListStream::from_stream(vals.into_iter(), ctrlc).enumerate() { + for (idx, x) in vals.into_iter().enumerate() { + if nu_utils::ctrl_c::was_pressed(&ctrlc) { + break; + } + // with_env() is used here to ensure that each iteration uses // a different set of environment variables. // Hence, a 'cd' in the first loop won't affect the next loop. diff --git a/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs b/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs index 780d8d5a13..0b8d2d0200 100644 --- a/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs +++ b/crates/nu-cmd-lang/src/core_commands/scope/aliases.rs @@ -26,13 +26,10 @@ impl Command for ScopeAliases { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; - let ctrlc = engine_state.ctrlc.clone(); - + let head = call.head; let mut scope_data = ScopeData::new(engine_state, stack); scope_data.populate_decls(); - - Ok(scope_data.collect_aliases(span).into_pipeline_data(ctrlc)) + Ok(Value::list(scope_data.collect_aliases(head), head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/scope/commands.rs b/crates/nu-cmd-lang/src/core_commands/scope/commands.rs index 5feed1a9ee..6ce0448f4e 100644 --- a/crates/nu-cmd-lang/src/core_commands/scope/commands.rs +++ b/crates/nu-cmd-lang/src/core_commands/scope/commands.rs @@ -26,13 +26,10 @@ impl Command for ScopeCommands { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; - let ctrlc = engine_state.ctrlc.clone(); - + let head = call.head; let mut scope_data = ScopeData::new(engine_state, stack); scope_data.populate_decls(); - - Ok(scope_data.collect_commands(span).into_pipeline_data(ctrlc)) + Ok(Value::list(scope_data.collect_commands(head), head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/scope/externs.rs b/crates/nu-cmd-lang/src/core_commands/scope/externs.rs index 30cdc53f26..187f90206d 100644 --- a/crates/nu-cmd-lang/src/core_commands/scope/externs.rs +++ b/crates/nu-cmd-lang/src/core_commands/scope/externs.rs @@ -26,13 +26,10 @@ impl Command for ScopeExterns { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; - let ctrlc = engine_state.ctrlc.clone(); - + let head = call.head; let mut scope_data = ScopeData::new(engine_state, stack); scope_data.populate_decls(); - - Ok(scope_data.collect_externs(span).into_pipeline_data(ctrlc)) + Ok(Value::list(scope_data.collect_externs(head), head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/scope/modules.rs b/crates/nu-cmd-lang/src/core_commands/scope/modules.rs index 6031121847..9d78f2a061 100644 --- a/crates/nu-cmd-lang/src/core_commands/scope/modules.rs +++ b/crates/nu-cmd-lang/src/core_commands/scope/modules.rs @@ -26,13 +26,10 @@ impl Command for ScopeModules { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; - let ctrlc = engine_state.ctrlc.clone(); - + let head = call.head; let mut scope_data = ScopeData::new(engine_state, stack); scope_data.populate_modules(); - - Ok(scope_data.collect_modules(span).into_pipeline_data(ctrlc)) + Ok(Value::list(scope_data.collect_modules(head), head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-lang/src/core_commands/scope/variables.rs b/crates/nu-cmd-lang/src/core_commands/scope/variables.rs index 7f44289fb4..6c9a695c71 100644 --- a/crates/nu-cmd-lang/src/core_commands/scope/variables.rs +++ b/crates/nu-cmd-lang/src/core_commands/scope/variables.rs @@ -26,13 +26,10 @@ impl Command for ScopeVariables { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; - let ctrlc = engine_state.ctrlc.clone(); - + let head = call.head; let mut scope_data = ScopeData::new(engine_state, stack); scope_data.populate_vars(); - - Ok(scope_data.collect_vars(span).into_pipeline_data(ctrlc)) + Ok(Value::list(scope_data.collect_vars(head), head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-cmd-plugin/src/commands/plugin/list.rs b/crates/nu-cmd-plugin/src/commands/plugin/list.rs index 1d630b67c0..6b715a0001 100644 --- a/crates/nu-cmd-plugin/src/commands/plugin/list.rs +++ b/crates/nu-cmd-plugin/src/commands/plugin/list.rs @@ -69,35 +69,47 @@ impl Command for PluginList { call: &Call, _input: PipelineData, ) -> Result { - let span = call.span(); + let head = call.head; + // Group plugin decls by plugin identity let decls = engine_state.plugin_decls().into_group_map_by(|decl| { decl.plugin_identity() .expect("plugin decl should have identity") }); + // Build plugins list let list = engine_state.plugins().iter().map(|plugin| { // Find commands that belong to the plugin let commands = decls.get(plugin.identity()) .into_iter() .flat_map(|decls| { - decls.iter().map(|decl| Value::string(decl.name(), span)) + decls.iter().map(|decl| Value::string(decl.name(), head)) }) .collect(); - Value::record(record! { - "name" => Value::string(plugin.identity().name(), span), - "is_running" => Value::bool(plugin.is_running(), span), - "pid" => plugin.pid() - .map(|p| Value::int(p as i64, span)) - .unwrap_or(Value::nothing(span)), - "filename" => Value::string(plugin.identity().filename().to_string_lossy(), span), - "shell" => plugin.identity().shell() - .map(|s| Value::string(s.to_string_lossy(), span)) - .unwrap_or(Value::nothing(span)), - "commands" => Value::list(commands, span), - }, span) - }).collect::>(); - Ok(list.into_pipeline_data(engine_state.ctrlc.clone())) + let pid = plugin + .pid() + .map(|p| Value::int(p as i64, head)) + .unwrap_or(Value::nothing(head)); + + let shell = plugin + .identity() + .shell() + .map(|s| Value::string(s.to_string_lossy(), head)) + .unwrap_or(Value::nothing(head)); + + let record = record! { + "name" => Value::string(plugin.identity().name(), head), + "is_running" => Value::bool(plugin.is_running(), head), + "pid" => pid, + "filename" => Value::string(plugin.identity().filename().to_string_lossy(), head), + "shell" => shell, + "commands" => Value::list(commands, head), + }; + + Value::record(record, head) + }).collect(); + + Ok(Value::list(list, head).into_pipeline_data()) } } diff --git a/crates/nu-command/src/conversions/into/cell_path.rs b/crates/nu-command/src/conversions/into/cell_path.rs index 039656e9d6..4faa6e83d6 100644 --- a/crates/nu-command/src/conversions/into/cell_path.rs +++ b/crates/nu-command/src/conversions/into/cell_path.rs @@ -98,7 +98,7 @@ fn into_cell_path(call: &Call, input: PipelineData) -> Result Ok(value_to_cell_path(&value, head)?.into_pipeline_data()), PipelineData::ListStream(stream, ..) => { - let list: Vec<_> = stream.collect(); + let list: Vec<_> = stream.into_iter().collect(); Ok(list_to_cell_path(&list, head)?.into_pipeline_data()) } PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType { diff --git a/crates/nu-command/src/conversions/into/value.rs b/crates/nu-command/src/conversions/into/value.rs index 6021a4980a..4bf7e68f53 100644 --- a/crates/nu-command/src/conversions/into/value.rs +++ b/crates/nu-command/src/conversions/into/value.rs @@ -81,7 +81,7 @@ impl Command for IntoValue { display_as_filesizes, span, } - .into_pipeline_data(ctrlc) + .into_pipeline_data(span, ctrlc) .set_metadata(metadata)) } } diff --git a/crates/nu-command/src/database/commands/into_sqlite.rs b/crates/nu-command/src/database/commands/into_sqlite.rs index 7f61b6bc06..f3a2e3622a 100644 --- a/crates/nu-command/src/database/commands/into_sqlite.rs +++ b/crates/nu-command/src/database/commands/into_sqlite.rs @@ -203,8 +203,8 @@ fn action( ctrl_c: Option>, ) -> Result { match input { - PipelineData::ListStream(list_stream, _) => { - insert_in_transaction(list_stream.stream, span, table, ctrl_c) + PipelineData::ListStream(stream, _) => { + insert_in_transaction(stream.into_iter(), span, table, ctrl_c) } PipelineData::Value( Value::List { diff --git a/crates/nu-command/src/date/list_timezone.rs b/crates/nu-command/src/date/list_timezone.rs index bb56cb995d..6f9267947d 100644 --- a/crates/nu-command/src/date/list_timezone.rs +++ b/crates/nu-command/src/date/list_timezone.rs @@ -30,17 +30,17 @@ impl Command for SubCommand { call: &Call, _input: PipelineData, ) -> Result { - let span = call.head; + let head = call.head; Ok(TZ_VARIANTS .iter() .map(move |x| { Value::record( - record! { "timezone" => Value::string(x.name(), span) }, - span, + record! { "timezone" => Value::string(x.name(), head) }, + head, ) }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/debug/explain.rs b/crates/nu-command/src/debug/explain.rs index 0abd87b9a3..b451d6916a 100644 --- a/crates/nu-command/src/debug/explain.rs +++ b/crates/nu-command/src/debug/explain.rs @@ -34,16 +34,14 @@ impl Command for Explain { stack: &mut Stack, call: &Call, _input: PipelineData, - ) -> Result { + ) -> Result { + let head = call.head; // This was all delightfully stolen from benchmark :) let capture_block: Closure = call.req(engine_state, stack, 0)?; let block = engine_state.get_block(capture_block.block_id); - let ctrlc = engine_state.ctrlc.clone(); let mut stack = stack.captures_to_stack(capture_block.captures); - - let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head); - - Ok(elements.into_pipeline_data(ctrlc)) + let elements = get_pipeline_elements(engine_state, &mut stack, block, head); + Ok(Value::list(elements, head).into_pipeline_data()) } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/debug/metadata_set.rs b/crates/nu-command/src/debug/metadata_set.rs index 29cb8ab0a2..6608827fda 100644 --- a/crates/nu-command/src/debug/metadata_set.rs +++ b/crates/nu-command/src/debug/metadata_set.rs @@ -47,13 +47,21 @@ impl Command for MetadataSet { let metadata = PipelineMetadata { data_source: DataSource::FilePath(path.into()), }; - Ok(input.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(input.into_pipeline_data_with_metadata( + head, + engine_state.ctrlc.clone(), + metadata, + )) } (None, true) => { let metadata = PipelineMetadata { data_source: DataSource::Ls, }; - Ok(input.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(input.into_pipeline_data_with_metadata( + head, + engine_state.ctrlc.clone(), + metadata, + )) } _ => Err(ShellError::IncorrectValue { msg: "Expected either --datasource-ls(-l) or --datasource-filepath(-f)".to_string(), diff --git a/crates/nu-command/src/filesystem/du.rs b/crates/nu-command/src/filesystem/du.rs index adf648f732..c48a1f7ac1 100644 --- a/crates/nu-command/src/filesystem/du.rs +++ b/crates/nu-command/src/filesystem/du.rs @@ -121,7 +121,7 @@ impl Command for Du { }; Ok( du_for_one_pattern(args, ¤t_dir, tag, engine_state.ctrlc.clone())? - .into_pipeline_data(engine_state.ctrlc.clone()), + .into_pipeline_data(tag, engine_state.ctrlc.clone()), ) } Some(paths) => { @@ -147,7 +147,7 @@ impl Command for Du { Ok(result_iters .into_iter() .flatten() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(tag, engine_state.ctrlc.clone())) } } } diff --git a/crates/nu-command/src/filesystem/glob.rs b/crates/nu-command/src/filesystem/glob.rs index 909dc36837..c5f4bc08b4 100644 --- a/crates/nu-command/src/filesystem/glob.rs +++ b/crates/nu-command/src/filesystem/glob.rs @@ -199,7 +199,7 @@ impl Command for Glob { } }; - Ok(if !not_patterns.is_empty() { + let result = if !not_patterns.is_empty() { let np: Vec<&str> = not_patterns.iter().map(|s| s as &str).collect(); let glob_results = glob .walk_with_behavior( @@ -218,10 +218,7 @@ impl Command for Glob { inner: vec![], })? .flatten(); - let result = glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)?; - result - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone()) + glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span) } else { let glob_results = glob .walk_with_behavior( @@ -232,11 +229,12 @@ impl Command for Glob { }, ) .flatten(); - let result = glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span)?; - result - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone()) - }) + glob_to_value(ctrlc, glob_results, no_dirs, no_files, no_symlinks, span) + }?; + + Ok(result + .into_iter() + .into_pipeline_data(span, engine_state.ctrlc.clone())) } } diff --git a/crates/nu-command/src/filesystem/ls.rs b/crates/nu-command/src/filesystem/ls.rs index 9d8db0a8c6..dd1b9770d2 100644 --- a/crates/nu-command/src/filesystem/ls.rs +++ b/crates/nu-command/src/filesystem/ls.rs @@ -115,10 +115,11 @@ impl Command for Ls { match input_pattern_arg { None => Ok(ls_for_one_pattern(None, args, ctrl_c.clone(), cwd)? .into_pipeline_data_with_metadata( + call_span, + ctrl_c, PipelineMetadata { data_source: DataSource::Ls, }, - ctrl_c, )), Some(pattern) => { let mut result_iters = vec![]; @@ -137,10 +138,11 @@ impl Command for Ls { .into_iter() .flatten() .into_pipeline_data_with_metadata( + call_span, + ctrl_c, PipelineMetadata { data_source: DataSource::Ls, }, - ctrl_c, )) } } diff --git a/crates/nu-command/src/filesystem/open.rs b/crates/nu-command/src/filesystem/open.rs index 63b6aa8f04..23664bb576 100644 --- a/crates/nu-command/src/filesystem/open.rs +++ b/crates/nu-command/src/filesystem/open.rs @@ -209,7 +209,10 @@ impl Command for Open { } else if output.len() == 1 { Ok(output.remove(0)) } else { - Ok(output.into_iter().flatten().into_pipeline_data(ctrlc)) + Ok(output + .into_iter() + .flatten() + .into_pipeline_data(call_span, ctrlc)) } } diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index fe14253982..9b9e88b5ff 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -465,7 +465,7 @@ fn rm( } }) .filter(|x| !matches!(x.get_type(), Type::Nothing)) - .into_pipeline_data(ctrlc) + .into_pipeline_data(span, ctrlc) .print_not_formatted(engine_state, false, true)?; Ok(PipelineData::empty()) diff --git a/crates/nu-command/src/filters/append.rs b/crates/nu-command/src/filters/append.rs index 2ad5c2dbe4..af5bd49283 100644 --- a/crates/nu-command/src/filters/append.rs +++ b/crates/nu-command/src/filters/append.rs @@ -116,7 +116,7 @@ only unwrap the outer list, and leave the variable's contents untouched."# Ok(input .into_iter() .chain(other.into_pipeline_data()) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/columns.rs b/crates/nu-command/src/filters/columns.rs index 44b713e793..b6e15af8df 100644 --- a/crates/nu-command/src/filters/columns.rs +++ b/crates/nu-command/src/filters/columns.rs @@ -62,73 +62,68 @@ impl Command for Columns { fn run( &self, - engine_state: &EngineState, + _engine_state: &EngineState, _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let span = call.head; - getcol(engine_state, span, input) + getcol(call.head, input) } } -fn getcol( - engine_state: &EngineState, - head: Span, - input: PipelineData, -) -> Result { - let ctrlc = engine_state.ctrlc.clone(); +fn getcol(head: Span, input: PipelineData) -> Result { let metadata = input.metadata(); match input { PipelineData::Empty => Ok(PipelineData::Empty), PipelineData::Value(v, ..) => { let span = v.span(); - match v { + let cols = match v { Value::List { vals: input_vals, .. - } => { - let input_cols = get_columns(&input_vals); - Ok(input_cols - .into_iter() - .map(move |x| Value::string(x, span)) - .into_pipeline_data(ctrlc) - .set_metadata(metadata)) - } + } => get_columns(&input_vals) + .into_iter() + .map(move |x| Value::string(x, span)) + .collect(), Value::Custom { val, .. } => { // TODO: should we get CustomValue to expose columns in a more efficient way? // Would be nice to be able to get columns without generating the whole value let input_as_base_value = val.to_base_value(span)?; - let input_cols = get_columns(&[input_as_base_value]); - Ok(input_cols + get_columns(&[input_as_base_value]) .into_iter() .map(move |x| Value::string(x, span)) - .into_pipeline_data(ctrlc) - .set_metadata(metadata)) + .collect() } - Value::Record { val, .. } => Ok(val + Value::Record { val, .. } => val .into_owned() .into_iter() .map(move |(x, _)| Value::string(x, head)) - .into_pipeline_data(ctrlc) - .set_metadata(metadata)), + .collect(), // Propagate errors - Value::Error { error, .. } => Err(*error), - other => Err(ShellError::OnlySupportsThisInputType { - exp_input_type: "record or table".into(), - wrong_type: other.get_type().to_string(), - dst_span: head, - src_span: other.span(), - }), - } + Value::Error { error, .. } => return Err(*error), + other => { + return Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "record or table".into(), + wrong_type: other.get_type().to_string(), + dst_span: head, + src_span: other.span(), + }) + } + }; + + Ok(Value::list(cols, head) + .into_pipeline_data() + .set_metadata(metadata)) } PipelineData::ListStream(stream, ..) => { - let v: Vec<_> = stream.into_iter().collect(); - let input_cols = get_columns(&v); - - Ok(input_cols + let values = stream.into_iter().collect::>(); + let cols = get_columns(&values) .into_iter() - .map(move |x| Value::string(x, head)) - .into_pipeline_data_with_metadata(metadata, ctrlc)) + .map(|s| Value::string(s, head)) + .collect(); + + Ok(Value::list(cols, head) + .into_pipeline_data() + .set_metadata(metadata)) } PipelineData::ExternalStream { .. } => Err(ShellError::OnlySupportsThisInputType { exp_input_type: "record or table".into(), diff --git a/crates/nu-command/src/filters/drop/column.rs b/crates/nu-command/src/filters/drop/column.rs index 3f527bcc14..3354492570 100644 --- a/crates/nu-command/src/filters/drop/column.rs +++ b/crates/nu-command/src/filters/drop/column.rs @@ -90,7 +90,8 @@ fn drop_cols( // is displayed farther to the right. let metadata = input.metadata(); match input { - PipelineData::ListStream(mut stream, ..) => { + PipelineData::ListStream(stream, ..) => { + let mut stream = stream.into_iter(); if let Some(mut first) = stream.next() { let drop_cols = drop_cols_set(&mut first, head, columns)?; @@ -101,7 +102,7 @@ fn drop_cols( Err(e) => Value::error(e, head), } })) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } else { Ok(PipelineData::Empty) } diff --git a/crates/nu-command/src/filters/drop/nth.rs b/crates/nu-command/src/filters/drop/nth.rs index b0858b19cc..a530de5aa1 100644 --- a/crates/nu-command/src/filters/drop/nth.rs +++ b/crates/nu-command/src/filters/drop/nth.rs @@ -100,6 +100,7 @@ impl Command for DropNth { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let metadata = input.metadata(); let number_or_range = extract_int_or_range(engine_state, stack, call)?; @@ -115,7 +116,7 @@ impl Command for DropNth { return Err(ShellError::UnsupportedInput { msg: "float range".into(), input: "value originates from here".into(), - msg_span: call.head, + msg_span: head, input_span: number_or_range.span, }); } @@ -129,7 +130,7 @@ impl Command for DropNth { return Err(ShellError::UnsupportedInput { msg: "drop nth accepts only positive ints".into(), input: "value originates from here".into(), - msg_span: call.head, + msg_span: head, input_span: number_or_range.span, }); } @@ -139,7 +140,7 @@ impl Command for DropNth { msg: "The upper bound needs to be equal or larger to the lower bound" .into(), input: "value originates from here".into(), - msg_span: call.head, + msg_span: head, input_span: number_or_range.span, }); } @@ -154,8 +155,9 @@ impl Command for DropNth { .into_iter() .take(start) .into_pipeline_data_with_metadata( - metadata, + head, engine_state.ctrlc.clone(), + metadata, )) } }; @@ -175,7 +177,7 @@ impl Command for DropNth { rows, current: 0, } - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index d0267b1fce..65d61fd3a8 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -138,7 +138,7 @@ with 'transpose' first."# } } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { @@ -170,7 +170,7 @@ with 'transpose' first."# } } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } // This match allows non-iterables to be accepted, // which is currently considered undesirable (Nov 2022). diff --git a/crates/nu-command/src/filters/empty.rs b/crates/nu-command/src/filters/empty.rs index e75700f26d..fd55921414 100644 --- a/crates/nu-command/src/filters/empty.rs +++ b/crates/nu-command/src/filters/empty.rs @@ -60,10 +60,11 @@ pub fn empty( } }, PipelineData::ListStream(s, ..) => { + let empty = s.into_iter().next().is_none(); if negate { - Ok(Value::bool(s.count() != 0, head).into_pipeline_data()) + Ok(Value::bool(!empty, head).into_pipeline_data()) } else { - Ok(Value::bool(s.count() == 0, head).into_pipeline_data()) + Ok(Value::bool(empty, head).into_pipeline_data()) } } PipelineData::Value(value, ..) => { diff --git a/crates/nu-command/src/filters/enumerate.rs b/crates/nu-command/src/filters/enumerate.rs index e46c873c4b..1034780657 100644 --- a/crates/nu-command/src/filters/enumerate.rs +++ b/crates/nu-command/src/filters/enumerate.rs @@ -50,9 +50,9 @@ impl Command for Enumerate { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let metadata = input.metadata(); let ctrlc = engine_state.ctrlc.clone(); - let span = call.head; Ok(input .into_iter() @@ -60,13 +60,13 @@ impl Command for Enumerate { .map(move |(idx, x)| { Value::record( record! { - "index" => Value::int(idx as i64, span), + "index" => Value::int(idx as i64, head), "item" => x, }, - span, + head, ) }) - .into_pipeline_data_with_metadata(metadata, ctrlc)) + .into_pipeline_data_with_metadata(head, ctrlc, metadata)) } } diff --git a/crates/nu-command/src/filters/every.rs b/crates/nu-command/src/filters/every.rs index a7fc4f1b02..1202b4f7c9 100644 --- a/crates/nu-command/src/filters/every.rs +++ b/crates/nu-command/src/filters/every.rs @@ -78,7 +78,7 @@ impl Command for Every { None } }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/filter.rs b/crates/nu-command/src/filters/filter.rs index 7fe936b4f4..b158dd3be3 100644 --- a/crates/nu-command/src/filters/filter.rs +++ b/crates/nu-command/src/filters/filter.rs @@ -67,7 +67,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."# Some(Value::error(err, span)) } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { @@ -92,7 +92,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."# } } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } // This match allows non-iterables to be accepted, // which is currently considered undesirable (Nov 2022). @@ -108,7 +108,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."# Some(Value::error(err, span)) } } - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } } .map(|data| data.set_metadata(metadata)) diff --git a/crates/nu-command/src/filters/find.rs b/crates/nu-command/src/filters/find.rs index 6efda0d836..b45fe8d810 100644 --- a/crates/nu-command/src/filters/find.rs +++ b/crates/nu-command/src/filters/find.rs @@ -3,7 +3,7 @@ use fancy_regex::Regex; use nu_ansi_term::Style; use nu_color_config::StyleComputer; use nu_engine::command_prelude::*; -use nu_protocol::{Config, ListStream}; +use nu_protocol::Config; use nu_utils::IgnoreCaseExt; #[derive(Clone)] @@ -416,9 +416,9 @@ fn find_with_rest_and_highlight( }, ctrlc, ), - PipelineData::ListStream(stream, metadata) => Ok(ListStream::from_stream( - stream - .map(move |mut x| { + PipelineData::ListStream(stream, metadata) => { + let stream = stream.modify(|iter| { + iter.map(move |mut x| { let span = x.span(); match &mut x { Value::Record { val, .. } => highlight_terms_in_record_with_search_columns( @@ -442,10 +442,11 @@ fn find_with_rest_and_highlight( &cols_to_search_in_filter, invert, ) - }), - ctrlc.clone(), - ) - .into_pipeline_data_with_metadata(metadata, ctrlc)), + }) + }); + + Ok(PipelineData::ListStream(stream, metadata)) + } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: Some(stream), @@ -496,7 +497,7 @@ fn find_with_rest_and_highlight( Err(e) => return Err(e), }; } - Ok(output.into_pipeline_data(ctrlc)) + Ok(output.into_pipeline_data(span, ctrlc)) } } } diff --git a/crates/nu-command/src/filters/first.rs b/crates/nu-command/src/filters/first.rs index eabd370858..1bc51f2562 100644 --- a/crates/nu-command/src/filters/first.rs +++ b/crates/nu-command/src/filters/first.rs @@ -143,7 +143,7 @@ fn first_helper( } else { Ok(iter .take(rows) - .into_pipeline_data_with_metadata(metadata, ctrlc)) + .into_pipeline_data_with_metadata(span, ctrlc, metadata)) } } // Propagate errors by explicitly matching them before the final case. @@ -156,17 +156,18 @@ fn first_helper( }), } } - PipelineData::ListStream(mut ls, metadata) => { + PipelineData::ListStream(stream, metadata) => { if return_single_element { - if let Some(v) = ls.next() { + if let Some(v) = stream.into_iter().next() { Ok(v.into_pipeline_data()) } else { Err(ShellError::AccessEmptyContent { span: head }) } } else { - Ok(ls - .take(rows) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(PipelineData::ListStream( + stream.modify(|iter| iter.take(rows)), + metadata, + )) } } PipelineData::ExternalStream { span, .. } => Err(ShellError::OnlySupportsThisInputType { diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index 5772ec2f11..c6232b80fc 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -89,7 +89,7 @@ If multiple cell paths are given, this will produce a list of values."# output.push(val?); } - Ok(output.into_iter().into_pipeline_data(ctrlc)) + Ok(output.into_iter().into_pipeline_data(span, ctrlc)) } .map(|x| x.set_metadata(metadata)) } diff --git a/crates/nu-command/src/filters/group.rs b/crates/nu-command/src/filters/group.rs index 196d2f79c8..821f35f34e 100644 --- a/crates/nu-command/src/filters/group.rs +++ b/crates/nu-command/src/filters/group.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use nu_protocol::ValueIterator; #[derive(Clone)] pub struct Group; @@ -52,6 +53,7 @@ impl Command for Group { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let group_size: Spanned = call.req(engine_state, stack, 0)?; let ctrlc = engine_state.ctrlc.clone(); let metadata = input.metadata(); @@ -61,16 +63,16 @@ impl Command for Group { let each_group_iterator = EachGroupIterator { group_size: group_size.item, input: Box::new(input.into_iter()), - span: call.head, + span: head, }; - Ok(each_group_iterator.into_pipeline_data_with_metadata(metadata, ctrlc)) + Ok(each_group_iterator.into_pipeline_data_with_metadata(head, ctrlc, metadata)) } } struct EachGroupIterator { group_size: usize, - input: Box + Send>, + input: ValueIterator, span: Span, } diff --git a/crates/nu-command/src/filters/insert.rs b/crates/nu-command/src/filters/insert.rs index 7814bcdb83..c87a2a78b9 100644 --- a/crates/nu-command/src/filters/insert.rs +++ b/crates/nu-command/src/filters/insert.rs @@ -159,7 +159,7 @@ fn insert( } Ok(value.into_pipeline_data_with_metadata(metadata)) } - PipelineData::ListStream(mut stream, metadata) => { + PipelineData::ListStream(stream, metadata) => { if let Some(( &PathMember::Int { val, @@ -169,6 +169,7 @@ fn insert( path, )) = cell_path.members.split_first() { + let mut stream = stream.into_iter(); let mut pre_elems = vec![]; for idx in 0..val { @@ -221,40 +222,39 @@ fn insert( Ok(pre_elems .into_iter() .chain(stream) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } else if let Value::Closure { val, .. } = replacement { let mut closure = ClosureEval::new(engine_state, stack, val); - Ok(stream - .map(move |mut value| { - let err = insert_value_by_closure( - &mut value, - &mut closure, - head, - &cell_path.members, - false, - ); + let stream = stream.map(move |mut value| { + let err = insert_value_by_closure( + &mut value, + &mut closure, + head, + &cell_path.members, + false, + ); - if let Err(e) = err { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + if let Err(e) = err { + Value::error(e, head) + } else { + value + } + }); + Ok(PipelineData::ListStream(stream, metadata)) } else { - Ok(stream - .map(move |mut value| { - if let Err(e) = value.insert_data_at_cell_path( - &cell_path.members, - replacement.clone(), - head, - ) { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + let stream = stream.map(move |mut value| { + if let Err(e) = value.insert_data_at_cell_path( + &cell_path.members, + replacement.clone(), + head, + ) { + Value::error(e, head) + } else { + value + } + }); + + Ok(PipelineData::ListStream(stream, metadata)) } } PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { diff --git a/crates/nu-command/src/filters/interleave.rs b/crates/nu-command/src/filters/interleave.rs index 3365b108db..85a92741a1 100644 --- a/crates/nu-command/src/filters/interleave.rs +++ b/crates/nu-command/src/filters/interleave.rs @@ -147,7 +147,7 @@ interleave // Now that threads are writing to the channel, we just return it as a stream Ok(rx .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } } diff --git a/crates/nu-command/src/filters/items.rs b/crates/nu-command/src/filters/items.rs index 5a97a5a3db..f0cba01888 100644 --- a/crates/nu-command/src/filters/items.rs +++ b/crates/nu-command/src/filters/items.rs @@ -66,7 +66,7 @@ impl Command for Items { } } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(head, engine_state.ctrlc.clone())) } Value::Error { error, .. } => Err(*error), other => Err(ShellError::OnlySupportsThisInputType { diff --git a/crates/nu-command/src/filters/lines.rs b/crates/nu-command/src/filters/lines.rs index 0a07378afb..e3e0f5d9fd 100644 --- a/crates/nu-command/src/filters/lines.rs +++ b/crates/nu-command/src/filters/lines.rs @@ -52,9 +52,8 @@ impl Command for Lines { } PipelineData::Empty => Ok(PipelineData::Empty), PipelineData::ListStream(stream, metadata) => { - let iter = stream - .into_iter() - .filter_map(move |value| { + let stream = stream.modify(|iter| { + iter.filter_map(move |value| { let span = value.span(); if let Value::String { val, .. } = value { Some( @@ -72,11 +71,10 @@ impl Command for Lines { None } }) - .flatten(); + .flatten() + }); - Ok(iter - .into_pipeline_data(engine_state.ctrlc.clone()) - .set_metadata(metadata)) + Ok(PipelineData::ListStream(stream, metadata)) } PipelineData::Value(val, ..) => { match val { @@ -97,7 +95,7 @@ impl Command for Lines { .. } => Ok(RawStreamLinesAdapter::new(stream, head, skip_empty) .map(move |x| x.unwrap_or_else(|err| Value::error(err, head))) - .into_pipeline_data(ctrlc) + .into_pipeline_data(head, ctrlc) .set_metadata(metadata)), } } diff --git a/crates/nu-command/src/filters/merge.rs b/crates/nu-command/src/filters/merge.rs index 5af331bf0c..8a3e613c56 100644 --- a/crates/nu-command/src/filters/merge.rs +++ b/crates/nu-command/src/filters/merge.rs @@ -85,11 +85,10 @@ repeating this process with row 1, and so on."# call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let merge_value: Value = call.req(engine_state, stack, 0)?; - let metadata = input.metadata(); let ctrlc = engine_state.ctrlc.clone(); - let call = call.clone(); match (&input, merge_value) { // table (list of records) @@ -104,29 +103,25 @@ repeating this process with row 1, and so on."# .into_iter() .map(move |inp| match (inp.as_record(), table_iter.next()) { (Ok(inp), Some(to_merge)) => match to_merge.as_record() { - Ok(to_merge) => Value::record(do_merge(inp, to_merge), call.head), - Err(error) => Value::error(error, call.head), + Ok(to_merge) => Value::record(do_merge(inp, to_merge), head), + Err(error) => Value::error(error, head), }, (_, None) => inp, - (Err(error), _) => Value::error(error, call.head), + (Err(error), _) => Value::error(error, head), }); - if let Some(md) = metadata { - Ok(res.into_pipeline_data_with_metadata(md, ctrlc)) - } else { - Ok(res.into_pipeline_data(ctrlc)) - } + Ok(res.into_pipeline_data_with_metadata(head, ctrlc, metadata)) } // record ( PipelineData::Value(Value::Record { val: inp, .. }, ..), Value::Record { val: to_merge, .. }, - ) => Ok(Value::record(do_merge(inp, &to_merge), call.head).into_pipeline_data()), + ) => Ok(Value::record(do_merge(inp, &to_merge), head).into_pipeline_data()), (PipelineData::Value(val, ..), ..) => { // Only point the "value originates here" arrow at the merge value // if it was generated from a block. Otherwise, point at the pipeline value. -Leon 2022-10-27 let span = if val.span() == Span::test_data() { - Span::new(call.head.start, call.head.start) + Span::new(head.start, head.start) } else { val.span() }; @@ -134,14 +129,14 @@ repeating this process with row 1, and so on."# Err(ShellError::PipelineMismatch { exp_input_type: "input, and argument, to be both record or both table" .to_string(), - dst_span: call.head, + dst_span: head, src_span: span, }) } _ => Err(ShellError::PipelineMismatch { exp_input_type: "input, and argument, to be both record or both table".to_string(), - dst_span: call.head, - src_span: Span::new(call.head.start, call.head.start), + dst_span: head, + src_span: Span::new(head.start, head.start), }), } } diff --git a/crates/nu-command/src/filters/move_.rs b/crates/nu-command/src/filters/move_.rs index ab2f8c55cd..d93368f291 100644 --- a/crates/nu-command/src/filters/move_.rs +++ b/crates/nu-command/src/filters/move_.rs @@ -109,6 +109,7 @@ impl Command for Move { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let columns: Vec = call.rest(engine_state, stack, 0)?; let after: Option = call.get_flag(engine_state, stack, "after")?; let before: Option = call.get_flag(engine_state, stack, "before")?; @@ -126,7 +127,7 @@ impl Command for Move { return Err(ShellError::GenericError { error: "Cannot move columns".into(), msg: "Use either --after, or --before, not both".into(), - span: Some(call.head), + span: Some(head), help: None, inner: vec![], }) @@ -135,7 +136,7 @@ impl Command for Move { return Err(ShellError::GenericError { error: "Cannot move columns".into(), msg: "Missing --after or --before flag".into(), - span: Some(call.head), + span: Some(head), help: None, inner: vec![], }) @@ -144,36 +145,29 @@ impl Command for Move { let metadata = input.metadata(); let ctrlc = engine_state.ctrlc.clone(); - let call = call.clone(); match input { PipelineData::Value(Value::List { .. }, ..) | PipelineData::ListStream { .. } => { let res = input.into_iter().map(move |x| match x.as_record() { Ok(record) => { - match move_record_columns(record, &columns, &before_or_after, call.head) { + match move_record_columns(record, &columns, &before_or_after, head) { Ok(val) => val, - Err(error) => Value::error(error, call.head), + Err(error) => Value::error(error, head), } } - Err(error) => Value::error(error, call.head), + Err(error) => Value::error(error, head), }); - if let Some(md) = metadata { - Ok(res.into_pipeline_data_with_metadata(md, ctrlc)) - } else { - Ok(res.into_pipeline_data(ctrlc)) - } + Ok(res.into_pipeline_data_with_metadata(head, ctrlc, metadata)) } PipelineData::Value(Value::Record { val, .. }, ..) => { - Ok( - move_record_columns(&val, &columns, &before_or_after, call.head)? - .into_pipeline_data(), - ) + Ok(move_record_columns(&val, &columns, &before_or_after, head)? + .into_pipeline_data()) } _ => Err(ShellError::PipelineMismatch { exp_input_type: "record or table".to_string(), - dst_span: call.head, - src_span: Span::new(call.head.start, call.head.start), + dst_span: head, + src_span: Span::new(head.start, head.start), }), } } diff --git a/crates/nu-command/src/filters/par_each.rs b/crates/nu-command/src/filters/par_each.rs index 4f0a07b300..52c3024270 100644 --- a/crates/nu-command/src/filters/par_each.rs +++ b/crates/nu-command/src/filters/par_each.rs @@ -159,7 +159,7 @@ impl Command for ParEach { }) .collect::>(); - apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) + apply_order(vec).into_pipeline_data(span, engine_state.ctrlc.clone()) })), Value::Range { val, .. } => Ok(create_pool(max_threads)?.install(|| { let ctrlc = engine_state.ctrlc.clone(); @@ -186,7 +186,7 @@ impl Command for ParEach { }) .collect::>(); - apply_order(vec).into_pipeline_data(ctrlc) + apply_order(vec).into_pipeline_data(span, ctrlc) })), // This match allows non-iterables to be accepted, // which is currently considered undesirable (Nov 2022). @@ -197,6 +197,7 @@ impl Command for ParEach { } PipelineData::ListStream(stream, ..) => Ok(create_pool(max_threads)?.install(|| { let vec = stream + .into_iter() .enumerate() .par_bridge() .map(move |(index, value)| { @@ -216,7 +217,7 @@ impl Command for ParEach { }) .collect::>(); - apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) + apply_order(vec).into_pipeline_data(head, engine_state.ctrlc.clone()) })), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { @@ -241,7 +242,7 @@ impl Command for ParEach { }) .collect::>(); - apply_order(vec).into_pipeline_data(engine_state.ctrlc.clone()) + apply_order(vec).into_pipeline_data(head, engine_state.ctrlc.clone()) })), } .and_then(|x| x.filter(|v| !v.is_nothing(), engine_state.ctrlc.clone())) diff --git a/crates/nu-command/src/filters/prepend.rs b/crates/nu-command/src/filters/prepend.rs index cef8ce8c1a..f017420595 100644 --- a/crates/nu-command/src/filters/prepend.rs +++ b/crates/nu-command/src/filters/prepend.rs @@ -117,7 +117,7 @@ only unwrap the outer list, and leave the variable's contents untouched."# .into_pipeline_data() .into_iter() .chain(input) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/range.rs b/crates/nu-command/src/filters/range.rs index 08d1c0fe42..c89a0b11f2 100644 --- a/crates/nu-command/src/filters/range.rs +++ b/crates/nu-command/src/filters/range.rs @@ -64,6 +64,7 @@ impl Command for Range { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let metadata = input.metadata(); let rows: Spanned = call.req(engine_state, stack, 0)?; @@ -102,20 +103,20 @@ impl Command for Range { }; if from > to { - Ok(PipelineData::Value(Value::nothing(call.head), None)) + Ok(PipelineData::Value(Value::nothing(head), None)) } else { let iter = v.into_iter().skip(from).take(to - from + 1); - Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())) + Ok(iter.into_pipeline_data(head, engine_state.ctrlc.clone())) } } else { let from = start as usize; let to = end as usize; if from > to { - Ok(PipelineData::Value(Value::nothing(call.head), None)) + Ok(PipelineData::Value(Value::nothing(head), None)) } else { let iter = input.into_iter().skip(from).take(to - from + 1); - Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())) + Ok(iter.into_pipeline_data(head, engine_state.ctrlc.clone())) } } .map(|x| x.set_metadata(metadata)) diff --git a/crates/nu-command/src/filters/reverse.rs b/crates/nu-command/src/filters/reverse.rs index db39ee3bd5..f40e5f3be4 100644 --- a/crates/nu-command/src/filters/reverse.rs +++ b/crates/nu-command/src/filters/reverse.rs @@ -59,11 +59,11 @@ impl Command for Reverse { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let metadata = input.metadata(); - - let v: Vec<_> = input.into_iter_strict(call.head)?.collect(); - let iter = v.into_iter().rev(); - Ok(iter.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + let values = input.into_iter_strict(head)?.collect::>(); + let iter = values.into_iter().rev(); + Ok(iter.into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 5b8e9e0420..3514ac6be7 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -215,7 +215,7 @@ fn select( rows: unique_rows.into_iter().peekable(), current: 0, } - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()) + .into_pipeline_data_with_metadata(call_span, engine_state.ctrlc.clone(), metadata) } else { input }; @@ -253,9 +253,11 @@ fn select( } } - Ok(output - .into_iter() - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(output.into_iter().into_pipeline_data_with_metadata( + call_span, + engine_state.ctrlc.clone(), + metadata, + )) } _ => { if !columns.is_empty() { @@ -300,7 +302,11 @@ fn select( } } - Ok(values.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(values.into_pipeline_data_with_metadata( + call_span, + engine_state.ctrlc.clone(), + metadata, + )) } _ => Ok(PipelineData::empty()), } diff --git a/crates/nu-command/src/filters/shuffle.rs b/crates/nu-command/src/filters/shuffle.rs index 598a292e5d..9e023b86c6 100644 --- a/crates/nu-command/src/filters/shuffle.rs +++ b/crates/nu-command/src/filters/shuffle.rs @@ -30,10 +30,10 @@ impl Command for Shuffle { input: PipelineData, ) -> Result { let metadata = input.metadata(); - let mut v: Vec<_> = input.into_iter_strict(call.head)?.collect(); - v.shuffle(&mut thread_rng()); - let iter = v.into_iter(); - Ok(iter.into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + let mut values = input.into_iter_strict(call.head)?.collect::>(); + values.shuffle(&mut thread_rng()); + let iter = values.into_iter(); + Ok(iter.into_pipeline_data_with_metadata(call.head, engine_state.ctrlc.clone(), metadata)) } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/filters/skip/skip_.rs b/crates/nu-command/src/filters/skip/skip_.rs index a76e2b706d..1919263aa3 100644 --- a/crates/nu-command/src/filters/skip/skip_.rs +++ b/crates/nu-command/src/filters/skip/skip_.rs @@ -101,7 +101,7 @@ impl Command for Skip { _ => Ok(input .into_iter_strict(call.head)? .skip(n) - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(input_span, ctrlc, metadata)), } } } diff --git a/crates/nu-command/src/filters/skip/skip_until.rs b/crates/nu-command/src/filters/skip/skip_until.rs index b0a4dd4cd9..74deeda84d 100644 --- a/crates/nu-command/src/filters/skip/skip_until.rs +++ b/crates/nu-command/src/filters/skip/skip_until.rs @@ -88,7 +88,7 @@ impl Command for SkipUntil { .map(|data| data.into_value(head).is_false()) .unwrap_or(false) }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/skip/skip_while.rs b/crates/nu-command/src/filters/skip/skip_while.rs index d72bbcd6fc..a832d8f7b1 100644 --- a/crates/nu-command/src/filters/skip/skip_while.rs +++ b/crates/nu-command/src/filters/skip/skip_while.rs @@ -93,7 +93,7 @@ impl Command for SkipWhile { .map(|data| data.into_value(head).is_true()) .unwrap_or(false) }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/sort.rs b/crates/nu-command/src/filters/sort.rs index cc9a72546d..965b997355 100644 --- a/crates/nu-command/src/filters/sort.rs +++ b/crates/nu-command/src/filters/sort.rs @@ -134,10 +134,11 @@ impl Command for Sort { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let reverse = call.has_flag(engine_state, stack, "reverse")?; let insensitive = call.has_flag(engine_state, stack, "ignore-case")?; let natural = call.has_flag(engine_state, stack, "natural")?; - let metadata = &input.metadata(); + let metadata = input.metadata(); let span = input.span().unwrap_or(call.head); match input { @@ -163,18 +164,18 @@ impl Command for Sort { pipe_data => { let mut vec: Vec<_> = pipe_data.into_iter().collect(); - sort(&mut vec, call.head, insensitive, natural)?; + sort(&mut vec, head, insensitive, natural)?; if reverse { vec.reverse() } let iter = vec.into_iter(); - match metadata { - Some(m) => Ok(iter - .into_pipeline_data_with_metadata(m.clone(), engine_state.ctrlc.clone())), - None => Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())), - } + Ok(iter.into_pipeline_data_with_metadata( + head, + engine_state.ctrlc.clone(), + metadata, + )) } } } diff --git a/crates/nu-command/src/filters/sort_by.rs b/crates/nu-command/src/filters/sort_by.rs index 66c1f2b03f..f3f715bc9d 100644 --- a/crates/nu-command/src/filters/sort_by.rs +++ b/crates/nu-command/src/filters/sort_by.rs @@ -78,33 +78,29 @@ impl Command for SortBy { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let columns: Vec = call.rest(engine_state, stack, 0)?; let reverse = call.has_flag(engine_state, stack, "reverse")?; let insensitive = call.has_flag(engine_state, stack, "ignore-case")?; let natural = call.has_flag(engine_state, stack, "natural")?; - let metadata = &input.metadata(); - let mut vec: Vec<_> = input.into_iter_strict(call.head)?.collect(); + let metadata = input.metadata(); + let mut vec: Vec<_> = input.into_iter_strict(head)?.collect(); if columns.is_empty() { return Err(ShellError::MissingParameter { param_name: "columns".into(), - span: call.head, + span: head, }); } - crate::sort(&mut vec, columns, call.head, insensitive, natural)?; + crate::sort(&mut vec, columns, head, insensitive, natural)?; if reverse { vec.reverse() } let iter = vec.into_iter(); - match metadata { - Some(m) => { - Ok(iter.into_pipeline_data_with_metadata(m.clone(), engine_state.ctrlc.clone())) - } - None => Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())), - } + Ok(iter.into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/take/take_.rs b/crates/nu-command/src/filters/take/take_.rs index a5ffe25301..01700420b8 100644 --- a/crates/nu-command/src/filters/take/take_.rs +++ b/crates/nu-command/src/filters/take/take_.rs @@ -42,6 +42,7 @@ impl Command for Take { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let rows_desired: usize = call.req(engine_state, stack, 0)?; let ctrlc = engine_state.ctrlc.clone(); @@ -54,7 +55,7 @@ impl Command for Take { Value::List { vals, .. } => Ok(vals .into_iter() .take(rows_desired) - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), Value::Binary { val, .. } => { let slice: Vec = val.into_iter().take(rows_desired).collect(); Ok(PipelineData::Value(Value::binary(slice, span), metadata)) @@ -62,33 +63,34 @@ impl Command for Take { Value::Range { val, .. } => Ok(val .into_range_iter(span, ctrlc.clone()) .take(rows_desired) - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), // Propagate errors by explicitly matching them before the final case. Value::Error { error, .. } => Err(*error), other => Err(ShellError::OnlySupportsThisInputType { exp_input_type: "list, binary or range".into(), wrong_type: other.get_type().to_string(), - dst_span: call.head, + dst_span: head, src_span: other.span(), }), } } - PipelineData::ListStream(ls, metadata) => Ok(ls - .take(rows_desired) - .into_pipeline_data_with_metadata(metadata, ctrlc)), + PipelineData::ListStream(stream, metadata) => Ok(PipelineData::ListStream( + stream.modify(|iter| iter.take(rows_desired)), + metadata, + )), PipelineData::ExternalStream { span, .. } => { Err(ShellError::OnlySupportsThisInputType { exp_input_type: "list, binary or range".into(), wrong_type: "raw data".into(), - dst_span: call.head, + dst_span: head, src_span: span, }) } PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType { exp_input_type: "list, binary or range".into(), wrong_type: "null".into(), - dst_span: call.head, - src_span: call.head, + dst_span: head, + src_span: head, }), } } diff --git a/crates/nu-command/src/filters/take/take_until.rs b/crates/nu-command/src/filters/take/take_until.rs index 40d2eee019..e3a2a37162 100644 --- a/crates/nu-command/src/filters/take/take_until.rs +++ b/crates/nu-command/src/filters/take/take_until.rs @@ -84,7 +84,7 @@ impl Command for TakeUntil { .map(|data| data.into_value(head).is_false()) .unwrap_or(false) }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/take/take_while.rs b/crates/nu-command/src/filters/take/take_while.rs index 1d2a98ee51..632c165847 100644 --- a/crates/nu-command/src/filters/take/take_while.rs +++ b/crates/nu-command/src/filters/take/take_while.rs @@ -84,7 +84,7 @@ impl Command for TakeWhile { .map(|data| data.into_value(head).is_true()) .unwrap_or(false) }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/filters/tee.rs b/crates/nu-command/src/filters/tee.rs index 5287f44512..319f70905c 100644 --- a/crates/nu-command/src/filters/tee.rs +++ b/crates/nu-command/src/filters/tee.rs @@ -64,6 +64,7 @@ use it in your pipeline."# call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let use_stderr = call.has_flag(engine_state, stack, "stderr")?; let Spanned { @@ -125,7 +126,7 @@ use it in your pipeline."# if use_stderr { let stderr = stderr .map(|stderr| { - let iter = tee(stderr.stream, with_stream).err_span(call.head)?; + let iter = tee(stderr.stream, with_stream).err_span(head)?; Ok::<_, ShellError>(RawStream::new( Box::new(iter.map(flatten_result)), stderr.ctrlc, @@ -145,7 +146,7 @@ use it in your pipeline."# } else { let stdout = stdout .map(|stdout| { - let iter = tee(stdout.stream, with_stream).err_span(call.head)?; + let iter = tee(stdout.stream, with_stream).err_span(head)?; Ok::<_, ShellError>(RawStream::new( Box::new(iter.map(flatten_result)), stdout.ctrlc, @@ -168,15 +169,16 @@ use it in your pipeline."# _ if use_stderr => Err(ShellError::UnsupportedInput { msg: "--stderr can only be used on external streams".into(), input: "the input to `tee` is not an external stream".into(), - msg_span: call.head, - input_span: input.span().unwrap_or(call.head), + msg_span: head, + input_span: input.span().unwrap_or(head), }), // Handle others with the plain iterator _ => { let teed = tee(input.into_iter(), move |rx| { let input_from_channel = rx.into_pipeline_data_with_metadata( - metadata_clone, + head, closure_engine_state.ctrlc.clone(), + metadata_clone, ); let result = eval_block_with_early_return( &closure_engine_state, @@ -187,9 +189,13 @@ use it in your pipeline."# // Make sure to drain any iterator produced to avoid unexpected behavior result.and_then(|data| data.drain()) }) - .err_span(call.head)? + .err_span(head)? .map(move |result| result.unwrap_or_else(|err| Value::error(err, closure_span))) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone()); + .into_pipeline_data_with_metadata( + head, + engine_state.ctrlc.clone(), + metadata, + ); Ok(teed) } diff --git a/crates/nu-command/src/filters/transpose.rs b/crates/nu-command/src/filters/transpose.rs index 9a41457a8f..49caa56d18 100644 --- a/crates/nu-command/src/filters/transpose.rs +++ b/crates/nu-command/src/filters/transpose.rs @@ -284,7 +284,7 @@ pub fn transpose( metadata, )) } else { - Ok(result_data.into_pipeline_data_with_metadata(metadata, ctrlc)) + Ok(result_data.into_pipeline_data_with_metadata(name, ctrlc, metadata)) } } diff --git a/crates/nu-command/src/filters/update.rs b/crates/nu-command/src/filters/update.rs index 76e0674ad8..2cea7deead 100644 --- a/crates/nu-command/src/filters/update.rs +++ b/crates/nu-command/src/filters/update.rs @@ -143,7 +143,7 @@ fn update( } Ok(value.into_pipeline_data_with_metadata(metadata)) } - PipelineData::ListStream(mut stream, metadata) => { + PipelineData::ListStream(stream, metadata) => { if let Some(( &PathMember::Int { val, @@ -153,6 +153,7 @@ fn update( path, )) = cell_path.members.split_first() { + let mut stream = stream.into_iter(); let mut pre_elems = vec![]; for idx in 0..=val { @@ -186,38 +187,38 @@ fn update( Ok(pre_elems .into_iter() .chain(stream) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } else if let Value::Closure { val, .. } = replacement { let mut closure = ClosureEval::new(engine_state, stack, val); - Ok(stream - .map(move |mut value| { - let err = update_value_by_closure( - &mut value, - &mut closure, - head, - &cell_path.members, - false, - ); + let stream = stream.map(move |mut value| { + let err = update_value_by_closure( + &mut value, + &mut closure, + head, + &cell_path.members, + false, + ); - if let Err(e) = err { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + if let Err(e) = err { + Value::error(e, head) + } else { + value + } + }); + + Ok(PipelineData::ListStream(stream, metadata)) } else { - Ok(stream - .map(move |mut value| { - if let Err(e) = - value.update_data_at_cell_path(&cell_path.members, replacement.clone()) - { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + let stream = stream.map(move |mut value| { + if let Err(e) = + value.update_data_at_cell_path(&cell_path.members, replacement.clone()) + { + Value::error(e, head) + } else { + value + } + }); + + Ok(PipelineData::ListStream(stream, metadata)) } } PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { diff --git a/crates/nu-command/src/filters/upsert.rs b/crates/nu-command/src/filters/upsert.rs index e62239f562..b7b4a782f2 100644 --- a/crates/nu-command/src/filters/upsert.rs +++ b/crates/nu-command/src/filters/upsert.rs @@ -189,7 +189,7 @@ fn upsert( } Ok(value.into_pipeline_data_with_metadata(metadata)) } - PipelineData::ListStream(mut stream, metadata) => { + PipelineData::ListStream(stream, metadata) => { if let Some(( &PathMember::Int { val, @@ -199,6 +199,7 @@ fn upsert( path, )) = cell_path.members.split_first() { + let mut stream = stream.into_iter(); let mut pre_elems = vec![]; for idx in 0..val { @@ -246,38 +247,38 @@ fn upsert( Ok(pre_elems .into_iter() .chain(stream) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } else if let Value::Closure { val, .. } = replacement { let mut closure = ClosureEval::new(engine_state, stack, val); - Ok(stream - .map(move |mut value| { - let err = upsert_value_by_closure( - &mut value, - &mut closure, - head, - &cell_path.members, - false, - ); + let stream = stream.map(move |mut value| { + let err = upsert_value_by_closure( + &mut value, + &mut closure, + head, + &cell_path.members, + false, + ); - if let Err(e) = err { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + if let Err(e) = err { + Value::error(e, head) + } else { + value + } + }); + + Ok(PipelineData::ListStream(stream, metadata)) } else { - Ok(stream - .map(move |mut value| { - if let Err(e) = - value.upsert_data_at_cell_path(&cell_path.members, replacement.clone()) - { - Value::error(e, head) - } else { - value - } - }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + let stream = stream.map(move |mut value| { + if let Err(e) = + value.upsert_data_at_cell_path(&cell_path.members, replacement.clone()) + { + Value::error(e, head) + } else { + value + } + }); + + Ok(PipelineData::ListStream(stream, metadata)) } } PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { diff --git a/crates/nu-command/src/filters/values.rs b/crates/nu-command/src/filters/values.rs index 8b35352150..aa576de874 100644 --- a/crates/nu-command/src/filters/values.rs +++ b/crates/nu-command/src/filters/values.rs @@ -144,7 +144,7 @@ fn values( Value::List { vals, .. } => match get_values(&vals, head, span) { Ok(cols) => Ok(cols .into_iter() - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), Err(err) => Err(err), }, Value::Custom { val, .. } => { @@ -152,7 +152,7 @@ fn values( match get_values(&[input_as_base_value], head, span) { Ok(cols) => Ok(cols .into_iter() - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), Err(err) => Err(err), } } @@ -160,7 +160,7 @@ fn values( .values() .cloned() .collect::>() - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), // Propagate errors Value::Error { error, .. } => Err(*error), other => Err(ShellError::OnlySupportsThisInputType { @@ -176,7 +176,7 @@ fn values( match get_values(&vals, head, head) { Ok(cols) => Ok(cols .into_iter() - .into_pipeline_data_with_metadata(metadata, ctrlc)), + .into_pipeline_data_with_metadata(head, ctrlc, metadata)), Err(err) => Err(err), } } diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index cb35bd8876..7507a7ede1 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -61,7 +61,7 @@ not supported."# Ok(data) => data.into_value(head).is_true().then_some(value), Err(err) => Some(Value::error(err, head)), }) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/filters/window.rs b/crates/nu-command/src/filters/window.rs index 5c84ad7e98..5b386b9f84 100644 --- a/crates/nu-command/src/filters/window.rs +++ b/crates/nu-command/src/filters/window.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use nu_protocol::ValueIterator; #[derive(Clone)] pub struct Window; @@ -110,6 +111,7 @@ impl Command for Window { call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let group_size: Spanned = call.req(engine_state, stack, 0)?; let ctrlc = engine_state.ctrlc.clone(); let metadata = input.metadata(); @@ -123,19 +125,19 @@ impl Command for Window { let each_group_iterator = EachWindowIterator { group_size: group_size.item, input: Box::new(input.into_iter()), - span: call.head, + span: head, previous: None, stride, remainder, }; - Ok(each_group_iterator.into_pipeline_data_with_metadata(metadata, ctrlc)) + Ok(each_group_iterator.into_pipeline_data_with_metadata(head, ctrlc, metadata)) } } struct EachWindowIterator { group_size: usize, - input: Box + Send>, + input: ValueIterator, span: Span, previous: Option>, stride: usize, diff --git a/crates/nu-command/src/filters/wrap.rs b/crates/nu-command/src/filters/wrap.rs index a5ccf9eed2..24ce8e6821 100644 --- a/crates/nu-command/src/filters/wrap.rs +++ b/crates/nu-command/src/filters/wrap.rs @@ -42,9 +42,9 @@ impl Command for Wrap { | PipelineData::ListStream { .. } => Ok(input .into_iter() .map(move |x| Value::record(record! { name.clone() => x }, span)) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())), + .into_pipeline_data_with_metadata(span, engine_state.ctrlc.clone(), metadata)), PipelineData::ExternalStream { .. } => Ok(Value::record( - record! { name => input.into_value(call.head) }, + record! { name => input.into_value(span) }, span, ) .into_pipeline_data_with_metadata(metadata)), diff --git a/crates/nu-command/src/filters/zip.rs b/crates/nu-command/src/filters/zip.rs index 0a30450091..f4ee739f50 100644 --- a/crates/nu-command/src/filters/zip.rs +++ b/crates/nu-command/src/filters/zip.rs @@ -112,7 +112,7 @@ impl Command for Zip { .into_iter() .zip(other) .map(move |(x, y)| Value::list(vec![x, y], head)) - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + .into_pipeline_data_with_metadata(head, engine_state.ctrlc.clone(), metadata)) } } diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index 5baaea30dd..44f127152f 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -84,8 +84,11 @@ impl Command for FromJson { .collect() }; - Ok(converted_lines - .into_pipeline_data_with_metadata(metadata, engine_state.ctrlc.clone())) + Ok(converted_lines.into_pipeline_data_with_metadata( + span, + engine_state.ctrlc.clone(), + metadata, + )) } else if strict { Ok(convert_string_to_value_strict(&string_input, span)? .into_pipeline_data_with_metadata(metadata)) diff --git a/crates/nu-command/src/formats/from/msgpack.rs b/crates/nu-command/src/formats/from/msgpack.rs index 0311ecfd1a..75f2be2056 100644 --- a/crates/nu-command/src/formats/from/msgpack.rs +++ b/crates/nu-command/src/formats/from/msgpack.rs @@ -109,10 +109,9 @@ MessagePack: https://msgpack.org/ call: &Call, input: PipelineData, ) -> Result { - let span = input.span().unwrap_or(call.head); let objects = call.has_flag(engine_state, stack, "objects")?; let opts = Opts { - span, + span: call.head, objects, ctrlc: engine_state.ctrlc.clone(), }; @@ -126,10 +125,10 @@ MessagePack: https://msgpack.org/ stdout: Some(raw_stream), .. } => read_msgpack(ReadRawStream::new(raw_stream), opts), - _ => Err(ShellError::PipelineMismatch { + input => Err(ShellError::PipelineMismatch { exp_input_type: "binary".into(), dst_span: call.head, - src_span: span, + src_span: input.span().unwrap_or(call.head), }), } } @@ -257,7 +256,7 @@ pub(crate) fn read_msgpack( None } }) - .into_pipeline_data(ctrlc)) + .into_pipeline_data(span, ctrlc)) } else { // Read a single value and then make sure it's EOF let result = read_value(&mut input, span, 0)?; diff --git a/crates/nu-command/src/formats/to/text.rs b/crates/nu-command/src/formats/to/text.rs index 2515ca5f92..7c12dc2821 100644 --- a/crates/nu-command/src/formats/to/text.rs +++ b/crates/nu-command/src/formats/to/text.rs @@ -1,6 +1,6 @@ use chrono_humanize::HumanTime; use nu_engine::command_prelude::*; -use nu_protocol::{format_duration, format_filesize_from_conf, Config, ListStream, RawStream}; +use nu_protocol::{format_duration, format_filesize_from_conf, Config, RawStream, ValueIterator}; #[derive(Clone)] pub struct ToText; @@ -41,7 +41,7 @@ impl Command for ToText { Ok(PipelineData::ExternalStream { stdout: Some(RawStream::new( Box::new(ListStreamIterator { - stream, + stream: stream.into_inner(), separator: line_ending.into(), config: config.clone(), }), @@ -86,7 +86,7 @@ impl Command for ToText { } struct ListStreamIterator { - stream: ListStream, + stream: ValueIterator, separator: String, config: Config, } diff --git a/crates/nu-command/src/generators/generate.rs b/crates/nu-command/src/generators/generate.rs index 96343fd093..0a01b79c08 100644 --- a/crates/nu-command/src/generators/generate.rs +++ b/crates/nu-command/src/generators/generate.rs @@ -183,7 +183,7 @@ used as the next argument to the closure, otherwise generation stops. Ok(iter .flatten() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(call.head, engine_state.ctrlc.clone())) } } diff --git a/crates/nu-command/src/generators/seq.rs b/crates/nu-command/src/generators/seq.rs index f43454b691..359d479ca0 100644 --- a/crates/nu-command/src/generators/seq.rs +++ b/crates/nu-command/src/generators/seq.rs @@ -1,4 +1,5 @@ use nu_engine::command_prelude::*; +use nu_protocol::ListStream; #[derive(Clone)] pub struct Seq; @@ -119,36 +120,32 @@ pub fn run_seq( let step = if free.len() > 2 { free[1] } else { 1.0 }; let last = { free[free.len() - 1] }; - if !contains_decimals { - // integers only - Ok(PipelineData::ListStream( - nu_protocol::ListStream::from_stream( - IntSeq { - count: first as i64, - step: step as i64, - last: last as i64, - span, - }, - engine_state.ctrlc.clone(), - ), - None, - )) + let stream = if !contains_decimals { + ListStream::new( + IntSeq { + count: first as i64, + step: step as i64, + last: last as i64, + span, + }, + span, + engine_state.ctrlc.clone(), + ) } else { - // floats - Ok(PipelineData::ListStream( - nu_protocol::ListStream::from_stream( - FloatSeq { - first, - step, - last, - index: 0, - span, - }, - engine_state.ctrlc.clone(), - ), - None, - )) - } + ListStream::new( + FloatSeq { + first, + step, + last, + index: 0, + span, + }, + span, + engine_state.ctrlc.clone(), + ) + }; + + Ok(stream.into()) } struct FloatSeq { diff --git a/crates/nu-command/src/help/help_aliases.rs b/crates/nu-command/src/help/help_aliases.rs index f97084bb51..2cc7c7f073 100644 --- a/crates/nu-command/src/help/help_aliases.rs +++ b/crates/nu-command/src/help/help_aliases.rs @@ -92,17 +92,12 @@ pub fn help_aliases( &highlight_style, )?; - return Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())); + return Ok(Value::list(found_cmds_vec, head).into_pipeline_data()); } if rest.is_empty() { let found_cmds_vec = build_help_aliases(engine_state, stack, head); - - Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(found_cmds_vec, head).into_pipeline_data()) } else { let mut name = String::new(); diff --git a/crates/nu-command/src/help/help_commands.rs b/crates/nu-command/src/help/help_commands.rs index 128c838efd..bc508b249b 100644 --- a/crates/nu-command/src/help/help_commands.rs +++ b/crates/nu-command/src/help/help_commands.rs @@ -72,17 +72,12 @@ pub fn help_commands( &highlight_style, )?; - return Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())); + return Ok(Value::list(found_cmds_vec, head).into_pipeline_data()); } if rest.is_empty() { let found_cmds_vec = build_help_commands(engine_state, head); - - Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(found_cmds_vec, head).into_pipeline_data()) } else { let mut name = String::new(); diff --git a/crates/nu-command/src/help/help_escapes.rs b/crates/nu-command/src/help/help_escapes.rs index 73a83f1175..212cbb58bf 100644 --- a/crates/nu-command/src/help/help_escapes.rs +++ b/crates/nu-command/src/help/help_escapes.rs @@ -21,7 +21,7 @@ impl Command for HelpEscapes { fn run( &self, - engine_state: &EngineState, + _engine_state: &EngineState, _stack: &mut Stack, call: &Call, _input: PipelineData, @@ -40,9 +40,7 @@ impl Command for HelpEscapes { )); } - Ok(recs - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(recs, call.head).into_pipeline_data()) } } diff --git a/crates/nu-command/src/help/help_externs.rs b/crates/nu-command/src/help/help_externs.rs index 3aad5b27fe..624a8d8060 100644 --- a/crates/nu-command/src/help/help_externs.rs +++ b/crates/nu-command/src/help/help_externs.rs @@ -92,17 +92,12 @@ pub fn help_externs( &highlight_style, )?; - return Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())); + return Ok(Value::list(found_cmds_vec, head).into_pipeline_data()); } if rest.is_empty() { let found_cmds_vec = build_help_externs(engine_state, stack, head); - - Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(found_cmds_vec, head).into_pipeline_data()) } else { let mut name = String::new(); diff --git a/crates/nu-command/src/help/help_modules.rs b/crates/nu-command/src/help/help_modules.rs index e51b52154b..f2ddf55f1d 100644 --- a/crates/nu-command/src/help/help_modules.rs +++ b/crates/nu-command/src/help/help_modules.rs @@ -98,17 +98,12 @@ pub fn help_modules( &highlight_style, )?; - return Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())); + return Ok(Value::list(found_cmds_vec, head).into_pipeline_data()); } if rest.is_empty() { let found_cmds_vec = build_help_modules(engine_state, stack, head); - - Ok(found_cmds_vec - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(found_cmds_vec, head).into_pipeline_data()) } else { let mut name = String::new(); diff --git a/crates/nu-command/src/help/help_operators.rs b/crates/nu-command/src/help/help_operators.rs index 72c9e752e9..a7beee3dd5 100644 --- a/crates/nu-command/src/help/help_operators.rs +++ b/crates/nu-command/src/help/help_operators.rs @@ -21,7 +21,7 @@ impl Command for HelpOperators { fn run( &self, - engine_state: &EngineState, + _engine_state: &EngineState, _stack: &mut Stack, call: &Call, _input: PipelineData, @@ -43,9 +43,7 @@ impl Command for HelpOperators { )); } - Ok(recs - .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + Ok(Value::list(recs, head).into_pipeline_data()) } } diff --git a/crates/nu-command/src/math/utils.rs b/crates/nu-command/src/math/utils.rs index 9abcce06e9..9d2c15e15f 100644 --- a/crates/nu-command/src/math/utils.rs +++ b/crates/nu-command/src/math/utils.rs @@ -69,7 +69,7 @@ pub fn calculate( let span = values.span().unwrap_or(name); match values { PipelineData::ListStream(s, ..) => { - helper_for_tables(&s.collect::>(), span, name, mf) + helper_for_tables(&s.into_iter().collect::>(), span, name, mf) } PipelineData::Value(Value::List { ref vals, .. }, ..) => match &vals[..] { [Value::Record { .. }, _end @ ..] => helper_for_tables( diff --git a/crates/nu-command/src/platform/ansi/ansi_.rs b/crates/nu-command/src/platform/ansi/ansi_.rs index e4f2bca378..427c7c3a73 100644 --- a/crates/nu-command/src/platform/ansi/ansi_.rs +++ b/crates/nu-command/src/platform/ansi/ansi_.rs @@ -660,7 +660,7 @@ Operating system commands: let ctrlc = engine_state.ctrlc.clone(); if list { - return generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring); + return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring)); } // The code can now be one of the ansi abbreviations like green_bold @@ -694,7 +694,7 @@ Operating system commands: let ctrlc = working_set.permanent().ctrlc.clone(); if list { - return generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring); + return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring)); } // The code can now be one of the ansi abbreviations like green_bold @@ -833,8 +833,8 @@ fn generate_ansi_code_list( ctrlc: Option>, call_span: Span, use_ansi_coloring: bool, -) -> Result { - return Ok(CODE_LIST +) -> PipelineData { + CODE_LIST .iter() .enumerate() .map(move |(i, ansi_code)| { @@ -865,7 +865,7 @@ fn generate_ansi_code_list( Value::record(record, call_span) }) - .into_pipeline_data(ctrlc)); + .into_pipeline_data(call_span, ctrlc) } fn build_ansi_hashmap(v: &[AnsiCode]) -> HashMap<&str, &str> { diff --git a/crates/nu-command/src/random/dice.rs b/crates/nu-command/src/random/dice.rs index b0569c697e..2fb659ad1e 100644 --- a/crates/nu-command/src/random/dice.rs +++ b/crates/nu-command/src/random/dice.rs @@ -78,10 +78,7 @@ fn dice( Value::int(thread_rng.gen_range(1..sides + 1) as i64, span) }); - Ok(PipelineData::ListStream( - ListStream::from_stream(iter, engine_state.ctrlc.clone()), - None, - )) + Ok(ListStream::new(iter, span, engine_state.ctrlc.clone()).into()) } #[cfg(test)] diff --git a/crates/nu-command/src/strings/char_.rs b/crates/nu-command/src/strings/char_.rs index befab1a93d..e227f2667f 100644 --- a/crates/nu-command/src/strings/char_.rs +++ b/crates/nu-command/src/strings/char_.rs @@ -230,7 +230,7 @@ impl Command for Char { // handle -l flag if list { - return generate_character_list(ctrlc, call.head); + return Ok(generate_character_list(ctrlc, call.head)); } // handle -i flag @@ -265,7 +265,7 @@ impl Command for Char { // handle -l flag if list { - return generate_character_list(ctrlc, call_span); + return Ok(generate_character_list(ctrlc, call_span)); } // handle -i flag @@ -286,11 +286,8 @@ impl Command for Char { } } -fn generate_character_list( - ctrlc: Option>, - call_span: Span, -) -> Result { - Ok(CHAR_MAP +fn generate_character_list(ctrlc: Option>, call_span: Span) -> PipelineData { + CHAR_MAP .iter() .map(move |(name, s)| { let unicode = Value::string( @@ -308,7 +305,7 @@ fn generate_character_list( Value::record(record, call_span) }) - .into_pipeline_data(ctrlc)) + .into_pipeline_data(call_span, ctrlc) } fn handle_integer_flag( diff --git a/crates/nu-command/src/strings/detect_columns.rs b/crates/nu-command/src/strings/detect_columns.rs index 9c33ffa494..74bcf07820 100644 --- a/crates/nu-command/src/strings/detect_columns.rs +++ b/crates/nu-command/src/strings/detect_columns.rs @@ -159,7 +159,7 @@ fn guess_width( Err(e) => Value::error(e, input_span), } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(input_span, engine_state.ctrlc.clone())) } else { let length = result[0].len(); let columns: Vec = (0..length).map(|n| format!("column{n}")).collect(); @@ -184,7 +184,7 @@ fn guess_width( Err(e) => Value::error(e, input_span), } }) - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(input_span, engine_state.ctrlc.clone())) } } @@ -278,7 +278,7 @@ fn detect_columns( None => Value::record(record, name_span), } }) - .into_pipeline_data(ctrlc)) + .into_pipeline_data(call.head, ctrlc)) } else { Ok(PipelineData::empty()) } diff --git a/crates/nu-command/src/strings/parse.rs b/crates/nu-command/src/strings/parse.rs index 658fc20361..8f6d35b0b3 100644 --- a/crates/nu-command/src/strings/parse.rs +++ b/crates/nu-command/src/strings/parse.rs @@ -1,6 +1,6 @@ use fancy_regex::Regex; use nu_engine::command_prelude::*; -use nu_protocol::ListStream; +use nu_protocol::{ListStream, ValueIterator}; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -187,44 +187,36 @@ fn operate( } } - Ok(PipelineData::ListStream( - ListStream::from_stream(parsed.into_iter(), ctrlc), - None, - )) + Ok(ListStream::new(parsed.into_iter(), head, ctrlc).into()) } - PipelineData::ListStream(stream, ..) => Ok(PipelineData::ListStream( - ListStream::from_stream( - ParseStreamer { - span: head, - excess: Vec::new(), - regex: regex_pattern, - columns, - stream: stream.stream, - ctrlc: ctrlc.clone(), - }, + PipelineData::ListStream(stream, ..) => Ok(stream + .modify(|stream| ParseStreamer { + span: head, + excess: Vec::new(), + regex: regex_pattern, + columns, + stream, ctrlc, - ), - None, - )), + }) + .into()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::Empty), PipelineData::ExternalStream { stdout: Some(stream), .. - } => Ok(PipelineData::ListStream( - ListStream::from_stream( - ParseStreamerExternal { - span: head, - excess: Vec::new(), - regex: regex_pattern, - columns, - stream: stream.stream, - }, - ctrlc, - ), - None, - )), + } => Ok(ListStream::new( + ParseStreamerExternal { + span: head, + excess: Vec::new(), + regex: regex_pattern, + columns, + stream: stream.stream, + }, + head, + ctrlc, + ) + .into()), } } @@ -299,7 +291,7 @@ pub struct ParseStreamer { excess: Vec, regex: Regex, columns: Vec, - stream: Box + Send + 'static>, + stream: ValueIterator, ctrlc: Option>, } diff --git a/crates/nu-command/src/strings/split/list.rs b/crates/nu-command/src/strings/split/list.rs index 08bd8fbc61..470ba12ec4 100644 --- a/crates/nu-command/src/strings/split/list.rs +++ b/crates/nu-command/src/strings/split/list.rs @@ -196,9 +196,12 @@ fn split_list( let mut temp_list = Vec::new(); let mut returned_list = Vec::new(); - let iter = input.into_interruptible_iter(engine_state.ctrlc.clone()); let matcher = Matcher::new(call.has_flag(engine_state, stack, "regex")?, separator)?; - for val in iter { + for val in input { + if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) { + break; + } + if matcher.compare(&val)? { if !temp_list.is_empty() { returned_list.push(Value::list(temp_list.clone(), call.head)); diff --git a/crates/nu-command/src/system/complete.rs b/crates/nu-command/src/system/complete.rs index 80dae4d37a..c622c86f3c 100644 --- a/crates/nu-command/src/system/complete.rs +++ b/crates/nu-command/src/system/complete.rs @@ -88,7 +88,7 @@ impl Command for Complete { }; if let Some(exit_code) = exit_code { - let mut v: Vec<_> = exit_code.collect(); + let mut v: Vec<_> = exit_code.into_iter().collect(); if let Some(v) = v.pop() { record.push("exit_code", v); diff --git a/crates/nu-command/src/system/ps.rs b/crates/nu-command/src/system/ps.rs index 11eb66011d..922bf7915b 100644 --- a/crates/nu-command/src/system/ps.rs +++ b/crates/nu-command/src/system/ps.rs @@ -195,5 +195,5 @@ fn run_ps( Ok(output .into_iter() - .into_pipeline_data(engine_state.ctrlc.clone())) + .into_pipeline_data(span, engine_state.ctrlc.clone())) } diff --git a/crates/nu-command/src/system/registry_query.rs b/crates/nu-command/src/system/registry_query.rs index c926ad6aaf..1e2a328356 100644 --- a/crates/nu-command/src/system/registry_query.rs +++ b/crates/nu-command/src/system/registry_query.rs @@ -106,7 +106,7 @@ fn registry_query( *registry_key_span, )) } - Ok(reg_values.into_pipeline_data(engine_state.ctrlc.clone())) + Ok(reg_values.into_pipeline_data(call_span, engine_state.ctrlc.clone())) } else { match registry_value { Some(value) => { diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 734488fd81..e73bd4ab50 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -163,8 +163,6 @@ impl ExternalCommand { ) -> Result { let head = self.name.span; - let ctrlc = engine_state.ctrlc.clone(); - #[allow(unused_mut)] let (cmd, mut reader) = self.create_process(&input, false, head)?; @@ -431,7 +429,7 @@ impl ExternalCommand { ( Some(RawStream::new( Box::new(ByteLines::new(combined)), - ctrlc.clone(), + engine_state.ctrlc.clone(), head, None, )), @@ -439,11 +437,21 @@ impl ExternalCommand { ) } else { let stdout = child.as_mut().stdout.take().map(|out| { - RawStream::new(Box::new(ByteLines::new(out)), ctrlc.clone(), head, None) + RawStream::new( + Box::new(ByteLines::new(out)), + engine_state.ctrlc.clone(), + head, + None, + ) }); let stderr = child.as_mut().stderr.take().map(|err| { - RawStream::new(Box::new(ByteLines::new(err)), ctrlc.clone(), head, None) + RawStream::new( + Box::new(ByteLines::new(err)), + engine_state.ctrlc.clone(), + head, + None, + ) }); if matches!(self.err, OutDest::Pipe) { @@ -505,15 +513,16 @@ impl ExternalCommand { }) .err_span(head)?; - let exit_code_receiver = ValueReceiver::new(exit_code_rx); + let exit_code = Some(ListStream::new( + ValueReceiver::new(exit_code_rx), + head, + None, + )); Ok(PipelineData::ExternalStream { stdout, stderr, - exit_code: Some(ListStream::from_stream( - Box::new(exit_code_receiver), - ctrlc.clone(), - )), + exit_code, span: head, metadata: None, trim_end_newline: true, diff --git a/crates/nu-command/src/system/which_.rs b/crates/nu-command/src/system/which_.rs index f593bcf9fe..1244a57d99 100644 --- a/crates/nu-command/src/system/which_.rs +++ b/crates/nu-command/src/system/which_.rs @@ -214,6 +214,7 @@ fn which( stack: &mut Stack, call: &Call, ) -> Result { + let head = call.head; let which_args = WhichArgs { applications: call.rest(engine_state, stack, 0)?, all: call.has_flag(engine_state, stack, "all")?, @@ -223,7 +224,7 @@ fn which( if which_args.applications.is_empty() { return Err(ShellError::MissingParameter { param_name: "application".into(), - span: call.head, + span: head, }); } @@ -231,7 +232,7 @@ fn which( #[allow(deprecated)] let cwd = env::current_dir_str(engine_state, stack)?; - let paths = env::path_str(engine_state, stack, call.head)?; + let paths = env::path_str(engine_state, stack, head)?; for app in which_args.applications { let values = which_single( @@ -244,7 +245,7 @@ fn which( output.extend(values); } - Ok(output.into_iter().into_pipeline_data(ctrlc)) + Ok(output.into_iter().into_pipeline_data(head, ctrlc)) } #[cfg(test)] diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index e7d2774a5e..f4df2e03bc 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -5,7 +5,9 @@ use lscolors::{LsColors, Style}; use nu_color_config::{color_from_hex, StyleComputer, TextStyle}; use nu_engine::{command_prelude::*, env::get_config, env_to_string}; -use nu_protocol::{Config, DataSource, ListStream, PipelineMetadata, RawStream, TableMode}; +use nu_protocol::{ + Config, DataSource, ListStream, PipelineMetadata, RawStream, TableMode, ValueIterator, +}; use nu_table::{ common::create_nu_table_config, CollapsedTable, ExpandedTable, JustTable, NuTable, NuTableCell, StringResult, TableOpts, TableOutput, @@ -381,7 +383,7 @@ fn handle_table_command( // None of these two receive a StyleComputer because handle_row_stream() can produce it by itself using engine_state and stack. PipelineData::Value(Value::List { vals, .. }, metadata) => { let ctrlc = input.engine_state.ctrlc.clone(); - let stream = ListStream::from_stream(vals.into_iter(), ctrlc); + let stream = ListStream::new(vals.into_iter(), span, ctrlc); input.data = PipelineData::Empty; handle_row_stream(input, cfg, stream, metadata) @@ -405,7 +407,7 @@ fn handle_table_command( } PipelineData::Value(Value::Range { val, .. }, metadata) => { let ctrlc = input.engine_state.ctrlc.clone(); - let stream = ListStream::from_stream(val.into_range_iter(span, ctrlc.clone()), ctrlc); + let stream = ListStream::new(val.into_range_iter(span, ctrlc), span, None); input.data = PipelineData::Empty; handle_row_stream(input, cfg, stream, metadata) } @@ -537,7 +539,6 @@ fn handle_row_stream( data_source: DataSource::Ls, }) => { let config = get_config(input.engine_state, input.stack); - let ctrlc = ctrlc.clone(); let ls_colors_env_str = match input.stack.get_env_var(input.engine_state, "LS_COLORS") { Some(v) => Some(env_to_string( "LS_COLORS", @@ -549,67 +550,55 @@ fn handle_row_stream( }; let ls_colors = get_ls_colors(ls_colors_env_str); - ListStream::from_stream( - stream.map(move |mut x| match &mut x { - Value::Record { val: record, .. } => { - // Only the name column gets special colors, for now - if let Some(value) = record.to_mut().get_mut("name") { - let span = value.span(); - if let Value::String { val, .. } = value { - if let Some(val) = render_path_name(val, &config, &ls_colors, span) - { - *value = val; - } + stream.map(move |mut value| { + if let Value::Record { val: record, .. } = &mut value { + // Only the name column gets special colors, for now + if let Some(value) = record.to_mut().get_mut("name") { + let span = value.span(); + if let Value::String { val, .. } = value { + if let Some(val) = render_path_name(val, &config, &ls_colors, span) { + *value = val; } } - - x } - _ => x, - }), - ctrlc, - ) + } + value + }) } // Next, `to html -l` sources: Some(PipelineMetadata { data_source: DataSource::HtmlThemes, }) => { - let ctrlc = ctrlc.clone(); - - ListStream::from_stream( - stream.map(move |mut x| match &mut x { - Value::Record { val: record, .. } => { - for (rec_col, rec_val) in record.to_mut().iter_mut() { - // Every column in the HTML theme table except 'name' is colored - if rec_col != "name" { - continue; - } - // Simple routine to grab the hex code, convert to a style, - // then place it in a new Value::String. - - let span = rec_val.span(); - if let Value::String { val, .. } = rec_val { - let s = match color_from_hex(val) { - Ok(c) => match c { - // .normal() just sets the text foreground color. - Some(c) => c.normal(), - None => nu_ansi_term::Style::default(), - }, - Err(_) => nu_ansi_term::Style::default(), - }; - *rec_val = Value::string( - // Apply the style (ANSI codes) to the string - s.paint(&*val).to_string(), - span, - ); - } + stream.map(|mut value| { + if let Value::Record { val: record, .. } = &mut value { + for (rec_col, rec_val) in record.to_mut().iter_mut() { + // Every column in the HTML theme table except 'name' is colored + if rec_col != "name" { + continue; + } + // Simple routine to grab the hex code, convert to a style, + // then place it in a new Value::String. + + let span = rec_val.span(); + if let Value::String { val, .. } = rec_val { + let s = match color_from_hex(val) { + Ok(c) => match c { + // .normal() just sets the text foreground color. + Some(c) => c.normal(), + None => nu_ansi_term::Style::default(), + }, + Err(_) => nu_ansi_term::Style::default(), + }; + *rec_val = Value::string( + // Apply the style (ANSI codes) to the string + s.paint(&*val).to_string(), + span, + ); } - x } - _ => x, - }), - ctrlc, - ) + } + value + }) } _ => stream, }; @@ -662,7 +651,7 @@ fn make_clickable_link( struct PagingTableCreator { head: Span, - stream: ListStream, + stream: ValueIterator, engine_state: EngineState, stack: Stack, ctrlc: Option>, @@ -683,7 +672,7 @@ impl PagingTableCreator { ) -> Self { PagingTableCreator { head, - stream, + stream: stream.into_inner(), engine_state, stack, ctrlc, @@ -822,7 +811,7 @@ impl Iterator for PagingTableCreator { } fn stream_collect( - stream: &mut ListStream, + stream: impl Iterator, size: usize, ctrlc: Option>, ) -> (Vec, bool) { @@ -830,7 +819,7 @@ fn stream_collect( let mut end = true; let mut batch = Vec::with_capacity(size); - for (i, item) in stream.by_ref().enumerate() { + for (i, item) in stream.enumerate() { batch.push(item); // If we've been buffering over a second, go ahead and send out what we have so far @@ -853,7 +842,7 @@ fn stream_collect( } fn stream_collect_abbriviated( - stream: &mut ListStream, + stream: impl Iterator, size: usize, ctrlc: Option>, ) -> (Vec, usize, bool) { @@ -866,7 +855,7 @@ fn stream_collect_abbriviated( return (vec![], 0, false); } - for item in stream.by_ref() { + for item in stream { read += 1; if read <= size { diff --git a/crates/nu-explore/src/nu_common/value.rs b/crates/nu-explore/src/nu_common/value.rs index c61533770b..17b277cac5 100644 --- a/crates/nu-explore/src/nu_common/value.rs +++ b/crates/nu-explore/src/nu_common/value.rs @@ -22,9 +22,9 @@ pub fn collect_pipeline(input: PipelineData) -> Result<(Vec, Vec (Vec, Vec>) { +fn collect_list_stream(stream: ListStream) -> (Vec, Vec>) { let mut records = vec![]; - for item in stream.by_ref() { + for item in stream { records.push(item); } @@ -70,7 +70,7 @@ fn collect_external_stream( data.push(value); } if let Some(exit_code) = exit_code { - let list = exit_code.collect::>(); + let list = exit_code.into_iter().collect::>(); let val = Value::list(list, span); columns.push(String::from("exit_code")); diff --git a/crates/nu-plugin-core/src/interface/mod.rs b/crates/nu-plugin-core/src/interface/mod.rs index 4124e83bfb..3fb86aee36 100644 --- a/crates/nu-plugin-core/src/interface/mod.rs +++ b/crates/nu-plugin-core/src/interface/mod.rs @@ -183,7 +183,7 @@ pub trait InterfaceManager { PipelineDataHeader::ListStream(info) => { let handle = self.stream_manager().get_handle(); let reader = handle.read_stream(info.id, self.get_interface())?; - PipelineData::ListStream(ListStream::from_stream(reader, ctrlc.cloned()), None) + ListStream::new(reader, info.span, ctrlc.cloned()).into() } PipelineDataHeader::ExternalStream(info) => { let handle = self.stream_manager().get_handle(); @@ -203,7 +203,7 @@ pub trait InterfaceManager { .map(|list_info| { handle .read_stream(list_info.id, self.get_interface()) - .map(|reader| ListStream::from_stream(reader, ctrlc.cloned())) + .map(|reader| ListStream::new(reader, info.span, ctrlc.cloned())) }) .transpose()?, span: info.span, @@ -278,7 +278,10 @@ pub trait Interface: Clone + Send { PipelineData::ListStream(stream, _) => { let (id, writer) = new_stream(LIST_STREAM_HIGH_PRESSURE)?; Ok(( - PipelineDataHeader::ListStream(ListStreamInfo { id }), + PipelineDataHeader::ListStream(ListStreamInfo { + id, + span: stream.span(), + }), PipelineDataWriter::ListStream(writer, stream), )) } @@ -316,7 +319,7 @@ pub trait Interface: Clone + Send { .map(|(stream, (id, _))| RawStreamInfo::new(*id, stream)), exit_code: exit_code_stream .as_ref() - .map(|&(id, _)| ListStreamInfo { id }), + .map(|&(id, _)| ListStreamInfo { id, span }), trim_end_newline, }); // Collect the writers diff --git a/crates/nu-plugin-core/src/interface/tests.rs b/crates/nu-plugin-core/src/interface/tests.rs index 33b6ef27ae..ce7be52f30 100644 --- a/crates/nu-plugin-core/src/interface/tests.rs +++ b/crates/nu-plugin-core/src/interface/tests.rs @@ -161,7 +161,10 @@ fn read_pipeline_data_list_stream() -> Result<(), ShellError> { } test.add(StreamMessage::End(7)); - let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 7 }); + let header = PipelineDataHeader::ListStream(ListStreamInfo { + id: 7, + span: Span::test_data(), + }); let pipe = manager.read_pipeline_data(header, None)?; assert!( @@ -221,7 +224,10 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> { is_binary: true, known_size: None, }), - exit_code: Some(ListStreamInfo { id: 14 }), + exit_code: Some(ListStreamInfo { + id: 14, + span: Span::test_data(), + }), trim_end_newline: true, }); @@ -273,7 +279,10 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> { } assert_eq!(iterations, count, "stderr length"); - assert_eq!(vec![Value::test_int(1)], exit_code.collect::>()); + assert_eq!( + vec![Value::test_int(1)], + exit_code.into_iter().collect::>() + ); } _ => panic!("unexpected PipelineData: {pipe:?}"), } @@ -284,30 +293,13 @@ fn read_pipeline_data_external_stream() -> Result<(), ShellError> { Ok(()) } -#[test] -fn read_pipeline_data_ctrlc() -> Result<(), ShellError> { - let manager = TestInterfaceManager::new(&TestCase::new()); - let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }); - let ctrlc = Default::default(); - match manager.read_pipeline_data(header, Some(&ctrlc))? { - PipelineData::ListStream( - ListStream { - ctrlc: stream_ctrlc, - .. - }, - _, - ) => { - assert!(Arc::ptr_eq(&ctrlc, &stream_ctrlc.expect("ctrlc not set"))); - Ok(()) - } - _ => panic!("Unexpected PipelineData, should have been ListStream"), - } -} - #[test] fn read_pipeline_data_prepared_properly() -> Result<(), ShellError> { let manager = TestInterfaceManager::new(&TestCase::new()); - let header = PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }); + let header = PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + }); match manager.read_pipeline_data(header, None)? { PipelineData::ListStream(_, meta) => match meta { Some(PipelineMetadata { data_source }) => match data_source { @@ -404,7 +396,7 @@ fn write_pipeline_data_list_stream() -> Result<(), ShellError> { // Set up pipeline data for a list stream let pipe = PipelineData::ListStream( - ListStream::from_stream(values.clone().into_iter(), None), + ListStream::new(values.clone().into_iter(), Span::test_data(), None), None, ); @@ -474,8 +466,9 @@ fn write_pipeline_data_external_stream() -> Result<(), ShellError> { span, None, )), - exit_code: Some(ListStream::from_stream( + exit_code: Some(ListStream::new( std::iter::once(exit_code.clone()), + Span::test_data(), None, )), span, diff --git a/crates/nu-plugin-engine/src/interface/mod.rs b/crates/nu-plugin-engine/src/interface/mod.rs index be14dbdc2d..3447d6a907 100644 --- a/crates/nu-plugin-engine/src/interface/mod.rs +++ b/crates/nu-plugin-engine/src/interface/mod.rs @@ -11,8 +11,8 @@ use nu_plugin_protocol::{ PluginOutput, ProtocolInfo, StreamId, StreamMessage, }; use nu_protocol::{ - ast::Operator, CustomValue, IntoInterruptiblePipelineData, IntoSpanned, ListStream, - PipelineData, PluginSignature, ShellError, Span, Spanned, Value, + ast::Operator, CustomValue, IntoSpanned, PipelineData, PluginSignature, ShellError, Span, + Spanned, Value, }; use std::{ collections::{btree_map, BTreeMap}, @@ -592,14 +592,15 @@ impl InterfaceManager for PluginInterfaceManager { })?; Ok(data) } - PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => { + PipelineData::ListStream(stream, meta) => { let source = self.state.source.clone(); - Ok(stream - .map(move |mut value| { + Ok(PipelineData::ListStream( + stream.map(move |mut value| { let _ = PluginCustomValueWithSource::add_source_in(&mut value, &source); value - }) - .into_pipeline_data_with_metadata(meta, ctrlc)) + }), + meta, + )) } PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), } @@ -1076,18 +1077,19 @@ impl Interface for PluginInterface { state.prepare_value(&mut value, &self.state.source)?; Ok(PipelineData::Value(value, meta)) } - PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => { + PipelineData::ListStream(stream, meta) => { let source = self.state.source.clone(); let state = state.clone(); - Ok(stream - .map(move |mut value| { + Ok(PipelineData::ListStream( + stream.map(move |mut value| { match state.prepare_value(&mut value, &source) { Ok(()) => value, // Put the error in the stream instead Err(err) => Value::error(err, value.span()), } - }) - .into_pipeline_data_with_metadata(meta, ctrlc)) + }), + meta, + )) } PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), } diff --git a/crates/nu-plugin-engine/src/interface/tests.rs b/crates/nu-plugin-engine/src/interface/tests.rs index 007568d726..7548703191 100644 --- a/crates/nu-plugin-engine/src/interface/tests.rs +++ b/crates/nu-plugin-engine/src/interface/tests.rs @@ -52,7 +52,10 @@ fn manager_consume_all_exits_after_streams_and_interfaces_are_dropped() -> Resul // Create a stream... let stream = manager.read_pipeline_data( - PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), + PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + }), None, )?; @@ -105,7 +108,10 @@ fn manager_consume_all_propagates_io_error_to_readers() -> Result<(), ShellError test.set_read_error(test_io_error()); let stream = manager.read_pipeline_data( - PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), + PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + }), None, )?; @@ -331,7 +337,10 @@ fn manager_consume_call_response_forwards_to_subscriber_with_pipeline_data( manager.consume(PluginOutput::CallResponse( 0, - PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), + PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + })), ))?; for i in 0..2 { @@ -372,7 +381,10 @@ fn manager_consume_call_response_registers_streams() -> Result<(), ShellError> { // Check list streams, external streams manager.consume(PluginOutput::CallResponse( 0, - PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), + PluginCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + })), ))?; manager.consume(PluginOutput::CallResponse( 1, @@ -388,7 +400,10 @@ fn manager_consume_call_response_registers_streams() -> Result<(), ShellError> { is_binary: false, known_size: None, }), - exit_code: Some(ListStreamInfo { id: 3 }), + exit_code: Some(ListStreamInfo { + id: 3, + span: Span::test_data(), + }), trim_end_newline: false, })), ))?; @@ -448,7 +463,10 @@ fn manager_consume_engine_call_forwards_to_subscriber_with_pipeline_data() -> Re span: Span::test_data(), }, positional: vec![], - input: PipelineDataHeader::ListStream(ListStreamInfo { id: 2 }), + input: PipelineDataHeader::ListStream(ListStreamInfo { + id: 2, + span: Span::test_data(), + }), redirect_stdout: false, redirect_stderr: false, }, @@ -681,7 +699,7 @@ fn manager_prepare_pipeline_data_adds_source_to_list_streams() -> Result<(), She [Value::test_custom_value(Box::new( test_plugin_custom_value(), ))] - .into_pipeline_data(None), + .into_pipeline_data(Span::test_data(), None), )?; let value = data @@ -855,7 +873,7 @@ fn interface_write_plugin_call_writes_run_with_stream_input() -> Result<(), Shel positional: vec![], named: vec![], }, - input: values.clone().into_pipeline_data(None), + input: values.clone().into_pipeline_data(Span::test_data(), None), }), None, )?; @@ -1131,7 +1149,10 @@ fn interface_prepare_pipeline_data_accepts_normal_streams() -> Result<(), ShellE let interface = TestCase::new().plugin("test").get_interface(); let values = normal_values(&interface); let state = CurrentCallState::default(); - let data = interface.prepare_pipeline_data(values.clone().into_pipeline_data(None), &state)?; + let data = interface.prepare_pipeline_data( + values.clone().into_pipeline_data(Span::test_data(), None), + &state, + )?; let mut count = 0; for (expected_value, actual_value) in values.iter().zip(data) { @@ -1191,7 +1212,10 @@ fn interface_prepare_pipeline_data_rejects_bad_custom_value_in_a_stream() -> Res let interface = TestCase::new().plugin("test").get_interface(); let values = bad_custom_values(); let state = CurrentCallState::default(); - let data = interface.prepare_pipeline_data(values.clone().into_pipeline_data(None), &state)?; + let data = interface.prepare_pipeline_data( + values.clone().into_pipeline_data(Span::test_data(), None), + &state, + )?; let mut count = 0; for value in data { diff --git a/crates/nu-plugin-protocol/src/lib.rs b/crates/nu-plugin-protocol/src/lib.rs index 57bec28327..e40136ca56 100644 --- a/crates/nu-plugin-protocol/src/lib.rs +++ b/crates/nu-plugin-protocol/src/lib.rs @@ -116,6 +116,7 @@ impl PipelineDataHeader { #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct ListStreamInfo { pub id: StreamId, + pub span: Span, } /// Additional information about external streams diff --git a/crates/nu-plugin-test-support/src/lib.rs b/crates/nu-plugin-test-support/src/lib.rs index dd301d4d2b..8aa675fd1f 100644 --- a/crates/nu-plugin-test-support/src/lib.rs +++ b/crates/nu-plugin-test-support/src/lib.rs @@ -79,7 +79,7 @@ //! //! // #[test] //! fn test_lowercase() -> Result<(), ShellError> { -//! let input = vec![Value::test_string("FooBar")].into_pipeline_data(None); +//! let input = vec![Value::test_string("FooBar")].into_pipeline_data(Span::test_data(), None); //! let output = PluginTest::new("lowercase", LowercasePlugin.into())? //! .eval_with("lowercase", input)? //! .into_value(Span::test_data()); diff --git a/crates/nu-plugin-test-support/src/plugin_test.rs b/crates/nu-plugin-test-support/src/plugin_test.rs index 16eb62cf2e..18eee356ef 100644 --- a/crates/nu-plugin-test-support/src/plugin_test.rs +++ b/crates/nu-plugin-test-support/src/plugin_test.rs @@ -91,7 +91,7 @@ impl PluginTest { /// let result = PluginTest::new("my_plugin", MyPlugin.into())? /// .eval_with( /// "my-command", - /// vec![Value::test_int(42)].into_pipeline_data(None) + /// vec![Value::test_int(42)].into_pipeline_data(Span::test_data(), None) /// )? /// .into_value(Span::test_data()); /// assert_eq!(Value::test_string("42"), result); diff --git a/crates/nu-plugin-test-support/tests/lowercase/mod.rs b/crates/nu-plugin-test-support/tests/lowercase/mod.rs index 25a6063dc0..33446cea86 100644 --- a/crates/nu-plugin-test-support/tests/lowercase/mod.rs +++ b/crates/nu-plugin-test-support/tests/lowercase/mod.rs @@ -68,7 +68,7 @@ impl Plugin for LowercasePlugin { fn test_lowercase_using_eval_with() -> Result<(), ShellError> { let result = PluginTest::new("lowercase", LowercasePlugin.into())?.eval_with( "lowercase", - vec![Value::test_string("HeLlO wOrLd")].into_pipeline_data(None), + vec![Value::test_string("HeLlO wOrLd")].into_pipeline_data(Span::test_data(), None), )?; assert_eq!( diff --git a/crates/nu-plugin/src/plugin/interface/mod.rs b/crates/nu-plugin/src/plugin/interface/mod.rs index 630c6b2979..70e143ece5 100644 --- a/crates/nu-plugin/src/plugin/interface/mod.rs +++ b/crates/nu-plugin/src/plugin/interface/mod.rs @@ -11,8 +11,8 @@ use nu_plugin_protocol::{ ProtocolInfo, }; use nu_protocol::{ - engine::Closure, Config, IntoInterruptiblePipelineData, LabeledError, ListStream, PipelineData, - PluginSignature, ShellError, Span, Spanned, Value, + engine::Closure, Config, LabeledError, PipelineData, PluginSignature, ShellError, Span, + Spanned, Value, }; use std::{ collections::{btree_map, BTreeMap, HashMap}, @@ -336,14 +336,15 @@ impl InterfaceManager for EngineInterfaceManager { PluginCustomValue::deserialize_custom_values_in(value)?; Ok(data) } - PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => Ok(stream - .map(|mut value| { + PipelineData::ListStream(stream, meta) => { + let stream = stream.map(|mut value| { let span = value.span(); PluginCustomValue::deserialize_custom_values_in(&mut value) .map(|()| value) .unwrap_or_else(|err| Value::error(err, span)) - }) - .into_pipeline_data_with_metadata(meta, ctrlc)), + }); + Ok(PipelineData::ListStream(stream, meta)) + } PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), } } @@ -910,14 +911,15 @@ impl Interface for EngineInterface { PluginCustomValue::serialize_custom_values_in(value)?; Ok(data) } - PipelineData::ListStream(ListStream { stream, ctrlc, .. }, meta) => Ok(stream - .map(|mut value| { + PipelineData::ListStream(stream, meta) => { + let stream = stream.map(|mut value| { let span = value.span(); PluginCustomValue::serialize_custom_values_in(&mut value) .map(|_| value) .unwrap_or_else(|err| Value::error(err, span)) - }) - .into_pipeline_data_with_metadata(meta, ctrlc)), + }); + Ok(PipelineData::ListStream(stream, meta)) + } PipelineData::Empty | PipelineData::ExternalStream { .. } => Ok(data), } } diff --git a/crates/nu-plugin/src/plugin/interface/tests.rs b/crates/nu-plugin/src/plugin/interface/tests.rs index 7fc7bf06e4..17018cbc00 100644 --- a/crates/nu-plugin/src/plugin/interface/tests.rs +++ b/crates/nu-plugin/src/plugin/interface/tests.rs @@ -56,7 +56,10 @@ fn manager_consume_all_exits_after_streams_and_interfaces_are_dropped() -> Resul // Create a stream... let stream = manager.read_pipeline_data( - PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), + PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + }), None, )?; @@ -109,7 +112,10 @@ fn manager_consume_all_propagates_io_error_to_readers() -> Result<(), ShellError test.set_read_error(test_io_error()); let stream = manager.read_pipeline_data( - PipelineDataHeader::ListStream(ListStreamInfo { id: 0 }), + PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + }), None, )?; @@ -395,7 +401,10 @@ fn manager_consume_call_run_forwards_to_receiver_with_pipeline_data() -> Result< positional: vec![], named: vec![], }, - input: PipelineDataHeader::ListStream(ListStreamInfo { id: 6 }), + input: PipelineDataHeader::ListStream(ListStreamInfo { + id: 6, + span: Span::test_data(), + }), }), ))?; @@ -534,7 +543,10 @@ fn manager_consume_engine_call_response_forwards_to_subscriber_with_pipeline_dat manager.consume(PluginInput::EngineCallResponse( 0, - EngineCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { id: 0 })), + EngineCallResponse::PipelineData(PipelineDataHeader::ListStream(ListStreamInfo { + id: 0, + span: Span::test_data(), + })), ))?; for i in 0..2 { @@ -590,7 +602,7 @@ fn manager_prepare_pipeline_data_deserializes_custom_values_in_streams() -> Resu [Value::test_custom_value(Box::new( test_plugin_custom_value(), ))] - .into_pipeline_data(None), + .into_pipeline_data(Span::test_data(), None), )?; let value = data @@ -621,7 +633,8 @@ fn manager_prepare_pipeline_data_embeds_deserialization_errors_in_streams() -> R let span = Span::new(20, 30); let data = manager.prepare_pipeline_data( - [Value::custom(Box::new(invalid_custom_value), span)].into_pipeline_data(None), + [Value::custom(Box::new(invalid_custom_value), span)] + .into_pipeline_data(Span::test_data(), None), )?; let value = data @@ -703,7 +716,8 @@ fn interface_write_response_with_stream() -> Result<(), ShellError> { interface .write_response(Ok::<_, ShellError>( - [Value::test_int(3), Value::test_int(4), Value::test_int(5)].into_pipeline_data(None), + [Value::test_int(3), Value::test_int(4), Value::test_int(5)] + .into_pipeline_data(Span::test_data(), None), ))? .write()?; @@ -1105,7 +1119,7 @@ fn interface_prepare_pipeline_data_serializes_custom_values_in_streams() -> Resu [Value::test_custom_value(Box::new( expected_test_custom_value(), ))] - .into_pipeline_data(None), + .into_pipeline_data(Span::test_data(), None), &(), )?; @@ -1163,7 +1177,8 @@ fn interface_prepare_pipeline_data_embeds_serialization_errors_in_streams() -> R let span = Span::new(40, 60); let data = interface.prepare_pipeline_data( - [Value::custom(Box::new(CantSerialize::BadVariant), span)].into_pipeline_data(None), + [Value::custom(Box::new(CantSerialize::BadVariant), span)] + .into_pipeline_data(Span::test_data(), None), &(), )?; diff --git a/crates/nu-protocol/src/eval_base.rs b/crates/nu-protocol/src/eval_base.rs index f211f48560..6a1c0d302f 100644 --- a/crates/nu-protocol/src/eval_base.rs +++ b/crates/nu-protocol/src/eval_base.rs @@ -4,8 +4,7 @@ use crate::{ ExternalArgument, ListItem, Math, Operator, RecordItem, }, debugger::DebugContext, - Config, IntoInterruptiblePipelineData, Range, Record, ShellError, Span, Value, VarId, - ENV_VARIABLE_ID, + Config, Range, Record, ShellError, Span, Value, VarId, ENV_VARIABLE_ID, }; use std::{borrow::Cow, collections::HashMap}; @@ -278,18 +277,13 @@ pub trait Eval { Self::eval_row_condition_or_closure(state, mut_state, *block_id, expr.span) } Expr::StringInterpolation(exprs) => { - let mut parts = vec![]; - for expr in exprs { - parts.push(Self::eval::(state, mut_state, expr)?); - } - let config = Self::get_config(state, mut_state); + let str = exprs + .iter() + .map(|expr| Self::eval::(state, mut_state, expr).map(|v| v.to_expanded_string(", ", &config))) + .collect::>()?; - parts - .into_iter() - .into_pipeline_data(None) - .collect_string("", &config) - .map(|x| Value::string(x, expr.span)) + Ok(Value::string(str, expr.span)) } Expr::Overlay(_) => Self::eval_overlay(state, expr.span), Expr::GlobPattern(pattern, quoted) => { diff --git a/crates/nu-protocol/src/pipeline_data/list_stream.rs b/crates/nu-protocol/src/pipeline_data/list_stream.rs new file mode 100644 index 0000000000..117c264219 --- /dev/null +++ b/crates/nu-protocol/src/pipeline_data/list_stream.rs @@ -0,0 +1,156 @@ +use crate::{Config, PipelineData, ShellError, Span, Value}; +use std::{ + fmt::Debug, + sync::{atomic::AtomicBool, Arc}, +}; + +pub type ValueIterator = Box + Send + 'static>; + +/// A potentially infinite, interruptible stream of [`Value`]s. +/// +/// In practice, a "stream" here means anything which can be iterated and produces Values. +/// Like other iterators in Rust, observing values from this stream will drain the items +/// as you view them and the stream cannot be replayed. +pub struct ListStream { + stream: ValueIterator, + span: Span, +} + +impl ListStream { + /// Create a new [`ListStream`] from a [`Value`] `Iterator`. + pub fn new( + iter: impl Iterator + Send + 'static, + span: Span, + interrupt: Option>, + ) -> Self { + Self { + stream: Box::new(Interrupt::new(iter, interrupt)), + span, + } + } + + /// Returns the [`Span`] associated with this [`ListStream`]. + pub fn span(&self) -> Span { + self.span + } + + /// Convert a [`ListStream`] into its inner [`Value`] `Iterator`. + pub fn into_inner(self) -> ValueIterator { + self.stream + } + + /// Converts each value in a [`ListStream`] into a string and then joins the strings together + /// using the given separator. + pub fn into_string(self, separator: &str, config: &Config) -> String { + self.into_iter() + .map(|val| val.to_expanded_string(", ", config)) + .collect::>() + .join(separator) + } + + /// Collect the values of a [`ListStream`] into a list [`Value`]. + pub fn into_value(self) -> Value { + Value::list(self.stream.collect(), self.span) + } + + /// Consume all values in the stream, returning an error if any of the values is a `Value::Error`. + pub fn drain(self) -> Result<(), ShellError> { + for next in self { + if let Value::Error { error, .. } = next { + return Err(*error); + } + } + Ok(()) + } + + /// Modify the inner iterator of a [`ListStream`] using a function. + /// + /// This can be used to call any number of standard iterator functions on the [`ListStream`]. + /// E.g., `take`, `filter`, `step_by`, and more. + /// + /// ``` + /// use nu_protocol::{ListStream, Span, Value}; + /// + /// let span = Span::unknown(); + /// let stream = ListStream::new(std::iter::repeat(Value::int(0, span)), span, None); + /// let new_stream = stream.modify(|iter| iter.take(100)); + /// ``` + pub fn modify(self, f: impl FnOnce(ValueIterator) -> I) -> Self + where + I: Iterator + Send + 'static, + { + Self { + stream: Box::new(f(self.stream)), + span: self.span, + } + } + + /// Create a new [`ListStream`] whose values are the results of applying the given function + /// to each of the values in the original [`ListStream`]. + pub fn map(self, mapping: impl FnMut(Value) -> Value + Send + 'static) -> Self { + self.modify(|iter| iter.map(mapping)) + } +} + +impl Debug for ListStream { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ListStream").finish() + } +} + +impl IntoIterator for ListStream { + type Item = Value; + + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter { + stream: self.into_inner(), + } + } +} + +impl From for PipelineData { + fn from(stream: ListStream) -> Self { + Self::ListStream(stream, None) + } +} + +pub struct IntoIter { + stream: ValueIterator, +} + +impl Iterator for IntoIter { + type Item = Value; + + fn next(&mut self) -> Option { + self.stream.next() + } +} + +struct Interrupt { + iter: I, + interrupt: Option>, +} + +impl Interrupt { + fn new(iter: I, interrupt: Option>) -> Self { + Self { iter, interrupt } + } +} + +impl Iterator for Interrupt { + type Item = ::Item; + + fn next(&mut self) -> Option { + if nu_utils::ctrl_c::was_pressed(&self.interrupt) { + None + } else { + self.iter.next() + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} diff --git a/crates/nu-protocol/src/pipeline_data/mod.rs b/crates/nu-protocol/src/pipeline_data/mod.rs index 94096c31a4..71c667fa70 100644 --- a/crates/nu-protocol/src/pipeline_data/mod.rs +++ b/crates/nu-protocol/src/pipeline_data/mod.rs @@ -1,10 +1,12 @@ +pub mod list_stream; mod metadata; mod out_dest; -mod stream; +mod raw_stream; +pub use list_stream::{ListStream, ValueIterator}; pub use metadata::*; pub use out_dest::*; -pub use stream::*; +pub use raw_stream::*; use crate::{ ast::{Call, PathMember}, @@ -76,8 +78,9 @@ impl PipelineData { PipelineData::ExternalStream { stdout: None, stderr: None, - exit_code: Some(ListStream::from_stream( + exit_code: Some(ListStream::new( [Value::int(exit_code, Span::unknown())].into_iter(), + Span::unknown(), None, )), span: Span::unknown(), @@ -118,7 +121,7 @@ impl PipelineData { /// PipelineData doesn't always have a Span, but we can try! pub fn span(&self) -> Option { match self { - PipelineData::ListStream(..) => None, + PipelineData::ListStream(stream, ..) => Some(stream.span()), PipelineData::ExternalStream { span, .. } => Some(*span), PipelineData::Value(v, _) => Some(v.span()), PipelineData::Empty => None, @@ -131,7 +134,7 @@ impl PipelineData { PipelineData::Value(Value::Nothing { .. }, ..) => Value::nothing(span), PipelineData::Value(v, ..) => v.with_span(span), PipelineData::ListStream(s, ..) => Value::list( - s.collect(), + s.into_iter().collect(), span, // FIXME? ), PipelineData::ExternalStream { @@ -403,51 +406,54 @@ impl PipelineData { /// /// It returns Err if the `self` cannot be converted to an iterator. pub fn into_iter_strict(self, span: Span) -> Result { - match self { - PipelineData::Value(value, metadata) => match value { - Value::List { vals, .. } => Ok(PipelineIterator(PipelineData::ListStream( - ListStream::from_stream(vals.into_iter(), None), - metadata, - ))), - Value::Binary { val, .. } => Ok(PipelineIterator(PipelineData::ListStream( - ListStream::from_stream( - val.into_iter().map(move |x| Value::int(x as i64, span)), - None, + Ok(PipelineIterator(match self { + PipelineData::Value(value, ..) => { + let val_span = value.span(); + match value { + Value::List { vals, .. } => PipelineIteratorInner::ListStream( + ListStream::new(vals.into_iter(), val_span, None).into_iter(), ), - metadata, - ))), - Value::Range { val, .. } => Ok(PipelineIterator(PipelineData::ListStream( - ListStream::from_stream(val.into_range_iter(value.span(), None), None), - metadata, - ))) - , - // Propagate errors by explicitly matching them before the final case. - Value::Error { error, .. } => Err(*error), - other => Err(ShellError::OnlySupportsThisInputType { + Value::Binary { val, .. } => PipelineIteratorInner::ListStream( + ListStream::new( + val.into_iter().map(move |x| Value::int(x as i64, val_span)), + val_span, + None, + ) + .into_iter(), + ), + Value::Range { val, .. } => PipelineIteratorInner::ListStream( + ListStream::new(val.into_range_iter(value.span(), None), val_span, None) + .into_iter(), + ), + // Propagate errors by explicitly matching them before the final case. + Value::Error { error, .. } => return Err(*error), + other => { + return Err(ShellError::OnlySupportsThisInputType { + exp_input_type: "list, binary, raw data or range".into(), + wrong_type: other.get_type().to_string(), + dst_span: span, + src_span: val_span, + }) + } + } + } + PipelineData::ListStream(stream, ..) => { + PipelineIteratorInner::ListStream(stream.into_iter()) + } + PipelineData::Empty => { + return Err(ShellError::OnlySupportsThisInputType { exp_input_type: "list, binary, raw data or range".into(), - wrong_type: other.get_type().to_string(), + wrong_type: "null".into(), dst_span: span, - src_span: other.span(), - }), - }, - PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType { - exp_input_type: "list, binary, raw data or range".into(), - wrong_type: "null".into(), - dst_span: span, - src_span: span, - }), - other => Ok(PipelineIterator(other)), - } - } - - pub fn into_interruptible_iter(self, ctrlc: Option>) -> PipelineIterator { - let mut iter = self.into_iter(); - - if let PipelineIterator(PipelineData::ListStream(s, ..)) = &mut iter { - s.ctrlc = ctrlc; - } - - iter + src_span: span, + }) + } + PipelineData::ExternalStream { + stdout: Some(stdout), + .. + } => PipelineIteratorInner::ExternalStream(stdout), + PipelineData::ExternalStream { stdout: None, .. } => PipelineIteratorInner::Empty, + })) } pub fn collect_string(self, separator: &str, config: &Config) -> Result { @@ -516,9 +522,8 @@ impl PipelineData { ) -> Result { match self { // FIXME: there are probably better ways of doing this - PipelineData::ListStream(stream, ..) => { - Value::list(stream.collect(), head).follow_cell_path(cell_path, insensitive) - } + PipelineData::ListStream(stream, ..) => Value::list(stream.into_iter().collect(), head) + .follow_cell_path(cell_path, insensitive), PipelineData::Value(v, ..) => v.follow_cell_path(cell_path, insensitive), PipelineData::Empty => Err(ShellError::IncompatiblePathAccess { type_name: "empty pipeline".to_string(), @@ -531,22 +536,6 @@ impl PipelineData { } } - pub fn upsert_cell_path( - &mut self, - cell_path: &[PathMember], - callback: Box Value>, - head: Span, - ) -> Result<(), ShellError> { - match self { - // FIXME: there are probably better ways of doing this - PipelineData::ListStream(stream, ..) => { - Value::list(stream.collect(), head).upsert_cell_path(cell_path, callback) - } - PipelineData::Value(v, ..) => v.upsert_cell_path(cell_path, callback), - _ => Ok(()), - } - } - /// Simplified mapper to help with simple values also. For full iterator support use `.into_iter()` instead pub fn map( self, @@ -562,12 +551,12 @@ impl PipelineData { let span = value.span(); match value { Value::List { vals, .. } => { - Ok(vals.into_iter().map(f).into_pipeline_data(ctrlc)) + Ok(vals.into_iter().map(f).into_pipeline_data(span, ctrlc)) } Value::Range { val, .. } => Ok(val .into_range_iter(span, ctrlc.clone()) .map(f) - .into_pipeline_data(ctrlc)), + .into_pipeline_data(span, ctrlc)), value => match f(value) { Value::Error { error, .. } => Err(*error), v => Ok(v.into_pipeline_data()), @@ -575,7 +564,9 @@ impl PipelineData { } } PipelineData::Empty => Ok(PipelineData::Empty), - PipelineData::ListStream(stream, ..) => Ok(stream.map(f).into_pipeline_data(ctrlc)), + PipelineData::ListStream(stream, ..) => { + Ok(PipelineData::ListStream(stream.map(f), None)) + } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::empty()), PipelineData::ExternalStream { stdout: Some(stream), @@ -614,21 +605,22 @@ impl PipelineData { let span = value.span(); match value { Value::List { vals, .. } => { - Ok(vals.into_iter().flat_map(f).into_pipeline_data(ctrlc)) + Ok(vals.into_iter().flat_map(f).into_pipeline_data(span, ctrlc)) } Value::Range { val, .. } => Ok(val .into_range_iter(span, ctrlc.clone()) .flat_map(f) - .into_pipeline_data(ctrlc)), - value => Ok(f(value).into_iter().into_pipeline_data(ctrlc)), + .into_pipeline_data(span, ctrlc)), + value => Ok(f(value).into_iter().into_pipeline_data(span, ctrlc)), } } PipelineData::ListStream(stream, ..) => { - Ok(stream.flat_map(f).into_pipeline_data(ctrlc)) + Ok(stream.modify(|iter| iter.flat_map(f)).into()) } PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::Empty), PipelineData::ExternalStream { stdout: Some(stream), + span, trim_end_newline, .. } => { @@ -640,11 +632,11 @@ impl PipelineData { } Ok(f(Value::string(st, collected.span)) .into_iter() - .into_pipeline_data(ctrlc)) + .into_pipeline_data(span, ctrlc)) } else { Ok(f(Value::binary(collected.item, collected.span)) .into_iter() - .into_pipeline_data(ctrlc)) + .into_pipeline_data(span, ctrlc)) } } } @@ -665,12 +657,12 @@ impl PipelineData { let span = value.span(); match value { Value::List { vals, .. } => { - Ok(vals.into_iter().filter(f).into_pipeline_data(ctrlc)) + Ok(vals.into_iter().filter(f).into_pipeline_data(span, ctrlc)) } Value::Range { val, .. } => Ok(val .into_range_iter(span, ctrlc.clone()) .filter(f) - .into_pipeline_data(ctrlc)), + .into_pipeline_data(span, ctrlc)), value => { if f(&value) { Ok(value.into_pipeline_data()) @@ -680,7 +672,7 @@ impl PipelineData { } } } - PipelineData::ListStream(stream, ..) => Ok(stream.filter(f).into_pipeline_data(ctrlc)), + PipelineData::ListStream(stream, ..) => Ok(stream.modify(|iter| iter.filter(f)).into()), PipelineData::ExternalStream { stdout: None, .. } => Ok(PipelineData::Empty), PipelineData::ExternalStream { stdout: Some(stream), @@ -764,7 +756,6 @@ impl PipelineData { match exit_code { Some(exit_code_stream) => { - let ctrlc = exit_code_stream.ctrlc.clone(); let exit_code: Vec = exit_code_stream.into_iter().collect(); if let Some(Value::Int { val: code, .. }) = exit_code.last() { // if exit_code is not 0, it indicates error occurred, return back Err. @@ -776,7 +767,7 @@ impl PipelineData { PipelineData::ExternalStream { stdout: None, stderr, - exit_code: Some(ListStream::from_stream(exit_code.into_iter(), ctrlc)), + exit_code: Some(ListStream::new(exit_code.into_iter(), span, None)), span, metadata, trim_end_newline, @@ -947,7 +938,14 @@ impl PipelineData { } } -pub struct PipelineIterator(PipelineData); +enum PipelineIteratorInner { + Empty, + Value(Value), + ListStream(list_stream::IntoIter), + ExternalStream(RawStream), +} + +pub struct PipelineIterator(PipelineIteratorInner); impl IntoIterator for PipelineData { type Item = Value; @@ -955,23 +953,29 @@ impl IntoIterator for PipelineData { type IntoIter = PipelineIterator; fn into_iter(self) -> Self::IntoIter { - match self { - PipelineData::Value(value, metadata) => { + PipelineIterator(match self { + PipelineData::Value(value, ..) => { let span = value.span(); match value { - Value::List { vals, .. } => PipelineIterator(PipelineData::ListStream( - ListStream::from_stream(vals.into_iter(), None), - metadata, - )), - Value::Range { val, .. } => PipelineIterator(PipelineData::ListStream( - ListStream::from_stream(val.into_range_iter(span, None), None), - metadata, - )), - x => PipelineIterator(PipelineData::Value(x, metadata)), + Value::List { vals, .. } => PipelineIteratorInner::ListStream( + ListStream::new(vals.into_iter(), span, None).into_iter(), + ), + Value::Range { val, .. } => PipelineIteratorInner::ListStream( + ListStream::new(val.into_range_iter(span, None), span, None).into_iter(), + ), + x => PipelineIteratorInner::Value(x), } } - x => PipelineIterator(x), - } + PipelineData::ListStream(stream, ..) => { + PipelineIteratorInner::ListStream(stream.into_iter()) + } + PipelineData::ExternalStream { + stdout: Some(stdout), + .. + } => PipelineIteratorInner::ExternalStream(stdout), + PipelineData::ExternalStream { stdout: None, .. } => PipelineIteratorInner::Empty, + PipelineData::Empty => PipelineIteratorInner::Empty, + }) } } @@ -1075,15 +1079,11 @@ impl Iterator for PipelineIterator { fn next(&mut self) -> Option { match &mut self.0 { - PipelineData::Empty => None, - PipelineData::Value(Value::Nothing { .. }, ..) => None, - PipelineData::Value(v, ..) => Some(std::mem::take(v)), - PipelineData::ListStream(stream, ..) => stream.next(), - PipelineData::ExternalStream { stdout: None, .. } => None, - PipelineData::ExternalStream { - stdout: Some(stream), - .. - } => stream.next().map(|x| match x { + PipelineIteratorInner::Empty => None, + PipelineIteratorInner::Value(Value::Nothing { .. }, ..) => None, + PipelineIteratorInner::Value(v, ..) => Some(std::mem::take(v)), + PipelineIteratorInner::ListStream(stream, ..) => stream.next(), + PipelineIteratorInner::ExternalStream(stream) => stream.next().map(|x| match x { Ok(x) => x, Err(err) => Value::error( err, @@ -1120,11 +1120,12 @@ where } pub trait IntoInterruptiblePipelineData { - fn into_pipeline_data(self, ctrlc: Option>) -> PipelineData; + fn into_pipeline_data(self, span: Span, ctrlc: Option>) -> PipelineData; fn into_pipeline_data_with_metadata( self, - metadata: impl Into>, + span: Span, ctrlc: Option>, + metadata: impl Into>, ) -> PipelineData; } @@ -1134,20 +1135,18 @@ where I::IntoIter: Send + 'static, ::Item: Into, { - fn into_pipeline_data(self, ctrlc: Option>) -> PipelineData { - PipelineData::ListStream( - ListStream::from_stream(self.into_iter().map(Into::into), ctrlc), - None, - ) + fn into_pipeline_data(self, span: Span, ctrlc: Option>) -> PipelineData { + ListStream::new(self.into_iter().map(Into::into), span, ctrlc).into() } fn into_pipeline_data_with_metadata( self, - metadata: impl Into>, + span: Span, ctrlc: Option>, + metadata: impl Into>, ) -> PipelineData { PipelineData::ListStream( - ListStream::from_stream(self.into_iter().map(Into::into), ctrlc), + ListStream::new(self.into_iter().map(Into::into), span, ctrlc), metadata.into(), ) } diff --git a/crates/nu-protocol/src/pipeline_data/stream.rs b/crates/nu-protocol/src/pipeline_data/raw_stream.rs similarity index 74% rename from crates/nu-protocol/src/pipeline_data/stream.rs rename to crates/nu-protocol/src/pipeline_data/raw_stream.rs index 58e759229b..846cdd772b 100644 --- a/crates/nu-protocol/src/pipeline_data/stream.rs +++ b/crates/nu-protocol/src/pipeline_data/raw_stream.rs @@ -174,72 +174,3 @@ impl Iterator for RawStream { } } } - -/// A potentially infinite stream of values, optionally with a mean to send a Ctrl-C signal to stop -/// the stream from continuing. -/// -/// In practice, a "stream" here means anything which can be iterated and produce Values as it iterates. -/// Like other iterators in Rust, observing values from this stream will drain the items as you view them -/// and the stream cannot be replayed. -pub struct ListStream { - pub stream: Box + Send + 'static>, - pub ctrlc: Option>, - first_guard: bool, -} - -impl ListStream { - pub fn into_string(self, separator: &str, config: &Config) -> String { - self.map(|x: Value| x.to_expanded_string(", ", config)) - .collect::>() - .join(separator) - } - - pub fn drain(self) -> Result<(), ShellError> { - for next in self { - if let Value::Error { error, .. } = next { - return Err(*error); - } - } - Ok(()) - } - - pub fn from_stream( - input: impl Iterator + Send + 'static, - ctrlc: Option>, - ) -> ListStream { - ListStream { - stream: Box::new(input), - ctrlc, - first_guard: true, - } - } -} - -impl Debug for ListStream { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ListStream").finish() - } -} - -impl Iterator for ListStream { - type Item = Value; - - fn next(&mut self) -> Option { - // We need to check `first_guard` to guarantee that it always have something to return in - // underlying stream. - // - // A realworld example is running an external commands, which have an `exit_code` - // ListStream. - // When we press ctrl-c, the external command receives the signal too, if we don't have - // `first_guard`, the `exit_code` ListStream will return Nothing, which is not expected - if self.first_guard { - self.first_guard = false; - return self.stream.next(); - } - if nu_utils::ctrl_c::was_pressed(&self.ctrlc) { - None - } else { - self.stream.next() - } - } -} diff --git a/crates/nu_plugin_example/src/commands/generate.rs b/crates/nu_plugin_example/src/commands/generate.rs index 67d30dcb9c..9938518f4c 100644 --- a/crates/nu_plugin_example/src/commands/generate.rs +++ b/crates/nu_plugin_example/src/commands/generate.rs @@ -60,8 +60,8 @@ impl PluginCommand for Generate { call: &EvaluatedCall, _input: PipelineData, ) -> Result { + let head = call.head; let engine = engine.clone(); - let call = call.clone(); let initial: Value = call.req(0)?; let closure = call.req(1)?; @@ -83,9 +83,9 @@ impl PluginCommand for Generate { }) .transpose() }) - .map(|result| result.unwrap_or_else(|err| Value::error(err, call.head))) + .map(|result| result.unwrap_or_else(|err| Value::error(err, head))) }) - .into_pipeline_data(None)) + .into_pipeline_data(head, None)) } } diff --git a/crates/nu_plugin_example/src/commands/seq.rs b/crates/nu_plugin_example/src/commands/seq.rs index 52a21a646a..5652b3ef9a 100644 --- a/crates/nu_plugin_example/src/commands/seq.rs +++ b/crates/nu_plugin_example/src/commands/seq.rs @@ -50,12 +50,11 @@ impl PluginCommand for Seq { call: &EvaluatedCall, _input: PipelineData, ) -> Result { + let head = call.head; let first: i64 = call.req(0)?; let last: i64 = call.req(1)?; - let span = call.head; - let iter = (first..=last).map(move |number| Value::int(number, span)); - let list_stream = ListStream::from_stream(iter, None); - Ok(PipelineData::ListStream(list_stream, None)) + let iter = (first..=last).map(move |number| Value::int(number, head)); + Ok(ListStream::new(iter, head, None).into()) } }