From 66dad400920f5626398badfdadab318f02fbb030 Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Thu, 21 Oct 2021 20:16:18 -0700 Subject: [PATCH 01/16] update readme with the issue 242 where people can sign up for commands to port --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index cec4a5df32..6c51abe900 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,6 @@ Engine-q is an experimental project to replace the core functionality in Nushell (parser, engine, protocol). It's still in an alpha state, and there is still a lot to do: please see TODO.md If you'd like to help out, come join us on the [discord](https://discord.gg/NtAbbGn) or propose some work in an issue or PR draft. We're currently looking to begin porting Nushell commands to engine-q. + +If you are interested in porting a command from nushell to engine-q you are welcome to +[comment on this issue 242](https://github.com/nushell/engine-q/issues/242) with the command name you would like to port. From 7bd5f887d17a2c927a236c1733453de4fa5f0b45 Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Thu, 21 Oct 2021 20:18:51 -0700 Subject: [PATCH 02/16] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c51abe900..ce983a5517 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,5 @@ Engine-q is an experimental project to replace the core functionality in Nushell If you'd like to help out, come join us on the [discord](https://discord.gg/NtAbbGn) or propose some work in an issue or PR draft. We're currently looking to begin porting Nushell commands to engine-q. -If you are interested in porting a command from nushell to engine-q you are welcome to +If you are interested in porting a command from Nushell to engine-q you are welcome to [comment on this issue 242](https://github.com/nushell/engine-q/issues/242) with the command name you would like to port. From 297f3ba5758784d7f184b75afa943d56b453d038 Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Sat, 23 Oct 2021 10:57:45 -0700 Subject: [PATCH 03/16] clean up filesystem by moving get_interactive_confirmation into util.rs --- crates/nu-command/src/filesystem/cp.rs | 4 +-- .../src/filesystem/interactive_helper.rs | 26 ------------------ crates/nu-command/src/filesystem/mod.rs | 1 - crates/nu-command/src/filesystem/mv.rs | 4 +-- crates/nu-command/src/filesystem/rm.rs | 4 +-- crates/nu-command/src/filesystem/util.rs | 27 +++++++++++++++++++ 6 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 crates/nu-command/src/filesystem/interactive_helper.rs diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 8c6ea0655a..80d2b39552 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -1,7 +1,7 @@ use std::env::current_dir; use std::path::PathBuf; -use super::interactive_helper::get_confirmation; +use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_path::canonicalize_with; use nu_protocol::ast::Call; @@ -88,7 +88,7 @@ impl Command for Cp { destination.file_name().unwrap().to_str().unwrap() ); - let input = get_confirmation(prompt)?; + let input = get_interactive_confirmation(prompt)?; if !input { remove.push(index); diff --git a/crates/nu-command/src/filesystem/interactive_helper.rs b/crates/nu-command/src/filesystem/interactive_helper.rs deleted file mode 100644 index 939caa5658..0000000000 --- a/crates/nu-command/src/filesystem/interactive_helper.rs +++ /dev/null @@ -1,26 +0,0 @@ -use dialoguer::Input; -use std::error::Error; - -pub fn get_confirmation(prompt: String) -> Result> { - let input = Input::new() - .with_prompt(prompt) - .validate_with(|c_input: &String| -> Result<(), String> { - if c_input.len() == 1 - && (c_input == "y" || c_input == "Y" || c_input == "n" || c_input == "N") - { - Ok(()) - } else if c_input.len() > 1 { - Err("Enter only one letter (Y/N)".to_string()) - } else { - Err("Input not valid".to_string()) - } - }) - .default("Y/N".into()) - .interact_text()?; - - if input == "y" || input == "Y" { - Ok(true) - } else { - Ok(false) - } -} diff --git a/crates/nu-command/src/filesystem/mod.rs b/crates/nu-command/src/filesystem/mod.rs index 9649859945..db5bc4bea6 100644 --- a/crates/nu-command/src/filesystem/mod.rs +++ b/crates/nu-command/src/filesystem/mod.rs @@ -1,6 +1,5 @@ mod cd; mod cp; -mod interactive_helper; mod ls; mod mkdir; mod mv; diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index fe9b919432..c9f46cd874 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -1,7 +1,7 @@ use std::env::current_dir; use std::path::{Path, PathBuf}; -use super::interactive_helper::get_confirmation; +use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; @@ -74,7 +74,7 @@ impl Command for Mv { destination.file_name().unwrap().to_str().unwrap() ); - let input = get_confirmation(prompt)?; + let input = get_interactive_confirmation(prompt)?; if !input { remove.push(index); diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 48d9126700..0beb63f153 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -3,7 +3,7 @@ use std::env::current_dir; use std::os::unix::prelude::FileTypeExt; use std::path::PathBuf; -use super::interactive_helper::get_confirmation; +use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; @@ -134,7 +134,7 @@ fn rm(context: &EvaluationContext, call: &Call) -> Result { file.1.file_name().unwrap().to_str().unwrap() ); - let input = get_confirmation(prompt)?; + let input = get_interactive_confirmation(prompt)?; if !input { remove.push(index); diff --git a/crates/nu-command/src/filesystem/util.rs b/crates/nu-command/src/filesystem/util.rs index a2d217cf05..8910314fab 100644 --- a/crates/nu-command/src/filesystem/util.rs +++ b/crates/nu-command/src/filesystem/util.rs @@ -3,6 +3,9 @@ use std::path::{Path, PathBuf}; use nu_path::canonicalize_with; use nu_protocol::ShellError; +use dialoguer::Input; +use std::error::Error; + #[derive(Default)] pub struct FileStructure { pub resources: Vec, @@ -79,3 +82,27 @@ pub struct Resource { } impl Resource {} + +pub fn get_interactive_confirmation(prompt: String) -> Result> { + let input = Input::new() + .with_prompt(prompt) + .validate_with(|c_input: &String| -> Result<(), String> { + if c_input.len() == 1 + && (c_input == "y" || c_input == "Y" || c_input == "n" || c_input == "N") + { + Ok(()) + } else if c_input.len() > 1 { + Err("Enter only one letter (Y/N)".to_string()) + } else { + Err("Input not valid".to_string()) + } + }) + .default("Y/N".into()) + .interact_text()?; + + if input == "y" || input == "Y" { + Ok(true) + } else { + Ok(false) + } +} From 1296100d31215bccebe2091bf3d4aafcc3045895 Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 24 Oct 2021 12:40:27 +1300 Subject: [PATCH 04/16] Clippy fixes --- crates/nu-parser/src/parse_keywords.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 7f405714dd..b086ed223f 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -71,7 +71,7 @@ pub fn parse_def( named: vec![], }); - let call = if let Some(name_span) = spans.get(1) { + if let Some(name_span) = spans.get(1) { let (name_expr, err) = parse_string(working_set, *name_span); error = error.or(err); @@ -142,8 +142,6 @@ pub fn parse_def( )) }); } - - call } else { let err_span = Span { start: name_span.end, @@ -152,8 +150,6 @@ pub fn parse_def( error = error .or_else(|| Some(ParseError::MissingPositional("parameters".into(), err_span))); - - call } } else { let err_span = Span { @@ -167,9 +163,7 @@ pub fn parse_def( err_span, )) }); - - call - }; + } ( Statement::Pipeline(Pipeline::from_vec(vec![Expression { From b6d269e90a6e183f0db2f504f720ea31e85e7447 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 25 Oct 2021 17:01:02 +1300 Subject: [PATCH 05/16] WIP --- Cargo.lock | 67 +++- crates/nu-cli/src/completions.rs | 16 +- .../nu-command/src/conversions/into/binary.rs | 41 +- .../src/conversions/into/command.rs | 10 +- .../src/conversions/into/filesize.rs | 45 +-- crates/nu-command/src/conversions/into/int.rs | 47 +-- crates/nu-command/src/core_commands/alias.rs | 9 +- crates/nu-command/src/core_commands/def.rs | 9 +- crates/nu-command/src/core_commands/do_.rs | 10 +- .../src/core_commands/export_def.rs | 9 +- crates/nu-command/src/core_commands/for_.rs | 34 +- crates/nu-command/src/core_commands/help.rs | 26 +- crates/nu-command/src/core_commands/hide.rs | 9 +- crates/nu-command/src/core_commands/if_.rs | 18 +- crates/nu-command/src/core_commands/let_.rs | 11 +- crates/nu-command/src/core_commands/module.rs | 9 +- crates/nu-command/src/core_commands/source.rs | 13 +- crates/nu-command/src/core_commands/use_.rs | 9 +- crates/nu-command/src/env/let_env.rs | 11 +- crates/nu-command/src/example_test.rs | 14 +- crates/nu-command/src/experimental/git.rs | 14 +- .../src/experimental/git_checkout.rs | 14 +- .../src/experimental/list_git_branches.rs | 16 +- crates/nu-command/src/filesystem/cd.rs | 9 +- crates/nu-command/src/filesystem/cp.rs | 9 +- crates/nu-command/src/filesystem/ls.rs | 120 +++--- crates/nu-command/src/filesystem/mkdir.rs | 13 +- crates/nu-command/src/filesystem/mv.rs | 9 +- crates/nu-command/src/filesystem/rm.rs | 17 +- crates/nu-command/src/filesystem/touch.rs | 9 +- crates/nu-command/src/filters/each.rs | 349 +++++++++--------- crates/nu-command/src/filters/get.rs | 7 +- crates/nu-command/src/filters/length.rs | 33 +- crates/nu-command/src/filters/lines.rs | 23 +- crates/nu-command/src/filters/select.rs | 66 ++-- crates/nu-command/src/filters/where_.rs | 65 ++-- crates/nu-command/src/filters/wrap.rs | 48 ++- crates/nu-command/src/formats/from/command.rs | 9 +- crates/nu-command/src/formats/from/json.rs | 32 +- crates/nu-command/src/strings/build_string.rs | 12 +- crates/nu-command/src/strings/size.rs | 35 +- crates/nu-command/src/strings/split/chars.rs | 16 +- crates/nu-command/src/strings/split/column.rs | 17 +- .../nu-command/src/strings/split/command.rs | 9 +- crates/nu-command/src/strings/split/row.rs | 17 +- crates/nu-command/src/system/benchmark.rs | 16 +- crates/nu-command/src/system/ps.rs | 11 +- crates/nu-command/src/system/run_external.rs | 53 +-- crates/nu-command/src/system/sys.rs | 12 +- crates/nu-command/src/viewers/griddle.rs | 1 + crates/nu-command/src/viewers/table.rs | 1 + crates/nu-engine/src/documentation.rs | 7 +- crates/nu-engine/src/eval.rs | 63 ++-- crates/nu-parser/tests/test_parser.rs | 5 +- crates/nu-protocol/Cargo.toml | 3 +- crates/nu-protocol/src/engine/command.rs | 27 +- crates/nu-protocol/src/engine/engine_state.rs | 80 ++-- .../src/engine/evaluation_context.rs | 112 +++--- crates/nu-protocol/src/lib.rs | 2 + crates/nu-protocol/src/pipeline_data.rs | 62 ++++ crates/nu-protocol/src/signature.rs | 12 +- crates/nu-protocol/src/value/mod.rs | 127 +------ crates/nu-protocol/src/value/stream.rs | 109 +++--- 63 files changed, 1075 insertions(+), 1013 deletions(-) create mode 100644 crates/nu-protocol/src/pipeline_data.rs diff --git a/Cargo.lock b/Cargo.lock index 696b84d35e..f4ea08395e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + [[package]] name = "bstr" version = "0.2.17" @@ -378,6 +387,20 @@ dependencies = [ "libc", ] +[[package]] +name = "im" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111c1983f3c5bb72732df25cddacee9b546d08325fb584b5ebd38148be7b0246" +dependencies = [ + "bitmaps", + "rand_core 0.5.1", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "instant" version = "0.1.11" @@ -640,6 +663,7 @@ dependencies = [ "byte-unit", "chrono", "chrono-humanize", + "im", "miette", "serde", "thiserror", @@ -823,7 +847,7 @@ checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.3", "rand_hc", ] @@ -834,9 +858,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.3", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + [[package]] name = "rand_core" version = "0.6.3" @@ -852,7 +882,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_xoshiro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -1032,6 +1071,16 @@ dependencies = [ "libc", ] +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "smallvec" version = "1.7.0" @@ -1198,6 +1247,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + [[package]] name = "unicode-linebreak" version = "0.1.2" @@ -1237,6 +1292,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + [[package]] name = "vte" version = "0.10.1" diff --git a/crates/nu-cli/src/completions.rs b/crates/nu-cli/src/completions.rs index 5a7009eb2e..0bd47c507b 100644 --- a/crates/nu-cli/src/completions.rs +++ b/crates/nu-cli/src/completions.rs @@ -4,26 +4,25 @@ use nu_engine::eval_block; use nu_parser::{flatten_block, parse}; use nu_protocol::{ engine::{EngineState, EvaluationContext, Stack, StateWorkingSet}, - Value, + PipelineData, Value, }; use reedline::Completer; const SEP: char = std::path::MAIN_SEPARATOR; pub struct NuCompleter { - engine_state: Rc>, + engine_state: Box, } impl NuCompleter { - pub fn new(engine_state: Rc>) -> Self { + pub fn new(engine_state: Box) -> Self { Self { engine_state } } } impl Completer for NuCompleter { fn complete(&self, line: &str, pos: usize) -> Vec<(reedline::Span, String)> { - let engine_state = self.engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&*self.engine_state); let offset = working_set.next_span_start(); let pos = offset + pos; let (output, _err) = parse(&mut working_set, Some("completer"), line.as_bytes(), false); @@ -49,7 +48,7 @@ impl Completer for NuCompleter { } } } - for scope in &engine_state.scope { + for scope in &self.engine_state.scope { for v in &scope.vars { if v.0.starts_with(prefix) { output.push(( @@ -76,11 +75,10 @@ impl Completer for NuCompleter { engine_state: self.engine_state.clone(), stack: Stack::default(), }; - let result = eval_block(&context, &block, Value::nothing()); + let result = eval_block(&context, &block, PipelineData::new()); let v: Vec<_> = match result { - Ok(Value::List { vals, .. }) => vals - .into_iter() + Ok(pd) => pd .map(move |x| { let s = x.as_string().expect( "FIXME: better error handling for custom completions", diff --git a/crates/nu-command/src/conversions/into/binary.rs b/crates/nu-command/src/conversions/into/binary.rs index 4778d1c07f..0658cdb0e3 100644 --- a/crates/nu-command/src/conversions/into/binary.rs +++ b/crates/nu-command/src/conversions/into/binary.rs @@ -1,9 +1,10 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, ShellError, Signature, Span, SyntaxShape, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -27,8 +28,8 @@ impl Command for SubCommand { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { into_binary(context, call, input) } @@ -86,26 +87,28 @@ impl Command for SubCommand { fn into_binary( _context: &EvaluationContext, call: &Call, - input: Value, -) -> Result { + input: PipelineData, +) -> Result { let head = call.head; // let column_paths: Vec = call.rest(context, 0)?; - input.map(head, move |v| { - action(v, head) - // FIXME: Add back in cell_path support - // if column_paths.is_empty() { - // action(v, head) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = - // ret.swap_data_by_cell_path(path, Box::new(move |old| action(old, old.tag())))?; - // } + Ok(input + .map(move |v| { + action(v, head) + // FIXME: Add back in cell_path support + // if column_paths.is_empty() { + // action(v, head) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = + // ret.swap_data_by_cell_path(path, Box::new(move |old| action(old, old.tag())))?; + // } - // Ok(ret) - // } - }) + // Ok(ret) + // } + }) + .into_pipeline_data()) } fn int_to_endian(n: i64) -> Vec { diff --git a/crates/nu-command/src/conversions/into/command.rs b/crates/nu-command/src/conversions/into/command.rs index f74c6436c1..37741e7f4a 100644 --- a/crates/nu-command/src/conversions/into/command.rs +++ b/crates/nu-command/src/conversions/into/command.rs @@ -2,9 +2,10 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Signature, Value, + IntoPipelineData, PipelineData, Signature, Value, }; +#[derive(Clone)] pub struct Into; impl Command for Into { @@ -24,12 +25,13 @@ impl Command for Into { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { Ok(Value::String { val: get_full_help(&Into.signature(), &[], context), span: call.head, - }) + } + .into_pipeline_data()) } } diff --git a/crates/nu-command/src/conversions/into/filesize.rs b/crates/nu-command/src/conversions/into/filesize.rs index 1e1b730071..bb2a2a8135 100644 --- a/crates/nu-command/src/conversions/into/filesize.rs +++ b/crates/nu-command/src/conversions/into/filesize.rs @@ -1,9 +1,10 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, ShellError, Signature, Span, SyntaxShape, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -27,8 +28,8 @@ impl Command for SubCommand { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { into_filesize(context, call, input) } @@ -114,29 +115,31 @@ impl Command for SubCommand { fn into_filesize( _context: &EvaluationContext, call: &Call, - input: Value, -) -> Result { + input: PipelineData, +) -> Result { let head = call.head; // let call_paths: Vec = args.rest(0)?; - input.map(head, move |v| { - action(v, head) + Ok(input + .map(move |v| { + action(v, head) - // FIXME: Add back cell_path support - // if column_paths.is_empty() { - // action(&v, v.tag()) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = ret.swap_data_by_column_path( - // path, - // Box::new(move |old| action(old, old.tag())), - // )?; - // } + // FIXME: Add back cell_path support + // if column_paths.is_empty() { + // action(&v, v.tag()) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = ret.swap_data_by_column_path( + // path, + // Box::new(move |old| action(old, old.tag())), + // )?; + // } - // Ok(ret) - // } - }) + // Ok(ret) + // } + }) + .into_pipeline_data()) } pub fn action(input: Value, span: Span) -> Value { diff --git a/crates/nu-command/src/conversions/into/int.rs b/crates/nu-command/src/conversions/into/int.rs index f53aee0833..b0b29a2dc7 100644 --- a/crates/nu-command/src/conversions/into/int.rs +++ b/crates/nu-command/src/conversions/into/int.rs @@ -1,9 +1,10 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, IntoValueStream, ShellError, Signature, Span, SyntaxShape, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -27,8 +28,8 @@ impl Command for SubCommand { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { into_int(context, call, input) } @@ -78,10 +79,8 @@ impl Command for SubCommand { Example { description: "Convert bool to integer", example: "[$false, $true] | into int", - result: Some(Value::Stream { - stream: vec![Value::test_int(0), Value::test_int(1)] - .into_iter() - .into_value_stream(), + result: Some(Value::List { + vals: vec![Value::test_int(0), Value::test_int(1)], span: Span::unknown(), }), }, @@ -92,26 +91,28 @@ impl Command for SubCommand { fn into_int( _context: &EvaluationContext, call: &Call, - input: Value, -) -> Result { + input: PipelineData, +) -> Result { let head = call.head; // let column_paths: Vec = call.rest(context, 0)?; - input.map(head, move |v| { - action(v, head) - // FIXME: Add back cell_path support - // if column_paths.is_empty() { - // action(&v, v.tag()) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = ret - // .swap_data_by_column_path(path, Box::new(move |old| action(old, old.tag())))?; - // } + Ok(input + .map(move |v| { + action(v, head) + // FIXME: Add back cell_path support + // if column_paths.is_empty() { + // action(&v, v.tag()) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = ret + // .swap_data_by_column_path(path, Box::new(move |old| action(old, old.tag())))?; + // } - // Ok(ret) - // } - }) + // Ok(ret) + // } + }) + .into_pipeline_data()) } pub fn action(input: Value, span: Span) -> Value { diff --git a/crates/nu-command/src/core_commands/alias.rs b/crates/nu-command/src/core_commands/alias.rs index 91beec2fda..971d04443f 100644 --- a/crates/nu-command/src/core_commands/alias.rs +++ b/crates/nu-command/src/core_commands/alias.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Alias; impl Command for Alias { @@ -27,8 +28,8 @@ impl Command for Alias { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/def.rs b/crates/nu-command/src/core_commands/def.rs index 0f6ef1b56b..4d3808bc71 100644 --- a/crates/nu-command/src/core_commands/def.rs +++ b/crates/nu-command/src/core_commands/def.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Def; impl Command for Def { @@ -28,8 +29,8 @@ impl Command for Def { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/do_.rs b/crates/nu-command/src/core_commands/do_.rs index ab4c97d859..8bc4435d7c 100644 --- a/crates/nu-command/src/core_commands/do_.rs +++ b/crates/nu-command/src/core_commands/do_.rs @@ -1,8 +1,9 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Do; impl Command for Do { @@ -29,15 +30,14 @@ impl Command for Do { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let block_id = call.positional[0] .as_block() .expect("internal error: expected block"); let rest: Vec = call.rest(context, 1)?; - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + let block = context.engine_state.get_block(block_id); let state = context.enter_scope(); diff --git a/crates/nu-command/src/core_commands/export_def.rs b/crates/nu-command/src/core_commands/export_def.rs index b82418c486..2ab2430b15 100644 --- a/crates/nu-command/src/core_commands/export_def.rs +++ b/crates/nu-command/src/core_commands/export_def.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct ExportDef; impl Command for ExportDef { @@ -28,8 +29,8 @@ impl Command for ExportDef { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index bd995ce99c..5ce82dc60c 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -1,8 +1,9 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; +#[derive(Clone)] pub struct For; impl Command for For { @@ -38,8 +39,8 @@ impl Command for For { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let var_id = call.positional[0] .as_var() .expect("internal error: missing variable"); @@ -55,19 +56,26 @@ impl Command for For { let context = context.clone(); - values.map(call.head, move |x| { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block); + match values { + Value::List { vals, span } => Ok(vals + .into_iter() + .map(move |x| { + let block = context.engine_state.get_block(block); - let state = context.enter_scope(); + let state = context.enter_scope(); - state.add_var(var_id, x); + state.add_var(var_id, x); - match eval_block(&state, block, Value::nothing()) { - Ok(value) => value, - Err(error) => Value::Error { error }, - } - }) + match eval_block(&state, block, PipelineData::new()) { + Ok(value) => Value::List { + vals: value.collect(), + span, + }, + Err(error) => Value::Error { error }, + } + }) + .into_pipeline_data()), + } } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/core_commands/help.rs b/crates/nu-command/src/core_commands/help.rs index 6bc36ef542..dc96f3bc48 100644 --- a/crates/nu-command/src/core_commands/help.rs +++ b/crates/nu-command/src/core_commands/help.rs @@ -1,11 +1,13 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - span, Example, ShellError, Signature, Spanned, SyntaxShape, Value, + span, Example, IntoPipelineData, PipelineData, ShellError, Signature, Spanned, SyntaxShape, + Value, }; use nu_engine::{get_full_help, CallExt}; +#[derive(Clone)] pub struct Help; impl Command for Help { @@ -36,8 +38,8 @@ impl Command for Help { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { help(context, call) } @@ -72,7 +74,7 @@ impl Command for Help { } } -fn help(context: &EvaluationContext, call: &Call) -> Result { +fn help(context: &EvaluationContext, call: &Call) -> Result { let head = call.head; let find: Option> = call.get_flag(context, "find")?; let rest: Vec> = call.rest(context, 0)?; @@ -114,10 +116,7 @@ fn help(context: &EvaluationContext, call: &Call) -> Result { } } - return Ok(Value::List { - vals: found_cmds_vec, - span: head, - }); + return Ok(found_cmds_vec.into_iter().into_pipeline_data()); } if !rest.is_empty() { @@ -151,10 +150,7 @@ fn help(context: &EvaluationContext, call: &Call) -> Result { }); } - Ok(Value::List { - vals: found_cmds_vec, - span: head, - }) + Ok(found_cmds_vec.into_iter().into_pipeline_data()) } else { let mut name = String::new(); let mut output = String::new(); @@ -177,7 +173,8 @@ fn help(context: &EvaluationContext, call: &Call) -> Result { Ok(Value::String { val: output, span: call.head, - }) + } + .into_pipeline_data()) } else { Err(ShellError::CommandNotFound(span(&[ rest[0].span, @@ -355,7 +352,8 @@ You can also learn more at https://www.nushell.sh/book/"#; Ok(Value::String { val: msg.into(), span: head, - }) + } + .into_pipeline_data()) } } diff --git a/crates/nu-command/src/core_commands/hide.rs b/crates/nu-command/src/core_commands/hide.rs index 9c9d611e12..dcfe345497 100644 --- a/crates/nu-command/src/core_commands/hide.rs +++ b/crates/nu-command/src/core_commands/hide.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Hide; impl Command for Hide { @@ -21,8 +22,8 @@ impl Command for Hide { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/if_.rs b/crates/nu-command/src/core_commands/if_.rs index fdb103dac0..16217142d0 100644 --- a/crates/nu-command/src/core_commands/if_.rs +++ b/crates/nu-command/src/core_commands/if_.rs @@ -1,8 +1,9 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct If; impl Command for If { @@ -29,8 +30,8 @@ impl Command for If { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let cond = &call.positional[0]; let then_block = call.positional[1] .as_block() @@ -40,25 +41,24 @@ impl Command for If { let result = eval_expression(context, cond)?; match result { Value::Bool { val, span } => { - let engine_state = context.engine_state.borrow(); if val { - let block = engine_state.get_block(then_block); + let block = context.engine_state.get_block(then_block); let state = context.enter_scope(); eval_block(&state, block, input) } else if let Some(else_case) = else_case { if let Some(else_expr) = else_case.as_keyword() { if let Some(block_id) = else_expr.as_block() { - let block = engine_state.get_block(block_id); + let block = context.engine_state.get_block(block_id); let state = context.enter_scope(); eval_block(&state, block, input) } else { - eval_expression(context, else_expr) + eval_expression(context, else_expr).map(|x| x.into_pipeline_data()) } } else { - eval_expression(context, else_case) + eval_expression(context, else_case).map(|x| x.into_pipeline_data()) } } else { - Ok(Value::Nothing { span }) + Ok(PipelineData::new()) } } _ => Err(ShellError::CantConvert("bool".into(), result.span()?)), diff --git a/crates/nu-command/src/core_commands/let_.rs b/crates/nu-command/src/core_commands/let_.rs index 6e3a2d2fd3..64a7437b0a 100644 --- a/crates/nu-command/src/core_commands/let_.rs +++ b/crates/nu-command/src/core_commands/let_.rs @@ -1,8 +1,9 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Let; impl Command for Let { @@ -28,8 +29,8 @@ impl Command for Let { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let var_id = call.positional[0] .as_var() .expect("internal error: missing variable"); @@ -43,8 +44,6 @@ impl Command for Let { //println!("Adding: {:?} to {}", rhs, var_id); context.add_var(var_id, rhs); - Ok(Value::Nothing { - span: call.positional[0].span, - }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/module.rs b/crates/nu-command/src/core_commands/module.rs index e2cec960d8..d7e59882ac 100644 --- a/crates/nu-command/src/core_commands/module.rs +++ b/crates/nu-command/src/core_commands/module.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Module; impl Command for Module { @@ -27,8 +28,8 @@ impl Command for Module { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index aacd3564cd..17881b2152 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,9 +1,10 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; /// Source a file for environment variables. +#[derive(Clone)] pub struct Source; impl Command for Source { @@ -27,17 +28,13 @@ impl Command for Source { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { // Note: this hidden positional is the block_id that corresponded to the 0th position // it is put here by the parser let block_id: i64 = call.req(context, 1)?; - let block = context - .engine_state - .borrow() - .get_block(block_id as usize) - .clone(); + let block = context.engine_state.get_block(block_id as usize).clone(); eval_block(context, &block, input) } } diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index 3cfae2e49d..ed3781b385 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Use; impl Command for Use { @@ -21,8 +22,8 @@ impl Command for Use { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { - Ok(Value::Nothing { span: call.head }) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/env/let_env.rs b/crates/nu-command/src/env/let_env.rs index 39ed4800ed..112cfa40df 100644 --- a/crates/nu-command/src/env/let_env.rs +++ b/crates/nu-command/src/env/let_env.rs @@ -1,8 +1,9 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct LetEnv; impl Command for LetEnv { @@ -28,8 +29,8 @@ impl Command for LetEnv { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let env_var = call.positional[0] .as_string() .expect("internal error: missing variable"); @@ -44,8 +45,6 @@ impl Command for LetEnv { //println!("Adding: {:?} to {}", rhs, var_id); context.add_env_var(env_var, rhs); - Ok(Value::Nothing { - span: call.positional[0].span, - }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index 621d5540e2..8b41ead793 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -4,19 +4,18 @@ use nu_engine::eval_block; use nu_parser::parse; use nu_protocol::{ engine::{Command, EngineState, EvaluationContext, StateWorkingSet}, - Value, + PipelineData, Value, }; use super::{From, Into, Split}; pub fn test_examples(cmd: impl Command + 'static) { let examples = cmd.examples(); - let engine_state = Rc::new(RefCell::new(EngineState::new())); + let mut engine_state = Box::new(EngineState::new()); let delta = { // Base functions that are needed for testing // Try to keep this working set small to keep tests running as fast as possible - let engine_state = engine_state.borrow(); let mut working_set = StateWorkingSet::new(&*engine_state); working_set.add_decl(Box::new(From)); working_set.add_decl(Box::new(Into)); @@ -28,7 +27,7 @@ pub fn test_examples(cmd: impl Command + 'static) { working_set.render() }; - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + EngineState::merge_delta(&mut *engine_state, delta); for example in examples { // Skip tests that don't have results to compare to @@ -38,7 +37,7 @@ pub fn test_examples(cmd: impl Command + 'static) { let start = std::time::Instant::now(); let (block, delta) = { - let engine_state = engine_state.borrow(); + let engine_state = engine_state; let mut working_set = StateWorkingSet::new(&*engine_state); let (output, err) = parse(&mut working_set, None, example.example.as_bytes(), false); @@ -49,16 +48,17 @@ pub fn test_examples(cmd: impl Command + 'static) { (output, working_set.render()) }; - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + EngineState::merge_delta(&mut *engine_state, delta); let state = EvaluationContext { engine_state: engine_state.clone(), stack: nu_protocol::engine::Stack::new(), }; - match eval_block(&state, &block, Value::nothing()) { + match eval_block(&state, &block, PipelineData::new()) { Err(err) => panic!("test eval error in `{}`: {:?}", example.example, err), Ok(result) => { + let result = result.into_value(); println!("input: {}", example.example); println!("result: {:?}", result); println!("done: {:?}", start.elapsed()); diff --git a/crates/nu-command/src/experimental/git.rs b/crates/nu-command/src/experimental/git.rs index cef4a27db0..57fe52c218 100644 --- a/crates/nu-command/src/experimental/git.rs +++ b/crates/nu-command/src/experimental/git.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; +#[derive(Clone)] pub struct Git; impl Command for Git { @@ -21,8 +22,8 @@ impl Command for Git { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { use std::process::Command as ProcessCommand; use std::process::Stdio; @@ -37,17 +38,18 @@ impl Command for Git { Ok(Value::String { val: String::from_utf8_lossy(&result).to_string(), span: call.head, - }) + } + .into_pipeline_data()) } Err(_err) => { // FIXME: Move this to an external signature and add better error handling - Ok(Value::nothing()) + Ok(PipelineData::new()) } } } Err(_err) => { // FIXME: Move this to an external signature and add better error handling - Ok(Value::nothing()) + Ok(PipelineData::new()) } } } diff --git a/crates/nu-command/src/experimental/git_checkout.rs b/crates/nu-command/src/experimental/git_checkout.rs index d25d607d7b..02b1ac01a5 100644 --- a/crates/nu-command/src/experimental/git_checkout.rs +++ b/crates/nu-command/src/experimental/git_checkout.rs @@ -1,8 +1,9 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct GitCheckout; impl Command for GitCheckout { @@ -26,8 +27,8 @@ impl Command for GitCheckout { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { use std::process::Command as ProcessCommand; use std::process::Stdio; @@ -52,17 +53,18 @@ impl Command for GitCheckout { Ok(Value::String { val: String::from_utf8_lossy(&result).to_string(), span: call.head, - }) + } + .into_pipeline_data()) } Err(_err) => { // FIXME: Move this to an external signature and add better error handling - Ok(Value::nothing()) + Ok(PipelineData::new()) } } } Err(_err) => { // FIXME: Move this to an external signature and add better error handling - Ok(Value::nothing()) + Ok(PipelineData::new()) } } } diff --git a/crates/nu-command/src/experimental/list_git_branches.rs b/crates/nu-command/src/experimental/list_git_branches.rs index 3a0a148925..065b5bf2c0 100644 --- a/crates/nu-command/src/experimental/list_git_branches.rs +++ b/crates/nu-command/src/experimental/list_git_branches.rs @@ -5,8 +5,11 @@ use std::process::Stdio; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::IntoPipelineData; +use nu_protocol::PipelineData; use nu_protocol::{Signature, Value}; +#[derive(Clone)] pub struct ListGitBranches; //NOTE: this is not a real implementation :D. It's just a simple one to test with until we port the real one. @@ -27,8 +30,8 @@ impl Command for ListGitBranches { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let list_branches = ProcessCommand::new("git") .arg("branch") .stdout(Stdio::piped()) @@ -55,15 +58,12 @@ impl Command for ListGitBranches { }) .collect(); - Ok(Value::List { - vals: lines, - span: call.head, - }) + Ok(lines.into_iter().into_pipeline_data()) } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } } diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 919e11e021..cbde266c49 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,8 +1,9 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Cd; impl Command for Cd { @@ -22,8 +23,8 @@ impl Command for Cd { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let path: Option = call.opt(context, 0)?; let path = match path { @@ -41,6 +42,6 @@ impl Command for Cd { //FIXME: this only changes the current scope, but instead this environment variable //should probably be a block that loads the information from the state in the overlay context.add_env_var("PWD".into(), path); - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 80d2b39552..71d5a255ac 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -6,10 +6,11 @@ use nu_engine::CallExt; use nu_path::canonicalize_with; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; use crate::filesystem::util::FileStructure; +#[derive(Clone)] pub struct Cp; #[allow(unused_must_use)] @@ -39,8 +40,8 @@ impl Command for Cp { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let source: String = call.req(context, 0)?; let destination: String = call.req(context, 1)?; let interactive = call.has_flag("interactive"); @@ -202,6 +203,6 @@ impl Command for Cp { } } - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/filesystem/ls.rs b/crates/nu-command/src/filesystem/ls.rs index 36fbaff74a..8c35698bb2 100644 --- a/crates/nu-command/src/filesystem/ls.rs +++ b/crates/nu-command/src/filesystem/ls.rs @@ -2,8 +2,9 @@ use chrono::{DateTime, Utc}; use nu_engine::eval_expression; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{IntoValueStream, Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Ls; //NOTE: this is not a real implementation :D. It's just a simple one to test with until we port the real one. @@ -28,8 +29,8 @@ impl Command for Ls { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let pattern = if let Some(expr) = call.positional.get(0) { let result = eval_expression(context, expr)?; let mut result = result.as_string()?; @@ -50,69 +51,66 @@ impl Command for Ls { let call_span = call.head; let glob = glob::glob(&pattern).unwrap(); - Ok(Value::Stream { - stream: glob - .into_iter() - .map(move |x| match x { - Ok(path) => match std::fs::symlink_metadata(&path) { - Ok(metadata) => { - let is_file = metadata.is_file(); - let is_dir = metadata.is_dir(); - let filesize = metadata.len(); + Ok(glob + .into_iter() + .map(move |x| match x { + Ok(path) => match std::fs::symlink_metadata(&path) { + Ok(metadata) => { + let is_file = metadata.is_file(); + let is_dir = metadata.is_dir(); + let filesize = metadata.len(); - let mut cols = vec!["name".into(), "type".into(), "size".into()]; + let mut cols = vec!["name".into(), "type".into(), "size".into()]; - let mut vals = vec![ - Value::String { - val: path.to_string_lossy().to_string(), - span: call_span, - }, - if is_file { - Value::string("File", call_span) - } else if is_dir { - Value::string("Dir", call_span) - } else { - Value::Nothing { span: call_span } - }, - Value::Filesize { - val: filesize as i64, - span: call_span, - }, - ]; - - if let Ok(date) = metadata.modified() { - let utc: DateTime = date.into(); - - cols.push("modified".into()); - vals.push(Value::Date { - val: utc.into(), - span: call_span, - }); - } - - Value::Record { - cols, - vals, + let mut vals = vec![ + Value::String { + val: path.to_string_lossy().to_string(), span: call_span, - } + }, + if is_file { + Value::string("File", call_span) + } else if is_dir { + Value::string("Dir", call_span) + } else { + Value::Nothing { span: call_span } + }, + Value::Filesize { + val: filesize as i64, + span: call_span, + }, + ]; + + if let Ok(date) = metadata.modified() { + let utc: DateTime = date.into(); + + cols.push("modified".into()); + vals.push(Value::Date { + val: utc.into(), + span: call_span, + }); } - Err(_) => Value::Record { - cols: vec!["name".into(), "type".into(), "size".into()], - vals: vec![ - Value::String { - val: path.to_string_lossy().to_string(), - span: call_span, - }, - Value::Nothing { span: call_span }, - Value::Nothing { span: call_span }, - ], + + Value::Record { + cols, + vals, span: call_span, - }, + } + } + Err(_) => Value::Record { + cols: vec!["name".into(), "type".into(), "size".into()], + vals: vec![ + Value::String { + val: path.to_string_lossy().to_string(), + span: call_span, + }, + Value::Nothing { span: call_span }, + Value::Nothing { span: call_span }, + ], + span: call_span, }, - _ => Value::Nothing { span: call_span }, - }) - .into_value_stream(), - span: call_span, - }) + }, + _ => Value::Nothing { span: call_span }, + }) + .into_pipeline_data()) } } diff --git a/crates/nu-command/src/filesystem/mkdir.rs b/crates/nu-command/src/filesystem/mkdir.rs index 5635c85538..43990605b6 100644 --- a/crates/nu-command/src/filesystem/mkdir.rs +++ b/crates/nu-command/src/filesystem/mkdir.rs @@ -4,8 +4,11 @@ use std::env::current_dir; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value, ValueStream}; +use nu_protocol::{ + IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, +}; +#[derive(Clone)] pub struct Mkdir; impl Command for Mkdir { @@ -31,8 +34,8 @@ impl Command for Mkdir { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let path = current_dir()?; let mut directories = call .rest::(context, 0)? @@ -67,8 +70,6 @@ impl Command for Mkdir { } } - let stream = ValueStream::from_stream(stream.into_iter()); - let span = call.head; - Ok(Value::Stream { stream, span }) + Ok(stream.into_iter().into_pipeline_data()) } } diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index c9f46cd874..ba709729e1 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -5,8 +5,9 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Mv; #[allow(unused_must_use)] @@ -39,8 +40,8 @@ impl Command for Mv { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { // TODO: handle invalid directory or insufficient permissions when moving let source: String = call.req(context, 0)?; let destination: String = call.req(context, 1)?; @@ -128,7 +129,7 @@ impl Command for Mv { move_file(call, &entry, &destination)? } - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 0beb63f153..d64764d780 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -8,8 +8,11 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value, ValueStream}; +use nu_protocol::{ + IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, +}; +#[derive(Clone)] pub struct Rm; // Where self.0 is the unexpanded target's positional index (i.e. call.positional[self.0].span) @@ -58,13 +61,13 @@ impl Command for Rm { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { rm(context, call) } } -fn rm(context: &EvaluationContext, call: &Call) -> Result { +fn rm(context: &EvaluationContext, call: &Call) -> Result { let trash = call.has_flag("trash"); let permanent = call.has_flag("permanent"); let interactive = call.has_flag("interactive"); @@ -164,11 +167,7 @@ fn rm(context: &EvaluationContext, call: &Call) -> Result { // let temp = rm_helper(call, args).flatten(); // let temp = input.flatten(call.head, move |_| rm_helper(call, args)); - Ok(Value::Stream { - stream: ValueStream::from_stream(response.into_iter()), - span: call.head, - }) - + Ok(response.into_iter().into_pipeline_data()) // Ok(Value::Nothing { span }) } diff --git a/crates/nu-command/src/filesystem/touch.rs b/crates/nu-command/src/filesystem/touch.rs index bb23d47189..3d323c71db 100644 --- a/crates/nu-command/src/filesystem/touch.rs +++ b/crates/nu-command/src/filesystem/touch.rs @@ -3,8 +3,9 @@ use std::fs::OpenOptions; use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Touch; impl Command for Touch { @@ -30,8 +31,8 @@ impl Command for Touch { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let target: String = call.req(context, 0)?; let rest: Vec = call.rest(context, 1)?; @@ -47,6 +48,6 @@ impl Command for Touch { } } - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index f2e6de61f1..7293e9c9e0 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -1,8 +1,9 @@ use nu_engine::eval_block; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, IntoValueStream, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{Example, PipelineData, Signature, Span, SyntaxShape, Value}; +#[derive(Clone)] pub struct Each; impl Command for Each { @@ -43,8 +44,8 @@ impl Command for Each { vec![Example { example: "[1 2 3] | each { 2 * $it }", description: "Multiplies elements in list", - result: Some(Value::Stream { - stream: stream_test_1.into_iter().into_value_stream(), + result: Some(Value::List { + vals: stream_test_1, span: Span::unknown(), }), }] @@ -54,8 +55,8 @@ impl Command for Each { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let block_id = call.positional[0] .as_block() .expect("internal error: expected block"); @@ -64,190 +65,186 @@ impl Command for Each { let context = context.clone(); let span = call.head; - match input { - Value::Range { val, .. } => Ok(Value::Stream { - stream: val - .into_range_iter()? - .enumerate() - .map(move |(idx, x)| { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + // match input { + // Value::Range { val, .. } => Ok(val + // .into_range_iter()? + // .enumerate() + // .map(move |(idx, x)| { + // let block = context.engine_state.get_block(block_id); - let state = context.enter_scope(); + // let state = context.enter_scope(); - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - if numbered { - state.add_var( - *var_id, - Value::Record { - cols: vec!["index".into(), "item".into()], - vals: vec![ - Value::Int { - val: idx as i64, - span, - }, - x, - ], - span, - }, - ); - } else { - state.add_var(*var_id, x); - } - } - } + // if let Some(var) = block.signature.get_positional(0) { + // if let Some(var_id) = &var.var_id { + // if numbered { + // state.add_var( + // *var_id, + // Value::Record { + // cols: vec!["index".into(), "item".into()], + // vals: vec![ + // Value::Int { + // val: idx as i64, + // span, + // }, + // x, + // ], + // span, + // }, + // ); + // } else { + // state.add_var(*var_id, x); + // } + // } + // } - match eval_block(&state, block, Value::nothing()) { - Ok(v) => v, - Err(error) => Value::Error { error }, - } - }) - .into_value_stream(), - span: call.head, - }), - Value::List { vals: val, .. } => Ok(Value::Stream { - stream: val - .into_iter() - .enumerate() - .map(move |(idx, x)| { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + // match eval_block(&state, block, Value::nothing()) { + // Ok(v) => v, + // Err(error) => Value::Error { error }, + // } + // }) + // .into_pipeline_data()), + // Value::List { vals: val, .. } => Ok(Value::Stream { + // stream: val + // .into_iter() + // .enumerate() + // .map(move |(idx, x)| { + // let engine_state = context.engine_state.borrow(); + // let block = engine_state.get_block(block_id); - let state = context.enter_scope(); - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - if numbered { - state.add_var( - *var_id, - Value::Record { - cols: vec!["index".into(), "item".into()], - vals: vec![ - Value::Int { - val: idx as i64, - span, - }, - x, - ], - span, - }, - ); - } else { - state.add_var(*var_id, x); - } - } - } + // let state = context.enter_scope(); + // if let Some(var) = block.signature.get_positional(0) { + // if let Some(var_id) = &var.var_id { + // if numbered { + // state.add_var( + // *var_id, + // Value::Record { + // cols: vec!["index".into(), "item".into()], + // vals: vec![ + // Value::Int { + // val: idx as i64, + // span, + // }, + // x, + // ], + // span, + // }, + // ); + // } else { + // state.add_var(*var_id, x); + // } + // } + // } - match eval_block(&state, block, Value::nothing()) { - Ok(v) => v, - Err(error) => Value::Error { error }, - } - }) - .into_value_stream(), - span: call.head, - }), - Value::Stream { stream, .. } => Ok(Value::Stream { - stream: stream - .enumerate() - .map(move |(idx, x)| { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + // match eval_block(&state, block, Value::nothing()) { + // Ok(v) => v, + // Err(error) => Value::Error { error }, + // } + // }) + // .into_value_stream(), + // span: call.head, + // }), + // Value::Stream { stream, .. } => Ok(Value::Stream { + // stream: stream + // .enumerate() + // .map(move |(idx, x)| { + // let engine_state = context.engine_state.borrow(); + // let block = engine_state.get_block(block_id); - let state = context.enter_scope(); - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - if numbered { - state.add_var( - *var_id, - Value::Record { - cols: vec!["index".into(), "item".into()], - vals: vec![ - Value::Int { - val: idx as i64, - span, - }, - x, - ], - span, - }, - ); - } else { - state.add_var(*var_id, x); - } - } - } + // let state = context.enter_scope(); + // if let Some(var) = block.signature.get_positional(0) { + // if let Some(var_id) = &var.var_id { + // if numbered { + // state.add_var( + // *var_id, + // Value::Record { + // cols: vec!["index".into(), "item".into()], + // vals: vec![ + // Value::Int { + // val: idx as i64, + // span, + // }, + // x, + // ], + // span, + // }, + // ); + // } else { + // state.add_var(*var_id, x); + // } + // } + // } - match eval_block(&state, block, Value::nothing()) { - Ok(v) => v, - Err(error) => Value::Error { error }, - } - }) - .into_value_stream(), - span: call.head, - }), - Value::Record { cols, vals, .. } => { - let mut output_cols = vec![]; - let mut output_vals = vec![]; + // match eval_block(&state, block, Value::nothing()) { + // Ok(v) => v, + // Err(error) => Value::Error { error }, + // } + // }) + // .into_value_stream(), + // span: call.head, + // }), + // Value::Record { cols, vals, .. } => { + // let mut output_cols = vec![]; + // let mut output_vals = vec![]; - for (col, val) in cols.into_iter().zip(vals.into_iter()) { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + // for (col, val) in cols.into_iter().zip(vals.into_iter()) { + // let engine_state = context.engine_state.borrow(); + // let block = engine_state.get_block(block_id); - let state = context.enter_scope(); - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - state.add_var( - *var_id, - Value::Record { - cols: vec!["column".into(), "value".into()], - vals: vec![ - Value::String { - val: col.clone(), - span: call.head, - }, - val, - ], - span: call.head, - }, - ); - } - } + // let state = context.enter_scope(); + // if let Some(var) = block.signature.get_positional(0) { + // if let Some(var_id) = &var.var_id { + // state.add_var( + // *var_id, + // Value::Record { + // cols: vec!["column".into(), "value".into()], + // vals: vec![ + // Value::String { + // val: col.clone(), + // span: call.head, + // }, + // val, + // ], + // span: call.head, + // }, + // ); + // } + // } - match eval_block(&state, block, Value::nothing())? { - Value::Record { - mut cols, mut vals, .. - } => { - // TODO check that the lengths match when traversing record - output_cols.append(&mut cols); - output_vals.append(&mut vals); - } - x => { - output_cols.push(col); - output_vals.push(x); - } - } - } + // match eval_block(&state, block, Value::nothing())? { + // Value::Record { + // mut cols, mut vals, .. + // } => { + // // TODO check that the lengths match when traversing record + // output_cols.append(&mut cols); + // output_vals.append(&mut vals); + // } + // x => { + // output_cols.push(col); + // output_vals.push(x); + // } + // } + // } - Ok(Value::Record { - cols: output_cols, - vals: output_vals, - span: call.head, - }) - } - x => { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block_id); + // Ok(Value::Record { + // cols: output_cols, + // vals: output_vals, + // span: call.head, + // }) + // } + // x => { + // let engine_state = context.engine_state.borrow(); + // let block = engine_state.get_block(block_id); - let state = context.enter_scope(); - if let Some(var) = block.signature.get_positional(0) { - if let Some(var_id) = &var.var_id { - state.add_var(*var_id, x); - } - } + // let state = context.enter_scope(); + // if let Some(var) = block.signature.get_positional(0) { + // if let Some(var_id) = &var.var_id { + // state.add_var(*var_id, x); + // } + // } - eval_block(&state, block, Value::nothing()) - } - } + // eval_block(&state, block, Value::nothing()) + // } + // } } } diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index 7ad1c12823..9cf3dd7963 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -1,8 +1,9 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Get; impl Command for Get { @@ -26,8 +27,8 @@ impl Command for Get { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let cell_path: CellPath = call.req(context, 0)?; input.follow_cell_path(&cell_path.members) diff --git a/crates/nu-command/src/filters/length.rs b/crates/nu-command/src/filters/length.rs index d2c33fad5b..5c7967fe8e 100644 --- a/crates/nu-command/src/filters/length.rs +++ b/crates/nu-command/src/filters/length.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; +#[derive(Clone)] pub struct Length; impl Command for Length { @@ -21,33 +22,19 @@ impl Command for Length { &self, _context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { match input { - Value::List { vals: val, .. } => { - let length = val.len(); - - Ok(Value::Int { - val: length as i64, - span: call.head, - }) - } - Value::Stream { stream, .. } => { - let length = stream.count(); - - Ok(Value::Int { - val: length as i64, - span: call.head, - }) - } - Value::Nothing { .. } => Ok(Value::Int { + PipelineData::Value(Value::Nothing { .. }) => Ok(Value::Int { val: 0, span: call.head, - }), + } + .into_pipeline_data()), _ => Ok(Value::Int { - val: 1, + val: input.count() as i64, span: call.head, - }), + } + .into_pipeline_data()), } } } diff --git a/crates/nu-command/src/filters/lines.rs b/crates/nu-command/src/filters/lines.rs index 2a32b54ca6..ec59b9d619 100644 --- a/crates/nu-command/src/filters/lines.rs +++ b/crates/nu-command/src/filters/lines.rs @@ -3,8 +3,9 @@ use std::rc::Rc; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, Value, ValueStream}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Value, ValueStream}; +#[derive(Clone)] pub struct Lines; const SPLIT_CHAR: char = '\n'; @@ -26,15 +27,15 @@ impl Command for Lines { &self, _context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let span = call.head; match input { #[allow(clippy::needless_collect)] // Collect is needed because the string may not live long enough for // the Rc structure to continue using it. If split could take ownership // of the split values, then this wouldn't be needed - Value::String { val, span } => { + PipelineData::Value(Value::String { val, span }) => { let lines = val .split(SPLIT_CHAR) .map(|s| s.to_string()) @@ -48,12 +49,9 @@ impl Command for Lines { } }); - Ok(Value::Stream { - stream: ValueStream(Rc::new(RefCell::new(iter))), - span, - }) + Ok(iter.into_pipeline_data()) } - Value::Stream { stream, span: _ } => { + PipelineData::Stream(stream) => { let iter = stream .into_iter() .filter_map(|value| { @@ -79,12 +77,9 @@ impl Command for Lines { }) .flatten(); - Ok(Value::Stream { - stream: ValueStream(Rc::new(RefCell::new(iter))), - span, - }) + Ok(iter.into_pipeline_data()) } - val => Err(ShellError::UnsupportedInput( + PipelineData::Value(val) => Err(ShellError::UnsupportedInput( format!("Not supported input: {}", val.as_string()?), call.head, )), diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 7a828aca5f..6849c545c1 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -1,8 +1,11 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, IntoValueStream, ShellError, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{ + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, +}; +#[derive(Clone)] pub struct Select; impl Command for Select { @@ -26,8 +29,8 @@ impl Command for Select { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let columns: Vec = call.rest(context, 0)?; let span = call.head; @@ -50,16 +53,20 @@ impl Command for Select { } } -fn select(span: Span, columns: Vec, input: Value) -> Result { +fn select( + span: Span, + columns: Vec, + input: PipelineData, +) -> Result { if columns.is_empty() { - return Err(ShellError::CantFindColumn(span, input.span()?)); + return Err(ShellError::CantFindColumn(span, span)); //FIXME? } match input { - Value::List { + PipelineData::Value(Value::List { vals: input_vals, span, - } => { + }) => { let mut output = vec![]; for input_val in input_vals { @@ -76,33 +83,30 @@ fn select(span: Span, columns: Vec, input: Value) -> Result Ok(Value::Stream { - stream: stream - .map(move |x| { - let mut cols = vec![]; - let mut vals = vec![]; - for path in &columns { - //FIXME: improve implementation to not clone - match x.clone().follow_cell_path(&path.members) { - Ok(value) => { - cols.push(path.into_string()); - vals.push(value); - } - Err(error) => { - cols.push(path.into_string()); - vals.push(Value::Error { error }); - } + PipelineData::Stream(stream) => Ok(stream + .map(move |x| { + let mut cols = vec![]; + let mut vals = vec![]; + for path in &columns { + //FIXME: improve implementation to not clone + match x.clone().follow_cell_path(&path.members) { + Ok(value) => { + cols.push(path.into_string()); + vals.push(value); + } + Err(error) => { + cols.push(path.into_string()); + vals.push(Value::Error { error }); } } + } - Value::Record { cols, vals, span } - }) - .into_value_stream(), - span, - }), - v => { + Value::Record { cols, vals, span } + }) + .into_pipeline_data()), + PipelineData::Value(v) => { let mut cols = vec![]; let mut vals = vec![]; @@ -114,7 +118,7 @@ fn select(span: Span, columns: Vec, input: Value) -> Result Result { + input: PipelineData, + ) -> Result { let cond = call.positional[0].clone(); let context = context.enter_scope(); @@ -37,54 +38,40 @@ impl Command for Where { }; match input { - Value::Stream { stream, span } => { - let output_stream = stream - .filter(move |value| { - context.add_var(var_id, value.clone()); + PipelineData::Stream(stream) => Ok(stream + .filter(move |value| { + context.add_var(var_id, value.clone()); - let result = eval_expression(&context, &cond); + let result = eval_expression(&context, &cond); - match result { - Ok(result) => result.is_true(), - _ => false, - } - }) - .into_value_stream(); - - Ok(Value::Stream { - stream: output_stream, - span, + match result { + Ok(result) => result.is_true(), + _ => false, + } }) - } - Value::List { vals, span } => { - let output_stream = vals - .into_iter() - .filter(move |value| { - context.add_var(var_id, value.clone()); + .into_pipeline_data()), + PipelineData::Value(Value::List { vals, span }) => Ok(vals + .into_iter() + .filter(move |value| { + context.add_var(var_id, value.clone()); - let result = eval_expression(&context, &cond); + let result = eval_expression(&context, &cond); - match result { - Ok(result) => result.is_true(), - _ => false, - } - }) - .into_value_stream(); - - Ok(Value::Stream { - stream: output_stream, - span, + match result { + Ok(result) => result.is_true(), + _ => false, + } }) - } - x => { + .into_pipeline_data()), + PipelineData::Value(x) => { context.add_var(var_id, x.clone()); let result = eval_expression(&context, &cond)?; if result.is_true() { - Ok(x) + Ok(x.into_pipeline_data()) } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } } diff --git a/crates/nu-command/src/filters/wrap.rs b/crates/nu-command/src/filters/wrap.rs index f23624ad23..9c924800e7 100644 --- a/crates/nu-command/src/filters/wrap.rs +++ b/crates/nu-command/src/filters/wrap.rs @@ -1,8 +1,9 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{IntoValueStream, Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Wrap; impl Command for Wrap { @@ -22,38 +23,33 @@ impl Command for Wrap { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let span = call.head; let name: String = call.req(context, 0)?; match input { - Value::List { vals, .. } => Ok(Value::List { - vals: vals - .into_iter() - .map(move |x| Value::Record { - cols: vec![name.clone()], - vals: vec![x], - span, - }) - .collect(), - span, - }), - Value::Stream { stream, .. } => Ok(Value::Stream { - stream: stream - .map(move |x| Value::Record { - cols: vec![name.clone()], - vals: vec![x], - span, - }) - .into_value_stream(), - span, - }), - _ => Ok(Value::Record { + PipelineData::Value(Value::List { vals, .. }) => Ok(vals + .into_iter() + .map(move |x| Value::Record { + cols: vec![name.clone()], + vals: vec![x], + span, + }) + .into_pipeline_data()), + PipelineData::Stream(stream) => Ok(stream + .map(move |x| Value::Record { + cols: vec![name.clone()], + vals: vec![x], + span, + }) + .into_pipeline_data()), + PipelineData::Value(input) => Ok(Value::Record { cols: vec![name], vals: vec![input], span, - }), + } + .into_pipeline_data()), } } } diff --git a/crates/nu-command/src/formats/from/command.rs b/crates/nu-command/src/formats/from/command.rs index cc2b6b2da8..23b3d84f6f 100644 --- a/crates/nu-command/src/formats/from/command.rs +++ b/crates/nu-command/src/formats/from/command.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, Value}; +use nu_protocol::{PipelineData, ShellError, Signature, Value}; +#[derive(Clone)] pub struct From; impl Command for From { @@ -21,8 +22,8 @@ impl Command for From { &self, _context: &EvaluationContext, _call: &Call, - _input: Value, - ) -> Result { - Ok(Value::nothing()) + _input: PipelineData, + ) -> Result { + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index c643f1ba07..37ee0f81ff 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -1,7 +1,8 @@ use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, IntoValueStream, ShellError, Signature, Span, Value}; +use nu_protocol::{Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; +#[derive(Clone)] pub struct FromJson; impl Command for FromJson { @@ -69,8 +70,8 @@ impl Command for FromJson { &self, _context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let span = input.span()?; let mut string_input = input.collect_string(); string_input.push('\n'); @@ -79,21 +80,18 @@ impl Command for FromJson { if call.has_flag("objects") { #[allow(clippy::needless_collect)] let lines: Vec = string_input.lines().map(|x| x.to_string()).collect(); - Ok(Value::Stream { - stream: lines - .into_iter() - .map(move |mut x| { - x.push('\n'); - match convert_string_to_value(x, span) { - Ok(v) => v, - Err(error) => Value::Error { error }, - } - }) - .into_value_stream(), - span, - }) + Ok(lines + .into_iter() + .map(move |mut x| { + x.push('\n'); + match convert_string_to_value(x, span) { + Ok(v) => v, + Err(error) => Value::Error { error }, + } + }) + .into_pipeline_data()) } else { - convert_string_to_value(string_input, span) + Ok(convert_string_to_value(string_input, span)?.into_pipeline_data()) } } } diff --git a/crates/nu-command/src/strings/build_string.rs b/crates/nu-command/src/strings/build_string.rs index d9121034d8..4e80d1128f 100644 --- a/crates/nu-command/src/strings/build_string.rs +++ b/crates/nu-command/src/strings/build_string.rs @@ -1,8 +1,11 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, ShellError, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{ + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, +}; +#[derive(Clone)] pub struct BuildString; impl Command for BuildString { @@ -43,8 +46,8 @@ impl Command for BuildString { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let output = call .positional .iter() @@ -54,7 +57,8 @@ impl Command for BuildString { Ok(Value::String { val: output.join(""), span: call.head, - }) + } + .into_pipeline_data()) } } diff --git a/crates/nu-command/src/strings/size.rs b/crates/nu-command/src/strings/size.rs index 245abdc759..b40f3abf4d 100644 --- a/crates/nu-command/src/strings/size.rs +++ b/crates/nu-command/src/strings/size.rs @@ -4,8 +4,11 @@ use unicode_segmentation::UnicodeSegmentation; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, ShellError, Signature, Span, Type, Value}; +use nu_protocol::{ + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, +}; +#[derive(Clone)] pub struct Size; impl Command for Size { @@ -25,8 +28,8 @@ impl Command for Size { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { size(context, call, input) } @@ -98,18 +101,24 @@ impl Command for Size { } } -fn size(_context: &EvaluationContext, call: &Call, input: Value) -> Result { +fn size( + _context: &EvaluationContext, + call: &Call, + input: PipelineData, +) -> Result { let span = call.head; - input.map(span, move |v| match v.as_string() { - Ok(s) => count(&s, span), - Err(_) => Value::Error { - error: ShellError::PipelineMismatch { - expected: Type::String, - expected_span: span, - origin: span, + Ok(input + .map(move |v| match v.as_string() { + Ok(s) => count(&s, span), + Err(_) => Value::Error { + error: ShellError::PipelineMismatch { + expected: Type::String, + expected_span: span, + origin: span, + }, }, - }, - }) + }) + .into_pipeline_data()) } fn count(contents: &str, span: Span) -> Value { diff --git a/crates/nu-command/src/strings/split/chars.rs b/crates/nu-command/src/strings/split/chars.rs index c74dce2f17..e0ceaa9cb8 100644 --- a/crates/nu-command/src/strings/split/chars.rs +++ b/crates/nu-command/src/strings/split/chars.rs @@ -1,9 +1,10 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, ShellError, Signature, Span, Type, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -40,16 +41,21 @@ impl Command for SubCommand { &self, _context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { split_chars(call, input) } } -fn split_chars(call: &Call, input: Value) -> Result { +fn split_chars( + call: &Call, + input: PipelineData, +) -> Result { let span = call.head; - Ok(input.flat_map(span, move |x| split_chars_helper(&x, span))) + Ok(input + .flat_map(move |x| split_chars_helper(&x, span)) + .into_pipeline_data()) } fn split_chars_helper(v: &Value, name: Span) -> Vec { diff --git a/crates/nu-command/src/strings/split/column.rs b/crates/nu-command/src/strings/split/column.rs index ace779bd20..3b7bcae082 100644 --- a/crates/nu-command/src/strings/split/column.rs +++ b/crates/nu-command/src/strings/split/column.rs @@ -2,9 +2,10 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, + IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -35,8 +36,8 @@ impl Command for SubCommand { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { split_column(context, call, input) } } @@ -44,16 +45,16 @@ impl Command for SubCommand { fn split_column( context: &EvaluationContext, call: &Call, - input: Value, -) -> Result { + input: PipelineData, +) -> Result { let name_span = call.head; let separator: Spanned = call.req(context, 0)?; let rest: Vec> = call.rest(context, 1)?; let collapse_empty = call.has_flag("collapse-empty"); - input.map(name_span, move |x| { - split_column_helper(&x, &separator, &rest, collapse_empty, name_span) - }) + Ok(input + .map(move |x| split_column_helper(&x, &separator, &rest, collapse_empty, name_span)) + .into_pipeline_data()) } fn split_column_helper( diff --git a/crates/nu-command/src/strings/split/command.rs b/crates/nu-command/src/strings/split/command.rs index 87df229275..2afaaee625 100644 --- a/crates/nu-command/src/strings/split/command.rs +++ b/crates/nu-command/src/strings/split/command.rs @@ -2,7 +2,7 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Signature, Value, + IntoPipelineData, PipelineData, Signature, Value, }; #[derive(Clone)] @@ -25,12 +25,13 @@ impl Command for SplitCommand { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { Ok(Value::String { val: get_full_help(&SplitCommand.signature(), &SplitCommand.examples(), context), span: call.head, - }) + } + .into_pipeline_data()) } } diff --git a/crates/nu-command/src/strings/split/row.rs b/crates/nu-command/src/strings/split/row.rs index afda969770..6b24e2c792 100644 --- a/crates/nu-command/src/strings/split/row.rs +++ b/crates/nu-command/src/strings/split/row.rs @@ -2,9 +2,10 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, + IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; +#[derive(Clone)] pub struct SubCommand; impl Command for SubCommand { @@ -28,8 +29,8 @@ impl Command for SubCommand { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { split_row(context, call, input) } } @@ -37,14 +38,14 @@ impl Command for SubCommand { fn split_row( context: &EvaluationContext, call: &Call, - input: Value, -) -> Result { + input: PipelineData, +) -> Result { let name_span = call.head; let separator: Spanned = call.req(context, 0)?; - Ok(input.flat_map(name_span, move |x| { - split_row_helper(&x, &separator, name_span) - })) + Ok(input + .flat_map(move |x| split_row_helper(&x, &separator, name_span)) + .into_pipeline_data()) } fn split_row_helper(v: &Value, separator: &Spanned, name: Span) -> Vec { diff --git a/crates/nu-command/src/system/benchmark.rs b/crates/nu-command/src/system/benchmark.rs index 1590e8af84..932b8b1265 100644 --- a/crates/nu-command/src/system/benchmark.rs +++ b/crates/nu-command/src/system/benchmark.rs @@ -3,8 +3,9 @@ use std::time::Instant; use nu_engine::eval_block; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +#[derive(Clone)] pub struct Benchmark; impl Command for Benchmark { @@ -28,21 +29,18 @@ impl Command for Benchmark { &self, context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { let block = call.positional[0] .as_block() .expect("internal error: expected block"); - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(block); + let block = context.engine_state.get_block(block); let state = context.enter_scope(); let start_time = Instant::now(); - eval_block(&state, block, Value::nothing())?; + eval_block(&state, block, PipelineData::new())?; let end_time = Instant::now(); println!("{} ms", (end_time - start_time).as_millis()); - Ok(Value::Nothing { - span: call.positional[0].span, - }) + Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/system/ps.rs b/crates/nu-command/src/system/ps.rs index 68f9409a89..6e5072ae73 100644 --- a/crates/nu-command/src/system/ps.rs +++ b/crates/nu-command/src/system/ps.rs @@ -1,10 +1,11 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, ShellError, Signature, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Value, }; use sysinfo::{ProcessExt, System, SystemExt}; +#[derive(Clone)] pub struct Ps; impl Command for Ps { @@ -31,8 +32,8 @@ impl Command for Ps { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { run_ps(call) } @@ -45,7 +46,7 @@ impl Command for Ps { } } -fn run_ps(call: &Call) -> Result { +fn run_ps(call: &Call) -> Result { let span = call.head; let long = call.has_flag("long"); let mut sys = System::new_all(); @@ -124,5 +125,5 @@ fn run_ps(call: &Call) -> Result { } } - Ok(Value::List { vals: output, span }) + Ok(output.into_iter().into_pipeline_data()) } diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 8d03b4a7d3..9ac2817a48 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -11,12 +11,13 @@ use nu_protocol::{ engine::{Command, EvaluationContext}, ShellError, Signature, SyntaxShape, Value, }; -use nu_protocol::{Span, ValueStream}; +use nu_protocol::{IntoPipelineData, PipelineData, Span, ValueStream}; use nu_engine::eval_expression; const OUTPUT_BUFFER_SIZE: usize = 8192; +#[derive(Clone)] pub struct External; impl Command for External { @@ -38,8 +39,8 @@ impl Command for External { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let command = ExternalCommand::try_new(call, context)?; command.run_with_input(input) } @@ -82,7 +83,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { .collect() } - pub fn run_with_input(&self, input: Value) -> Result { + pub fn run_with_input(&self, input: PipelineData) -> Result { let mut process = self.create_command(); // TODO. We don't have a way to know the current directory @@ -101,11 +102,11 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { // If there is an input from the pipeline. The stdin from the process // is piped so it can be used to send the input information - if let Value::String { .. } = input { + if let PipelineData::Value(Value::String { .. }) = input { process.stdin(Stdio::piped()); } - if let Value::Stream { .. } = input { + if let PipelineData::Stream { .. } = input { process.stdin(Stdio::piped()); } @@ -116,33 +117,18 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { )), Ok(mut child) => { // if there is a string or a stream, that is sent to the pipe std - match input { - Value::String { val, span: _ } => { - if let Some(mut stdin_write) = child.stdin.take() { - self.write_to_stdin(&mut stdin_write, val.as_bytes())? - } - } - Value::Binary { val, span: _ } => { - if let Some(mut stdin_write) = child.stdin.take() { - self.write_to_stdin(&mut stdin_write, &val)? - } - } - Value::Stream { stream, span: _ } => { - if let Some(mut stdin_write) = child.stdin.take() { - for value in stream { - match value { - Value::String { val, span: _ } => { - self.write_to_stdin(&mut stdin_write, val.as_bytes())? - } - Value::Binary { val, span: _ } => { - self.write_to_stdin(&mut stdin_write, &val)? - } - _ => continue, - } + if let Some(mut stdin_write) = child.stdin.take() { + for value in input { + match value { + Value::String { val, span: _ } => { + self.write_to_stdin(&mut stdin_write, val.as_bytes())? } + Value::Binary { val, span: _ } => { + self.write_to_stdin(&mut stdin_write, &val)? + } + _ => continue, } } - _ => (), } // If this external is not the last expression, then its output is piped to a channel @@ -185,12 +171,9 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { }); // The ValueStream is consumed by the next expression in the pipeline - Value::Stream { - stream: ValueStream(Rc::new(RefCell::new(ChannelReceiver::new(rx)))), - span: Span::unknown(), - } + ChannelReceiver::new(rx).into_pipeline_data() } else { - Value::nothing() + PipelineData::new() }; match child.wait() { diff --git a/crates/nu-command/src/system/sys.rs b/crates/nu-command/src/system/sys.rs index b0323ffdf6..8541b4649b 100644 --- a/crates/nu-command/src/system/sys.rs +++ b/crates/nu-command/src/system/sys.rs @@ -1,10 +1,11 @@ use nu_protocol::{ ast::Call, engine::{Command, EvaluationContext}, - Example, ShellError, Signature, Span, Value, + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value, }; use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt}; +#[derive(Clone)] pub struct Sys; impl Command for Sys { @@ -26,8 +27,8 @@ impl Command for Sys { &self, _context: &EvaluationContext, call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { run_sys(call) } @@ -40,7 +41,7 @@ impl Command for Sys { } } -fn run_sys(call: &Call) -> Result { +fn run_sys(call: &Call) -> Result { let span = call.head; let mut sys = System::new(); @@ -76,7 +77,8 @@ fn run_sys(call: &Call) -> Result { cols: headers, vals: values, span, - }) + } + .into_pipeline_data()) } pub fn trim_cstyle_null(s: String) -> String { diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs index b44d468a84..42d66d7edb 100644 --- a/crates/nu-command/src/viewers/griddle.rs +++ b/crates/nu-command/src/viewers/griddle.rs @@ -8,6 +8,7 @@ use nu_protocol::{ use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; use terminal_size::{Height, Width}; +#[derive(Clone)] pub struct Griddle; impl Command for Griddle { diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 93338f3589..3d5f94992f 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -5,6 +5,7 @@ use nu_table::StyledString; use std::collections::HashMap; use terminal_size::{Height, Width}; +#[derive(Clone)] pub struct Table; //NOTE: this is not a real implementation :D. It's just a simple one to test with until we port the real one. diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index 84fe44fa19..c028625d77 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -26,11 +26,10 @@ fn generate_doc(name: &str, context: &EvaluationContext) -> (Vec, Vec Result { } } -fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result { - let engine_state = context.engine_state.borrow(); - let decl = engine_state.get_decl(call.decl_id); +fn eval_call( + context: &EvaluationContext, + call: &Call, + input: PipelineData, +) -> Result { + let decl = context.engine_state.get_decl(call.decl_id); if call.named.iter().any(|(flag, _)| flag.item == "help") { let full_help = get_full_help(&decl.signature(), &decl.examples(), context); Ok(Value::String { val: full_help, span: call.head, - }) + } + .into_pipeline_data()) } else if let Some(block_id) = decl.get_block_id() { - let state = context.enter_scope(); + let mut state = context.enter_scope(); for (arg, param) in call.positional.iter().zip( decl.signature() .required_positional @@ -102,8 +108,7 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result Result { - let engine_state = context.engine_state.borrow(); - - let decl_id = engine_state +) -> Result { + let decl_id = context + .engine_state .find_decl("run_external".as_bytes()) .ok_or_else(|| ShellError::ExternalNotSupported(*name_span))?; - let command = engine_state.get_decl(decl_id); + let command = context.engine_state.get_decl(decl_id); let mut call = Call::new(); @@ -216,9 +220,20 @@ pub fn eval_expression( value.follow_cell_path(&cell_path.tail) } Expr::RowCondition(_, expr) => eval_expression(context, expr), - Expr::Call(call) => eval_call(context, call, Value::nothing()), + Expr::Call(call) => { + // FIXME: protect this collect with ctrl-c + Ok(Value::List { + vals: eval_call(context, call, PipelineData::new())?.collect(), + span: expr.span, + }) + } Expr::ExternalCall(name, span, args) => { - eval_external(context, name, span, args, Value::nothing(), true) + // FIXME: protect this collect with ctrl-c + Ok(Value::List { + vals: eval_external(context, name, span, args, PipelineData::new(), true)? + .collect(), + span: expr.span, + }) } Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }), Expr::BinaryOp(lhs, op, rhs) => { @@ -249,11 +264,15 @@ pub fn eval_expression( } } Expr::Subexpression(block_id) => { - let engine_state = context.engine_state.borrow(); - let block = engine_state.get_block(*block_id); + let block = context.engine_state.get_block(*block_id); let state = context.enter_scope(); - eval_block(&state, block, Value::nothing()) + + // FIXME: protect this collect with ctrl-c + Ok(Value::List { + vals: eval_block(&state, block, PipelineData::new())?.collect(), + span: expr.span, + }) } Expr::Block(block_id) => Ok(Value::Block { val: *block_id, @@ -313,8 +332,8 @@ pub fn eval_expression( pub fn eval_block( context: &EvaluationContext, block: &Block, - mut input: Value, -) -> Result { + mut input: PipelineData, +) -> Result { for stmt in block.stmts.iter() { if let Statement::Pipeline(pipeline) = stmt { for (i, elem) in pipeline.expressions.iter().enumerate() { @@ -340,7 +359,7 @@ pub fn eval_block( } elem => { - input = eval_expression(context, elem)?; + input = eval_expression(context, elem)?.into_pipeline_data(); } } } diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 7a418767f3..da45d1f1c4 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -7,6 +7,7 @@ use nu_protocol::{ }; #[cfg(test)] +#[derive(Clone)] pub struct Let; #[cfg(test)] @@ -33,8 +34,8 @@ impl Command for Let { &self, _context: &nu_protocol::engine::EvaluationContext, _call: &nu_protocol::ast::Call, - _input: nu_protocol::Value, - ) -> Result { + _input: nu_protocol::PipelineData, + ) -> Result { todo!() } } diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index c44b03cf08..842aba468a 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -11,4 +11,5 @@ miette = "3.0.0" serde = {version = "1.0.130", features = ["derive"]} chrono = { version="0.4.19", features=["serde"] } chrono-humanize = "0.2.1" -byte-unit = "4.0.9" \ No newline at end of file +byte-unit = "4.0.9" +im = "15.0.0" \ No newline at end of file diff --git a/crates/nu-protocol/src/engine/command.rs b/crates/nu-protocol/src/engine/command.rs index ce322eb873..a8b3a5581d 100644 --- a/crates/nu-protocol/src/engine/command.rs +++ b/crates/nu-protocol/src/engine/command.rs @@ -1,8 +1,8 @@ -use crate::{ast::Call, value::Value, BlockId, Example, ShellError, Signature}; +use crate::{ast::Call, value::Value, BlockId, Example, PipelineData, ShellError, Signature}; use super::EvaluationContext; -pub trait Command: Send + Sync { +pub trait Command: Send + Sync + CommandClone { fn name(&self) -> &str; fn signature(&self) -> Signature { @@ -19,8 +19,8 @@ pub trait Command: Send + Sync { &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result; + input: PipelineData, + ) -> Result; fn is_binary(&self) -> bool { false @@ -55,3 +55,22 @@ pub trait Command: Send + Sync { None } } + +pub trait CommandClone { + fn clone_box(&self) -> Box; +} + +impl CommandClone for T +where + T: 'static + Command + Clone, +{ + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Box { + self.clone_box() + } +} diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 830cd65697..a828530376 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -3,13 +3,14 @@ use crate::{ast::Block, BlockId, DeclId, Example, Signature, Span, Type, VarId}; use core::panic; use std::{collections::HashMap, slice::Iter}; +#[derive(Clone)] pub struct EngineState { - files: Vec<(String, usize, usize)>, - file_contents: Vec, - vars: Vec, - decls: Vec>, - blocks: Vec, - pub scope: Vec, + files: im::Vector<(String, usize, usize)>, + file_contents: im::Vector<(Vec, usize, usize)>, + vars: im::Vector, + decls: im::Vector>, + blocks: im::Vector, + pub scope: im::Vector, } // Tells whether a decl etc. is visible or not @@ -53,7 +54,7 @@ impl Visibility { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ScopeFrame { pub vars: HashMap, VarId>, predecls: HashMap, DeclId>, // temporary storage for predeclarations @@ -95,12 +96,12 @@ impl Default for EngineState { impl EngineState { pub fn new() -> Self { Self { - files: vec![], - file_contents: vec![], - vars: vec![], - decls: vec![], - blocks: vec![], - scope: vec![ScopeFrame::new()], + files: im::vector![], + file_contents: im::vector![], + vars: im::vector![], + decls: im::vector![], + blocks: im::vector![], + scope: im::vector![ScopeFrame::new()], } } @@ -112,7 +113,7 @@ impl EngineState { this.vars.extend(delta.vars); this.blocks.extend(delta.blocks); - if let Some(last) = this.scope.last_mut() { + if let Some(last) = this.scope.back_mut() { let first = delta.scope.remove(0); for item in first.decls.into_iter() { last.decls.insert(item.0, item.1); @@ -165,8 +166,10 @@ impl EngineState { } pub fn print_contents(&self) { - let string = String::from_utf8_lossy(&self.file_contents); - println!("{}", string); + for (contents, _, _) in self.file_contents.iter() { + let string = String::from_utf8_lossy(&contents); + println!("{}", string); + } } pub fn find_decl(&self, name: &[u8]) -> Option { @@ -200,7 +203,13 @@ impl EngineState { } pub fn get_span_contents(&self, span: &Span) -> &[u8] { - &self.file_contents[span.start..span.end] + for (contents, start, finish) in &self.file_contents { + if span.start >= *start && span.start < *finish { + return &contents[(span.start - start)..(span.end - start)]; + } + } + + panic!("internal error: span missing in file contents cache") } pub fn get_var(&self, var_id: VarId) -> &Type { @@ -256,7 +265,7 @@ impl EngineState { self.file_contents.len() } - pub fn files(&self) -> Iter<(String, usize, usize)> { + pub fn files(&self) -> impl Iterator { self.files.iter() } @@ -273,8 +282,11 @@ impl EngineState { pub fn get_file_source(&self, file_id: usize) -> String { for file in self.files.iter().enumerate() { if file.0 == file_id { - let output = - String::from_utf8_lossy(&self.file_contents[file.1 .1..file.1 .2]).to_string(); + let contents = self.get_span_contents(&Span { + start: file.1 .1, + end: file.1 .2, + }); + let output = String::from_utf8_lossy(contents).to_string(); return output; } @@ -286,12 +298,13 @@ impl EngineState { #[allow(unused)] pub(crate) fn add_file(&mut self, filename: String, contents: Vec) -> usize { let next_span_start = self.next_span_start(); + let next_span_end = next_span_start + contents.len(); - self.file_contents.extend(&contents); + self.file_contents + .push_back((contents, next_span_start, next_span_end)); - let next_span_end = self.next_span_start(); - - self.files.push((filename, next_span_start, next_span_end)); + self.files + .push_back((filename, next_span_start, next_span_end)); self.num_files() - 1 } @@ -304,7 +317,7 @@ pub struct StateWorkingSet<'a> { pub struct StateDelta { files: Vec<(String, usize, usize)>, - pub(crate) file_contents: Vec, + pub(crate) file_contents: Vec<(Vec, usize, usize)>, vars: Vec, // indexed by VarId decls: Vec>, // indexed by DeclId blocks: Vec, // indexed by BlockId @@ -520,10 +533,11 @@ impl<'a> StateWorkingSet<'a> { pub fn add_file(&mut self, filename: String, contents: &[u8]) -> usize { let next_span_start = self.next_span_start(); + let next_span_end = next_span_start + contents.len(); - self.delta.file_contents.extend(contents); - - let next_span_end = self.next_span_start(); + self.delta + .file_contents + .push((contents.to_vec(), next_span_start, next_span_end)); self.delta .files @@ -535,10 +549,16 @@ impl<'a> StateWorkingSet<'a> { pub fn get_span_contents(&self, span: Span) -> &[u8] { let permanent_end = self.permanent_state.next_span_start(); if permanent_end <= span.start { - &self.delta.file_contents[(span.start - permanent_end)..(span.end - permanent_end)] + for (contents, start, finish) in &self.delta.file_contents { + if (span.start >= *start) && (span.start < *finish) { + return &contents[(span.start - permanent_end)..(span.end - permanent_end)]; + } + } } else { - &self.permanent_state.file_contents[span.start..span.end] + return self.permanent_state.get_span_contents(&span); } + + panic!("internal error: missing span contents in file cache") } pub fn enter_scope(&mut self) { diff --git a/crates/nu-protocol/src/engine/evaluation_context.rs b/crates/nu-protocol/src/engine/evaluation_context.rs index b376294047..5fd4d17bcc 100644 --- a/crates/nu-protocol/src/engine/evaluation_context.rs +++ b/crates/nu-protocol/src/engine/evaluation_context.rs @@ -5,7 +5,7 @@ use crate::{Example, ShellError, Signature, Value, VarId}; #[derive(Clone)] pub struct EvaluationContext { - pub engine_state: Rc>, + pub engine_state: Box, pub stack: Stack, } @@ -21,25 +21,11 @@ impl EvaluationContext { } } - pub fn add_var(&self, var_id: VarId, value: Value) { - // We need to make values concreate before we assign them to variables, as stream values - // will drain and remain drained. - // - // TODO: find a good home for converting a stream->list when storing into a variable - // TODO: add ctrl-c support when setting a var - - let value = match value { - Value::Stream { stream, span } => Value::List { - vals: stream.collect(), - span, - }, - x => x, - }; - + pub fn add_var(&mut self, var_id: VarId, value: Value) { self.stack.add_var(var_id, value); } - pub fn add_env_var(&self, var: String, value: String) { + pub fn add_env_var(&mut self, var: String, value: String) { self.stack.add_env_var(var, value); } @@ -48,23 +34,22 @@ impl EvaluationContext { } pub fn get_signatures(&self) -> Vec { - self.engine_state.borrow().get_signatures() + self.engine_state.get_signatures() } pub fn get_signatures_with_examples(&self) -> Vec<(Signature, Vec)> { - self.engine_state.borrow().get_signatures_with_examples() + self.engine_state.get_signatures_with_examples() } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct StackFrame { pub vars: HashMap, pub env_vars: HashMap, - pub parent: Option, } #[derive(Clone, Debug)] -pub struct Stack(Rc>); +pub struct Stack(Vec); impl Default for Stack { fn default() -> Self { @@ -74,64 +59,77 @@ impl Default for Stack { impl Stack { pub fn new() -> Stack { - Stack(Rc::new(RefCell::new(StackFrame { + Stack(vec![StackFrame { vars: HashMap::new(), env_vars: HashMap::new(), - parent: None, - }))) + }]) } pub fn get_var(&self, var_id: VarId) -> Result { - let this = self.0.borrow(); - match this.vars.get(&var_id) { - Some(v) => Ok(v.clone()), - _ => { - if let Some(parent) = &this.parent { - parent.get_var(var_id) - } else { - Err(ShellError::InternalError("variable not found".into())) - } + for frame in self.0.iter().rev() { + if let Some(v) = frame.vars.get(&var_id) { + return Ok(v.clone()); } } + Err(ShellError::InternalError("variable not found".into())) } - pub fn add_var(&self, var_id: VarId, value: Value) { - let mut this = self.0.borrow_mut(); - this.vars.insert(var_id, value); + pub fn add_var(&mut self, var_id: VarId, value: Value) { + let frame = self + .0 + .last_mut() + .expect("internal error: can't access stack frame"); + frame.vars.insert(var_id, value); } - pub fn add_env_var(&self, var: String, value: String) { - let mut this = self.0.borrow_mut(); - this.env_vars.insert(var, value); + pub fn add_env_var(&mut self, var: String, value: String) { + let frame = self + .0 + .last_mut() + .expect("internal error: can't access stack frame"); + frame.env_vars.insert(var, value); } - pub fn enter_scope(self) -> Stack { - Stack(Rc::new(RefCell::new(StackFrame { + pub fn enter_scope(&self) -> Stack { + // FIXME: VERY EXPENSIVE to clone entire stack + let mut output = self.clone(); + output.0.push(StackFrame { vars: HashMap::new(), env_vars: HashMap::new(), - parent: Some(self), - }))) + }); + + output } pub fn get_env_vars(&self) -> HashMap { - self.0.borrow().env_vars.clone() + let mut output = HashMap::new(); + + for frame in &self.0 { + output.extend(frame.env_vars.clone().into_iter()); + } + + output } pub fn get_env_var(&self, name: &str) -> Option { - self.0.borrow().env_vars.get(name).cloned() + for frame in self.0.iter().rev() { + if let Some(v) = frame.env_vars.get(name) { + return Some(v.to_string()); + } + } + None } pub fn print_stack(&self) { - println!("===frame==="); - println!("vars:"); - for (var, val) in &self.0.borrow().vars { - println!(" {}: {:?}", var, val); - } - println!("env vars:"); - for (var, val) in &self.0.borrow().env_vars { - println!(" {}: {:?}", var, val); - } - if let Some(parent) = &self.0.borrow().parent { - parent.print_stack() + for frame in self.0.iter().rev() { + println!("===frame==="); + println!("vars:"); + for (var, val) in &frame.vars { + println!(" {}: {:?}", var, val); + } + println!("env vars:"); + for (var, val) in &frame.env_vars { + println!(" {}: {:?}", var, val); + } } } } diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs index 6bd566bfa3..081a9b0b41 100644 --- a/crates/nu-protocol/src/lib.rs +++ b/crates/nu-protocol/src/lib.rs @@ -2,6 +2,7 @@ pub mod ast; pub mod engine; mod example; mod id; +mod pipeline_data; mod shell_error; mod signature; mod span; @@ -12,6 +13,7 @@ pub use value::Value; pub use example::*; pub use id::*; +pub use pipeline_data::*; pub use shell_error::*; pub use signature::*; pub use span::*; diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs new file mode 100644 index 0000000000..9b110f6419 --- /dev/null +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -0,0 +1,62 @@ +use crate::{Span, Value, ValueStream}; + +pub enum PipelineData { + Value(Value), + Stream(ValueStream), +} + +impl PipelineData { + pub fn new() -> PipelineData { + PipelineData::Value(Value::nothing()) + } + + pub fn into_value(self) -> Value { + match self { + PipelineData::Value(v) => v, + PipelineData::Stream(s) => Value::List { + vals: s.collect(), + span: Span::unknown(), // FIXME? + }, + } + } +} + +impl Default for PipelineData { + fn default() -> Self { + PipelineData::new() + } +} + +impl Iterator for PipelineData { + type Item = Value; + + fn next(&mut self) -> Option { + match self { + PipelineData::Value(Value::Nothing { .. }) => None, + PipelineData::Value(v) => { + let prev = std::mem::take(v); + Some(prev) + } + PipelineData::Stream(stream) => stream.next(), + } + } +} + +pub trait IntoPipelineData { + fn into_pipeline_data(self) -> PipelineData; +} + +impl IntoPipelineData for Value { + fn into_pipeline_data(self) -> PipelineData { + PipelineData::Value(self) + } +} + +impl IntoPipelineData for T +where + T: Iterator + Send + 'static, +{ + fn into_pipeline_data(self) -> PipelineData { + PipelineData::Stream(ValueStream(Box::new(self))) + } +} diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index e29d4b79c9..4c2a36313b 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -1,7 +1,9 @@ use crate::ast::Call; use crate::engine::Command; +use crate::engine::CommandClone; use crate::engine::EvaluationContext; use crate::BlockId; +use crate::PipelineData; use crate::SyntaxShape; use crate::Value; use crate::VarId; @@ -335,6 +337,7 @@ impl Signature { } } +#[derive(Clone)] struct Predeclaration { signature: Signature, } @@ -356,12 +359,13 @@ impl Command for Predeclaration { &self, _context: &EvaluationContext, _call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { panic!("Internal error: can't run a predeclaration without a body") } } +#[derive(Clone)] struct BlockCommand { signature: Signature, block_id: BlockId, @@ -384,8 +388,8 @@ impl Command for BlockCommand { &self, _context: &EvaluationContext, _call: &Call, - _input: Value, - ) -> Result { + _input: PipelineData, + ) -> Result { panic!("Internal error: can't run custom command with 'run', use block_id"); } diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 976cb9b6b3..3cd0b0a480 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -59,10 +59,6 @@ pub enum Value { vals: Vec, span: Span, }, - Stream { - stream: ValueStream, - span: Span, - }, List { vals: Vec, span: Span, @@ -110,7 +106,6 @@ impl Value { Value::Record { span, .. } => Ok(*span), Value::List { span, .. } => Ok(*span), Value::Block { span, .. } => Ok(*span), - Value::Stream { span, .. } => Ok(*span), Value::Nothing { span, .. } => Ok(*span), Value::Binary { span, .. } => Ok(*span), Value::CellPath { span, .. } => Ok(*span), @@ -129,7 +124,6 @@ impl Value { Value::Range { span, .. } => *span = new_span, Value::String { span, .. } => *span = new_span, Value::Record { span, .. } => *span = new_span, - Value::Stream { span, .. } => *span = new_span, Value::List { span, .. } => *span = new_span, Value::Block { span, .. } => *span = new_span, Value::Nothing { span, .. } => *span = new_span, @@ -158,7 +152,6 @@ impl Value { Value::List { .. } => Type::List(Box::new(Type::Unknown)), // FIXME Value::Nothing { .. } => Type::Nothing, Value::Block { .. } => Type::Block, - Value::Stream { .. } => Type::ValueStream, Value::Error { .. } => Type::Error, Value::Binary { .. } => Type::Binary, Value::CellPath { .. } => Type::CellPath, @@ -186,7 +179,6 @@ impl Value { Err(error) => format!("{:?}", error), }, Value::String { val, .. } => val, - Value::Stream { stream, .. } => stream.into_string(), Value::List { vals: val, .. } => format!( "[{}]", val.into_iter() @@ -228,7 +220,6 @@ impl Value { } }, Value::String { val, .. } => val, - Value::Stream { stream, .. } => stream.collect_string(), Value::List { vals: val, .. } => val .into_iter() .map(|x| x.collect_string()) @@ -274,13 +265,6 @@ impl Value { return Err(ShellError::AccessBeyondEnd(val.len(), *origin_span)); } } - Value::Stream { stream, .. } => { - if let Some(item) = stream.nth(*count) { - current = item; - } else { - return Err(ShellError::AccessBeyondEndOfStream(*origin_span)); - } - } x => { return Err(ShellError::IncompatiblePathAccess( format!("{}", x.get_type()), @@ -329,27 +313,6 @@ impl Value { span: *span, }; } - Value::Stream { stream, span } => { - let mut output = vec![]; - for val in stream { - output.push(val.clone().follow_cell_path(&[PathMember::String { - val: column_name.clone(), - span: *origin_span, - }])?); - // if let Value::Record { cols, vals, .. } = val { - // for col in cols.iter().enumerate() { - // if col.1 == column_name { - // output.push(vals[col.0].clone()); - // } - // } - // } - } - - current = Value::List { - vals: output, - span: *span, - }; - } x => { return Err(ShellError::IncompatiblePathAccess( format!("{}", x.get_type()), @@ -374,64 +337,6 @@ impl Value { } } - pub fn map(self, span: Span, mut f: F) -> Result - where - Self: Sized, - F: FnMut(Self) -> Value + 'static, - { - match self { - Value::List { vals, .. } => Ok(Value::Stream { - stream: vals.into_iter().map(f).into_value_stream(), - span, - }), - Value::Stream { stream, .. } => Ok(Value::Stream { - stream: stream.map(f).into_value_stream(), - span, - }), - Value::Range { val, .. } => Ok(Value::Stream { - stream: val.into_range_iter()?.map(f).into_value_stream(), - span, - }), - v => { - let output = f(v); - match output { - Value::Error { error } => Err(error), - v => Ok(v), - } - } - } - } - - pub fn flat_map(self, span: Span, mut f: F) -> Value - where - Self: Sized, - U: IntoIterator, - ::IntoIter: 'static, - F: FnMut(Self) -> U + 'static, - { - match self { - Value::List { vals, .. } => Value::Stream { - stream: vals.into_iter().map(f).flatten().into_value_stream(), - span, - }, - Value::Stream { stream, .. } => Value::Stream { - stream: stream.map(f).flatten().into_value_stream(), - span, - }, - Value::Range { val, .. } => match val.into_range_iter() { - Ok(iter) => Value::Stream { - stream: iter.map(f).flatten().into_value_stream(), - span, - }, - Err(error) => Value::Error { error }, - }, - v => Value::Stream { - stream: f(v).into_iter().into_value_stream(), - span, - }, - } - } - pub fn string(val: impl Into, span: Span) -> Value { Value::String { val: val.into(), @@ -460,6 +365,12 @@ impl Value { } } +impl Default for Value { + fn default() -> Self { + Value::nothing() + } +} + impl PartialOrd for Value { fn partial_cmp(&self, other: &Self) -> Option { // Compare two floating point numbers. The decision interval for equality is dynamically @@ -511,24 +422,6 @@ impl PartialOrd for Value { .. }, ) if lhs_headers == rhs_headers && lhs == rhs => Some(Ordering::Equal), - (Value::Stream { stream: lhs, .. }, Value::Stream { stream: rhs, .. }) => { - lhs.clone().partial_cmp(rhs.clone()) - } - (Value::Stream { stream: lhs, .. }, Value::String { val: rhs, .. }) => { - lhs.clone().collect_string().partial_cmp(rhs) - } - (Value::String { val: lhs, .. }, Value::Stream { stream: rhs, .. }) => { - lhs.partial_cmp(&rhs.clone().collect_string()) - } - // NOTE: This may look a bit strange, but a `Stream` is still just a `List`, it just - // happens to be in an iterator form instead of a concrete form. The contained values - // can be compared. - (Value::Stream { stream: lhs, .. }, Value::List { vals: rhs, .. }) => { - lhs.clone().collect::>().partial_cmp(rhs) - } - (Value::List { vals: lhs, .. }, Value::Stream { stream: rhs, .. }) => { - lhs.partial_cmp(&rhs.clone().collect::>()) - } (Value::Binary { val: lhs, .. }, Value::Binary { val: rhs, .. }) => { lhs.partial_cmp(rhs) } @@ -852,10 +745,6 @@ impl Value { val: rhs.contains(lhs), span, }), - (lhs, Value::Stream { stream: rhs, .. }) => Ok(Value::Bool { - val: rhs.clone().any(|x| lhs == &x), - span, - }), _ => Err(ShellError::OperatorMismatch { op_span: op, lhs_ty: self.get_type(), @@ -886,10 +775,6 @@ impl Value { val: !rhs.contains(lhs), span, }), - (lhs, Value::Stream { stream: rhs, .. }) => Ok(Value::Bool { - val: rhs.clone().all(|x| lhs != &x), - span, - }), _ => Err(ShellError::OperatorMismatch { op_span: op, lhs_ty: self.get_type(), diff --git a/crates/nu-protocol/src/value/stream.rs b/crates/nu-protocol/src/value/stream.rs index 87ab2fec71..81aec0f0ac 100644 --- a/crates/nu-protocol/src/value/stream.rs +++ b/crates/nu-protocol/src/value/stream.rs @@ -1,10 +1,7 @@ use crate::*; -use std::{cell::RefCell, fmt::Debug, rc::Rc}; +use std::fmt::Debug; -use serde::{ser::SerializeSeq, Deserialize, Serialize}; - -#[derive(Clone)] -pub struct ValueStream(pub Rc>>); +pub struct ValueStream(pub Box + Send + 'static>); impl ValueStream { pub fn into_string(self) -> String { @@ -22,8 +19,8 @@ impl ValueStream { .join("\n") } - pub fn from_stream(input: impl Iterator + 'static) -> ValueStream { - ValueStream(Rc::new(RefCell::new(input))) + pub fn from_stream(input: impl Iterator + Send + 'static) -> ValueStream { + ValueStream(Box::new(input)) } } @@ -38,66 +35,66 @@ impl Iterator for ValueStream { fn next(&mut self) -> Option { { - self.0.borrow_mut().next() + self.0.next() } } } -impl Serialize for ValueStream { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut seq = serializer.serialize_seq(None)?; +// impl Serialize for ValueStream { +// fn serialize(&self, serializer: S) -> Result +// where +// S: serde::Serializer, +// { +// let mut seq = serializer.serialize_seq(None)?; - for element in self.0.borrow_mut().into_iter() { - seq.serialize_element(&element)?; - } - seq.end() - } -} +// for element in self.0.borrow_mut().into_iter() { +// seq.serialize_element(&element)?; +// } +// seq.end() +// } +// } -impl<'de> Deserialize<'de> for ValueStream { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_seq(MySeqVisitor) - } -} +// impl<'de> Deserialize<'de> for ValueStream { +// fn deserialize(deserializer: D) -> Result +// where +// D: serde::Deserializer<'de>, +// { +// deserializer.deserialize_seq(MySeqVisitor) +// } +// } -struct MySeqVisitor; +// struct MySeqVisitor; -impl<'a> serde::de::Visitor<'a> for MySeqVisitor { - type Value = ValueStream; +// impl<'a> serde::de::Visitor<'a> for MySeqVisitor { +// type Value = ValueStream; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a value stream") - } +// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { +// formatter.write_str("a value stream") +// } - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'a>, - { - let mut output: Vec = vec![]; +// fn visit_seq(self, mut seq: A) -> Result +// where +// A: serde::de::SeqAccess<'a>, +// { +// let mut output: Vec = vec![]; - while let Some(value) = seq.next_element()? { - output.push(value); - } +// while let Some(value) = seq.next_element()? { +// output.push(value); +// } - Ok(ValueStream(Rc::new(RefCell::new(output.into_iter())))) - } -} +// Ok(ValueStream(Rc::new(RefCell::new(output.into_iter())))) +// } +// } -pub trait IntoValueStream { - fn into_value_stream(self) -> ValueStream; -} +// pub trait IntoValueStream { +// fn into_value_stream(self) -> ValueStream; +// } -impl IntoValueStream for T -where - T: Iterator + 'static, -{ - fn into_value_stream(self) -> ValueStream { - ValueStream::from_stream(self) - } -} +// impl IntoValueStream for T +// where +// T: Iterator + 'static, +// { +// fn into_value_stream(self) -> ValueStream { +// ValueStream::from_stream(self) +// } +// } From 397a31e69cf78c1ecab1d6404e4ecb74424aed33 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 25 Oct 2021 17:24:10 +1300 Subject: [PATCH 06/16] WIP --- crates/nu-command/src/core_commands/do_.rs | 2 +- crates/nu-command/src/core_commands/for_.rs | 29 +- crates/nu-command/src/filters/each.rs | 330 ++++++++++---------- crates/nu-command/src/filters/get.rs | 6 +- crates/nu-command/src/formats/from/json.rs | 2 +- crates/nu-command/src/viewers/griddle.rs | 19 +- crates/nu-command/src/viewers/table.rs | 27 +- crates/nu-protocol/src/pipeline_data.rs | 21 +- 8 files changed, 241 insertions(+), 195 deletions(-) diff --git a/crates/nu-command/src/core_commands/do_.rs b/crates/nu-command/src/core_commands/do_.rs index 8bc4435d7c..09f6351b7a 100644 --- a/crates/nu-command/src/core_commands/do_.rs +++ b/crates/nu-command/src/core_commands/do_.rs @@ -39,7 +39,7 @@ impl Command for Do { let block = context.engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut state = context.enter_scope(); let params: Vec<_> = block .signature diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index 5ce82dc60c..2a52296dfd 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -62,7 +62,7 @@ impl Command for For { .map(move |x| { let block = context.engine_state.get_block(block); - let state = context.enter_scope(); + let mut state = context.enter_scope(); state.add_var(var_id, x); @@ -75,6 +75,33 @@ impl Command for For { } }) .into_pipeline_data()), + Value::Range { val, span } => Ok(val + .into_range_iter()? + .map(move |x| { + let block = context.engine_state.get_block(block); + + let mut state = context.enter_scope(); + + state.add_var(var_id, x); + + match eval_block(&state, block, PipelineData::new()) { + Ok(value) => Value::List { + vals: value.collect(), + span, + }, + Err(error) => Value::Error { error }, + } + }) + .into_pipeline_data()), + x => { + let block = context.engine_state.get_block(block); + + let mut state = context.enter_scope(); + + state.add_var(var_id, x); + + eval_block(&state, block, PipelineData::new()) + } } } diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 7293e9c9e0..d963fcb35c 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -1,7 +1,7 @@ use nu_engine::eval_block; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Example, PipelineData, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; #[derive(Clone)] pub struct Each; @@ -65,186 +65,180 @@ impl Command for Each { let context = context.clone(); let span = call.head; - // match input { - // Value::Range { val, .. } => Ok(val - // .into_range_iter()? - // .enumerate() - // .map(move |(idx, x)| { - // let block = context.engine_state.get_block(block_id); + match input { + PipelineData::Value(Value::Range { val, .. }) => Ok(val + .into_range_iter()? + .enumerate() + .map(move |(idx, x)| { + let block = context.engine_state.get_block(block_id); - // let state = context.enter_scope(); + let state = context.enter_scope(); - // if let Some(var) = block.signature.get_positional(0) { - // if let Some(var_id) = &var.var_id { - // if numbered { - // state.add_var( - // *var_id, - // Value::Record { - // cols: vec!["index".into(), "item".into()], - // vals: vec![ - // Value::Int { - // val: idx as i64, - // span, - // }, - // x, - // ], - // span, - // }, - // ); - // } else { - // state.add_var(*var_id, x); - // } - // } - // } + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + if numbered { + state.add_var( + *var_id, + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![ + Value::Int { + val: idx as i64, + span, + }, + x, + ], + span, + }, + ); + } else { + state.add_var(*var_id, x); + } + } + } - // match eval_block(&state, block, Value::nothing()) { - // Ok(v) => v, - // Err(error) => Value::Error { error }, - // } - // }) - // .into_pipeline_data()), - // Value::List { vals: val, .. } => Ok(Value::Stream { - // stream: val - // .into_iter() - // .enumerate() - // .map(move |(idx, x)| { - // let engine_state = context.engine_state.borrow(); - // let block = engine_state.get_block(block_id); + match eval_block(&state, block, PipelineData::new()) { + Ok(v) => v, + Err(error) => Value::Error { error }.into_pipeline_data(), + } + }) + .flatten() + .into_pipeline_data()), + PipelineData::Value(Value::List { vals: val, .. }) => Ok(val + .into_iter() + .enumerate() + .map(move |(idx, x)| { + let block = context.engine_state.get_block(block_id); - // let state = context.enter_scope(); - // if let Some(var) = block.signature.get_positional(0) { - // if let Some(var_id) = &var.var_id { - // if numbered { - // state.add_var( - // *var_id, - // Value::Record { - // cols: vec!["index".into(), "item".into()], - // vals: vec![ - // Value::Int { - // val: idx as i64, - // span, - // }, - // x, - // ], - // span, - // }, - // ); - // } else { - // state.add_var(*var_id, x); - // } - // } - // } + let state = context.enter_scope(); + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + if numbered { + state.add_var( + *var_id, + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![ + Value::Int { + val: idx as i64, + span, + }, + x, + ], + span, + }, + ); + } else { + state.add_var(*var_id, x); + } + } + } - // match eval_block(&state, block, Value::nothing()) { - // Ok(v) => v, - // Err(error) => Value::Error { error }, - // } - // }) - // .into_value_stream(), - // span: call.head, - // }), - // Value::Stream { stream, .. } => Ok(Value::Stream { - // stream: stream - // .enumerate() - // .map(move |(idx, x)| { - // let engine_state = context.engine_state.borrow(); - // let block = engine_state.get_block(block_id); + match eval_block(&state, block, PipelineData::new()) { + Ok(v) => v, + Err(error) => Value::Error { error }.into_pipeline_data(), + } + }) + .flatten() + .into_pipeline_data()), + PipelineData::Stream(stream) => Ok(stream + .enumerate() + .map(move |(idx, x)| { + let block = context.engine_state.get_block(block_id); - // let state = context.enter_scope(); - // if let Some(var) = block.signature.get_positional(0) { - // if let Some(var_id) = &var.var_id { - // if numbered { - // state.add_var( - // *var_id, - // Value::Record { - // cols: vec!["index".into(), "item".into()], - // vals: vec![ - // Value::Int { - // val: idx as i64, - // span, - // }, - // x, - // ], - // span, - // }, - // ); - // } else { - // state.add_var(*var_id, x); - // } - // } - // } + let state = context.enter_scope(); + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + if numbered { + state.add_var( + *var_id, + Value::Record { + cols: vec!["index".into(), "item".into()], + vals: vec![ + Value::Int { + val: idx as i64, + span, + }, + x, + ], + span, + }, + ); + } else { + state.add_var(*var_id, x); + } + } + } - // match eval_block(&state, block, Value::nothing()) { - // Ok(v) => v, - // Err(error) => Value::Error { error }, - // } - // }) - // .into_value_stream(), - // span: call.head, - // }), - // Value::Record { cols, vals, .. } => { - // let mut output_cols = vec![]; - // let mut output_vals = vec![]; + match eval_block(&state, block, PipelineData::new()) { + Ok(v) => v, + Err(error) => Value::Error { error }.into_pipeline_data(), + } + }) + .flatten() + .into_pipeline_data()), + PipelineData::Value(Value::Record { cols, vals, .. }) => { + let mut output_cols = vec![]; + let mut output_vals = vec![]; - // for (col, val) in cols.into_iter().zip(vals.into_iter()) { - // let engine_state = context.engine_state.borrow(); - // let block = engine_state.get_block(block_id); + for (col, val) in cols.into_iter().zip(vals.into_iter()) { + let block = context.engine_state.get_block(block_id); - // let state = context.enter_scope(); - // if let Some(var) = block.signature.get_positional(0) { - // if let Some(var_id) = &var.var_id { - // state.add_var( - // *var_id, - // Value::Record { - // cols: vec!["column".into(), "value".into()], - // vals: vec![ - // Value::String { - // val: col.clone(), - // span: call.head, - // }, - // val, - // ], - // span: call.head, - // }, - // ); - // } - // } + let state = context.enter_scope(); + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + state.add_var( + *var_id, + Value::Record { + cols: vec!["column".into(), "value".into()], + vals: vec![ + Value::String { + val: col.clone(), + span: call.head, + }, + val, + ], + span: call.head, + }, + ); + } + } - // match eval_block(&state, block, Value::nothing())? { - // Value::Record { - // mut cols, mut vals, .. - // } => { - // // TODO check that the lengths match when traversing record - // output_cols.append(&mut cols); - // output_vals.append(&mut vals); - // } - // x => { - // output_cols.push(col); - // output_vals.push(x); - // } - // } - // } + match eval_block(&state, block, PipelineData::new())? { + PipelineData::Value(Value::Record { + mut cols, mut vals, .. + }) => { + // TODO check that the lengths match when traversing record + output_cols.append(&mut cols); + output_vals.append(&mut vals); + } + x => { + output_cols.push(col); + output_vals.push(x.into_value()); + } + } + } - // Ok(Value::Record { - // cols: output_cols, - // vals: output_vals, - // span: call.head, - // }) - // } - // x => { - // let engine_state = context.engine_state.borrow(); - // let block = engine_state.get_block(block_id); + Ok(Value::Record { + cols: output_cols, + vals: output_vals, + span: call.head, + } + .into_pipeline_data()) + } + PipelineData::Value(x) => { + let block = context.engine_state.get_block(block_id); - // let state = context.enter_scope(); - // if let Some(var) = block.signature.get_positional(0) { - // if let Some(var_id) = &var.var_id { - // state.add_var(*var_id, x); - // } - // } + let state = context.enter_scope(); + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + state.add_var(*var_id, x); + } + } - // eval_block(&state, block, Value::nothing()) - // } - // } + eval_block(&state, block, PipelineData::new()) + } + } } } diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index 9cf3dd7963..fd4084e2bf 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] pub struct Get; @@ -31,6 +31,8 @@ impl Command for Get { ) -> Result { let cell_path: CellPath = call.req(context, 0)?; - input.follow_cell_path(&cell_path.members) + input + .follow_cell_path(&cell_path.members) + .map(|x| x.into_pipeline_data()) } } diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index 37ee0f81ff..598544aafd 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -72,7 +72,7 @@ impl Command for FromJson { call: &Call, input: PipelineData, ) -> Result { - let span = input.span()?; + let span = call.head; let mut string_input = input.collect_string(); string_input.push('\n'); diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs index 42d66d7edb..462c476abd 100644 --- a/crates/nu-command/src/viewers/griddle.rs +++ b/crates/nu-command/src/viewers/griddle.rs @@ -3,7 +3,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::{Call, PathMember}, engine::{Command, EvaluationContext}, - Signature, Span, SyntaxShape, Value, + IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value, }; use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; use terminal_size::{Height, Width}; @@ -50,14 +50,14 @@ prints out the list properly."# &self, context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let width_param: Option = call.get_flag(context, "width")?; let color_param: bool = call.has_flag("color"); let separator_param: Option = call.get_flag(context, "separator")?; match input { - Value::List { vals, .. } => { + PipelineData::Value(Value::List { vals, .. }) => { // dbg!("value::list"); let data = convert_to_list2(vals); if let Some(items) = data { @@ -69,10 +69,10 @@ prints out the list properly."# separator_param, )) } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } - Value::Stream { stream, .. } => { + PipelineData::Stream(stream) => { // dbg!("value::stream"); let data = convert_to_list2(stream); if let Some(items) = data { @@ -85,10 +85,10 @@ prints out the list properly."# )) } else { // dbg!(data); - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } - Value::Record { cols, vals, .. } => { + PipelineData::Value(Value::Record { cols, vals, .. }) => { // dbg!("value::record"); let mut items = vec![]; @@ -119,7 +119,7 @@ fn create_grid_output2( width_param: Option, color_param: bool, separator_param: Option, -) -> Value { +) -> PipelineData { let ls_colors = LsColors::from_env().unwrap_or_default(); let cols = if let Some(col) = width_param { col.parse::().unwrap_or(80) @@ -167,6 +167,7 @@ fn create_grid_output2( span: call.head, } } + .into_pipeline_data() } fn convert_to_list2(iter: impl IntoIterator) -> Option> { diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 3d5f94992f..131207f552 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::{Call, PathMember}; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{ShellError, Signature, Span, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; use nu_table::StyledString; use std::collections::HashMap; use terminal_size::{Height, Width}; @@ -26,8 +26,8 @@ impl Command for Table { &self, _context: &EvaluationContext, call: &Call, - input: Value, - ) -> Result { + input: PipelineData, + ) -> Result { let term_width = if let Some((Width(w), Height(_h))) = terminal_size::terminal_size() { w as usize } else { @@ -35,7 +35,7 @@ impl Command for Table { }; match input { - Value::List { vals, .. } => { + PipelineData::Value(Value::List { vals, .. }) => { let table = convert_to_table(vals)?; if let Some(table) = table { @@ -44,12 +44,13 @@ impl Command for Table { Ok(Value::String { val: result, span: call.head, - }) + } + .into_pipeline_data()) } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } - Value::Stream { stream, .. } => { + PipelineData::Stream(stream) => { let table = convert_to_table(stream)?; if let Some(table) = table { @@ -58,12 +59,13 @@ impl Command for Table { Ok(Value::String { val: result, span: call.head, - }) + } + .into_pipeline_data()) } else { - Ok(Value::Nothing { span: call.head }) + Ok(PipelineData::new()) } } - Value::Record { cols, vals, .. } => { + PipelineData::Value(Value::Record { cols, vals, .. }) => { let mut output = vec![]; for (c, v) in cols.into_iter().zip(vals.into_iter()) { @@ -90,9 +92,10 @@ impl Command for Table { Ok(Value::String { val: result, span: call.head, - }) + } + .into_pipeline_data()) } - Value::Error { error } => Err(error), + PipelineData::Value(Value::Error { error }) => Err(error), x => Ok(x), } } diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs index 9b110f6419..d8c1836ee5 100644 --- a/crates/nu-protocol/src/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -1,4 +1,4 @@ -use crate::{Span, Value, ValueStream}; +use crate::{ast::PathMember, ShellError, Span, Value, ValueStream}; pub enum PipelineData { Value(Value), @@ -19,6 +19,25 @@ impl PipelineData { }, } } + + pub fn collect_string(self) -> String { + match self { + PipelineData::Value(v) => v.collect_string(), + PipelineData::Stream(s) => s.collect_string(), + } + } + + pub fn follow_cell_path(self, cell_path: &[PathMember]) -> Result { + match self { + // FIXME: there are probably better ways of doing this + PipelineData::Stream(stream) => Value::List { + vals: stream.collect(), + span: Span::unknown(), + } + .follow_cell_path(cell_path), + PipelineData::Value(v) => v.follow_cell_path(cell_path), + } + } } impl Default for PipelineData { From b5965ee8ef714b3e9d446f01f233b5584d2a64b6 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 25 Oct 2021 19:31:39 +1300 Subject: [PATCH 07/16] WIP --- crates/nu-cli/src/completions.rs | 16 +- crates/nu-cli/src/syntax_highlight.rs | 8 +- crates/nu-cli/src/validation.rs | 5 +- .../nu-command/src/conversions/into/binary.rs | 8 +- .../src/conversions/into/command.rs | 7 +- .../src/conversions/into/filesize.rs | 8 +- crates/nu-command/src/conversions/into/int.rs | 8 +- crates/nu-command/src/core_commands/alias.rs | 5 +- crates/nu-command/src/core_commands/def.rs | 5 +- crates/nu-command/src/core_commands/do_.rs | 17 +- .../src/core_commands/export_def.rs | 5 +- crates/nu-command/src/core_commands/for_.rs | 35 ++-- crates/nu-command/src/core_commands/help.rs | 21 ++- crates/nu-command/src/core_commands/hide.rs | 5 +- crates/nu-command/src/core_commands/if_.rs | 25 +-- crates/nu-command/src/core_commands/let_.rs | 9 +- crates/nu-command/src/core_commands/module.rs | 5 +- crates/nu-command/src/core_commands/source.rs | 11 +- crates/nu-command/src/core_commands/use_.rs | 5 +- crates/nu-command/src/default_context.rs | 11 +- crates/nu-command/src/env/let_env.rs | 9 +- crates/nu-command/src/example_test.rs | 12 +- crates/nu-command/src/experimental/git.rs | 5 +- .../src/experimental/git_checkout.rs | 7 +- .../src/experimental/list_git_branches.rs | 5 +- crates/nu-command/src/filesystem/cd.rs | 9 +- crates/nu-command/src/filesystem/cp.rs | 9 +- crates/nu-command/src/filesystem/ls.rs | 7 +- crates/nu-command/src/filesystem/mkdir.rs | 7 +- crates/nu-command/src/filesystem/mv.rs | 9 +- crates/nu-command/src/filesystem/rm.rs | 15 +- crates/nu-command/src/filesystem/touch.rs | 9 +- crates/nu-command/src/filters/each.rs | 54 ++++--- crates/nu-command/src/filters/get.rs | 7 +- crates/nu-command/src/filters/length.rs | 5 +- crates/nu-command/src/filters/lines.rs | 5 +- crates/nu-command/src/filters/select.rs | 7 +- crates/nu-command/src/filters/where_.rs | 20 +-- crates/nu-command/src/filters/wrap.rs | 7 +- crates/nu-command/src/formats/from/command.rs | 5 +- crates/nu-command/src/formats/from/json.rs | 5 +- crates/nu-command/src/strings/build_string.rs | 7 +- crates/nu-command/src/strings/size.rs | 13 +- crates/nu-command/src/strings/split/chars.rs | 5 +- crates/nu-command/src/strings/split/column.rs | 14 +- .../nu-command/src/strings/split/command.rs | 11 +- crates/nu-command/src/strings/split/row.rs | 12 +- crates/nu-command/src/system/benchmark.rs | 11 +- crates/nu-command/src/system/ps.rs | 5 +- crates/nu-command/src/system/run_external.rs | 69 +++----- crates/nu-command/src/system/sys.rs | 5 +- crates/nu-command/src/viewers/griddle.rs | 9 +- crates/nu-command/src/viewers/table.rs | 5 +- crates/nu-engine/src/call_ext.rs | 46 ++++-- crates/nu-engine/src/documentation.rs | 38 +++-- crates/nu-engine/src/eval.rs | 102 ++++++------ crates/nu-parser/tests/test_parser.rs | 5 +- crates/nu-protocol/src/engine/command.rs | 5 +- crates/nu-protocol/src/signature.rs | 8 +- src/main.rs | 150 ++++++++---------- 60 files changed, 502 insertions(+), 455 deletions(-) diff --git a/crates/nu-cli/src/completions.rs b/crates/nu-cli/src/completions.rs index 0bd47c507b..837d633f6e 100644 --- a/crates/nu-cli/src/completions.rs +++ b/crates/nu-cli/src/completions.rs @@ -10,19 +10,20 @@ use reedline::Completer; const SEP: char = std::path::MAIN_SEPARATOR; +#[derive(Clone)] pub struct NuCompleter { - engine_state: Box, + engine_state: EngineState, } impl NuCompleter { - pub fn new(engine_state: Box) -> Self { + pub fn new(engine_state: EngineState) -> Self { Self { engine_state } } } impl Completer for NuCompleter { fn complete(&self, line: &str, pos: usize) -> Vec<(reedline::Span, String)> { - let mut working_set = StateWorkingSet::new(&*self.engine_state); + let mut working_set = StateWorkingSet::new(&self.engine_state); let offset = working_set.next_span_start(); let pos = offset + pos; let (output, _err) = parse(&mut working_set, Some("completer"), line.as_bytes(), false); @@ -71,11 +72,10 @@ impl Completer for NuCompleter { let (block, ..) = parse(&mut working_set, None, custom_completion.as_bytes(), false); - let context = EvaluationContext { - engine_state: self.engine_state.clone(), - stack: Stack::default(), - }; - let result = eval_block(&context, &block, PipelineData::new()); + + let mut stack = Stack::default(); + let result = + eval_block(&self.engine_state, &mut stack, &block, PipelineData::new()); let v: Vec<_> = match result { Ok(pd) => pd diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index a8878b23c0..5ecbdcab20 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -2,21 +2,19 @@ use nu_ansi_term::Style; use nu_parser::{flatten_block, parse, FlatShape}; use nu_protocol::engine::{EngineState, StateWorkingSet}; use reedline::{Highlighter, StyledText}; -use std::{cell::RefCell, rc::Rc}; pub struct NuHighlighter { - pub engine_state: Rc>, + pub engine_state: EngineState, } impl Highlighter for NuHighlighter { fn highlight(&self, line: &str) -> StyledText { let (shapes, global_span_offset) = { - let engine_state = self.engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&self.engine_state); let (block, _) = parse(&mut working_set, None, line.as_bytes(), false); let shapes = flatten_block(&working_set, &block); - (shapes, engine_state.next_span_start()) + (shapes, self.engine_state.next_span_start()) }; let mut output = StyledText::default(); diff --git a/crates/nu-cli/src/validation.rs b/crates/nu-cli/src/validation.rs index 85bf9538ae..058bc303c5 100644 --- a/crates/nu-cli/src/validation.rs +++ b/crates/nu-cli/src/validation.rs @@ -5,13 +5,12 @@ use nu_protocol::engine::{EngineState, StateWorkingSet}; use reedline::{ValidationResult, Validator}; pub struct NuValidator { - pub engine_state: Rc>, + pub engine_state: EngineState, } impl Validator for NuValidator { fn validate(&self, line: &str) -> ValidationResult { - let engine_state = self.engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&self.engine_state); let (_, err) = parse(&mut working_set, None, line.as_bytes(), false); if matches!(err, Some(ParseError::UnexpectedEof(..))) { diff --git a/crates/nu-command/src/conversions/into/binary.rs b/crates/nu-command/src/conversions/into/binary.rs index 0658cdb0e3..e6c697e56f 100644 --- a/crates/nu-command/src/conversions/into/binary.rs +++ b/crates/nu-command/src/conversions/into/binary.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -26,11 +26,12 @@ impl Command for SubCommand { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - into_binary(context, call, input) + into_binary(call, input) } fn examples(&self) -> Vec { @@ -85,7 +86,6 @@ impl Command for SubCommand { } fn into_binary( - _context: &EvaluationContext, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/conversions/into/command.rs b/crates/nu-command/src/conversions/into/command.rs index 37741e7f4a..a745834dc7 100644 --- a/crates/nu-command/src/conversions/into/command.rs +++ b/crates/nu-command/src/conversions/into/command.rs @@ -1,7 +1,7 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, IntoPipelineData, PipelineData, Signature, Value, }; @@ -23,12 +23,13 @@ impl Command for Into { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { Ok(Value::String { - val: get_full_help(&Into.signature(), &[], context), + val: get_full_help(&Into.signature(), &[], engine_state), span: call.head, } .into_pipeline_data()) diff --git a/crates/nu-command/src/conversions/into/filesize.rs b/crates/nu-command/src/conversions/into/filesize.rs index bb2a2a8135..a5aa0d6c19 100644 --- a/crates/nu-command/src/conversions/into/filesize.rs +++ b/crates/nu-command/src/conversions/into/filesize.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -26,11 +26,12 @@ impl Command for SubCommand { fn run( &self, - context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - into_filesize(context, call, input) + into_filesize(call, input) } fn examples(&self) -> Vec { @@ -113,7 +114,6 @@ impl Command for SubCommand { } fn into_filesize( - _context: &EvaluationContext, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/conversions/into/int.rs b/crates/nu-command/src/conversions/into/int.rs index b0b29a2dc7..a4f31f2d70 100644 --- a/crates/nu-command/src/conversions/into/int.rs +++ b/crates/nu-command/src/conversions/into/int.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -26,11 +26,12 @@ impl Command for SubCommand { fn run( &self, - context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - into_int(context, call, input) + into_int(call, input) } fn examples(&self) -> Vec { @@ -89,7 +90,6 @@ impl Command for SubCommand { } fn into_int( - _context: &EvaluationContext, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/core_commands/alias.rs b/crates/nu-command/src/core_commands/alias.rs index 971d04443f..3ed9b97d84 100644 --- a/crates/nu-command/src/core_commands/alias.rs +++ b/crates/nu-command/src/core_commands/alias.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -26,7 +26,8 @@ impl Command for Alias { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/core_commands/def.rs b/crates/nu-command/src/core_commands/def.rs index 4d3808bc71..3eb3a6307e 100644 --- a/crates/nu-command/src/core_commands/def.rs +++ b/crates/nu-command/src/core_commands/def.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,7 +27,8 @@ impl Command for Def { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/core_commands/do_.rs b/crates/nu-command/src/core_commands/do_.rs index 09f6351b7a..2b38dd4277 100644 --- a/crates/nu-command/src/core_commands/do_.rs +++ b/crates/nu-command/src/core_commands/do_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -28,18 +28,19 @@ impl Command for Do { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let block_id = call.positional[0] .as_block() .expect("internal error: expected block"); - let rest: Vec = call.rest(context, 1)?; + let rest: Vec = call.rest(engine_state, stack, 1)?; - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let mut state = context.enter_scope(); + let mut stack = stack.enter_scope(); let params: Vec<_> = block .signature @@ -50,7 +51,7 @@ impl Command for Do { for param in params.iter().zip(&rest) { if let Some(var_id) = param.0.var_id { - state.add_var(var_id, param.1.clone()) + stack.add_var(var_id, param.1.clone()) } } @@ -68,7 +69,7 @@ impl Command for Do { call.head }; - state.add_var( + stack.add_var( param .var_id .expect("Internal error: rest positional parameter lacks var_id"), @@ -79,6 +80,6 @@ impl Command for Do { ) } } - eval_block(&state, block, input) + eval_block(&engine_state, &mut stack, block, input) } } diff --git a/crates/nu-command/src/core_commands/export_def.rs b/crates/nu-command/src/core_commands/export_def.rs index 2ab2430b15..910716c9f3 100644 --- a/crates/nu-command/src/core_commands/export_def.rs +++ b/crates/nu-command/src/core_commands/export_def.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,7 +27,8 @@ impl Command for ExportDef { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index 2a52296dfd..1539690e2d 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; #[derive(Clone)] @@ -37,7 +37,8 @@ impl Command for For { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { @@ -48,25 +49,25 @@ impl Command for For { let keyword_expr = call.positional[1] .as_keyword() .expect("internal error: missing keyword"); - let values = eval_expression(context, keyword_expr)?; + let values = eval_expression(engine_state, stack, keyword_expr)?; let block = call.positional[2] .as_block() .expect("internal error: expected block"); - let context = context.clone(); + let engine_state = engine_state.clone(); + let mut stack = stack.enter_scope(); match values { Value::List { vals, span } => Ok(vals .into_iter() .map(move |x| { - let block = context.engine_state.get_block(block); + let block = engine_state.get_block(block); - let mut state = context.enter_scope(); + let mut stack = stack.clone(); + stack.add_var(var_id, x); - state.add_var(var_id, x); - - match eval_block(&state, block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(value) => Value::List { vals: value.collect(), span, @@ -78,13 +79,13 @@ impl Command for For { Value::Range { val, span } => Ok(val .into_range_iter()? .map(move |x| { - let block = context.engine_state.get_block(block); + let block = engine_state.get_block(block); - let mut state = context.enter_scope(); + let mut stack = stack.enter_scope(); - state.add_var(var_id, x); + stack.add_var(var_id, x); - match eval_block(&state, block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(value) => Value::List { vals: value.collect(), span, @@ -94,13 +95,13 @@ impl Command for For { }) .into_pipeline_data()), x => { - let block = context.engine_state.get_block(block); + let block = engine_state.get_block(block); - let mut state = context.enter_scope(); + let mut stack = stack.enter_scope(); - state.add_var(var_id, x); + stack.add_var(var_id, x); - eval_block(&state, block, PipelineData::new()) + eval_block(&engine_state, &mut stack, block, PipelineData::new()) } } } diff --git a/crates/nu-command/src/core_commands/help.rs b/crates/nu-command/src/core_commands/help.rs index dc96f3bc48..990acb4c71 100644 --- a/crates/nu-command/src/core_commands/help.rs +++ b/crates/nu-command/src/core_commands/help.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, span, Example, IntoPipelineData, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value, }; @@ -36,11 +36,12 @@ impl Command for Help { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - help(context, call) + help(engine_state, stack, call) } fn examples(&self) -> Vec { @@ -74,12 +75,16 @@ impl Command for Help { } } -fn help(context: &EvaluationContext, call: &Call) -> Result { +fn help( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, +) -> Result { let head = call.head; - let find: Option> = call.get_flag(context, "find")?; - let rest: Vec> = call.rest(context, 0)?; + let find: Option> = call.get_flag(engine_state, stack, "find")?; + let rest: Vec> = call.rest(engine_state, stack, 0)?; - let full_commands = context.get_signatures_with_examples(); + let full_commands = engine_state.get_signatures_with_examples(); if let Some(f) = find { let search_string = f.item; @@ -164,7 +169,7 @@ fn help(context: &EvaluationContext, call: &Call) -> Result Result { diff --git a/crates/nu-command/src/core_commands/if_.rs b/crates/nu-command/src/core_commands/if_.rs index 16217142d0..0ea5c8785d 100644 --- a/crates/nu-command/src/core_commands/if_.rs +++ b/crates/nu-command/src/core_commands/if_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -28,7 +28,8 @@ impl Command for If { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { @@ -38,24 +39,26 @@ impl Command for If { .expect("internal error: expected block"); let else_case = call.positional.get(2); - let result = eval_expression(context, cond)?; + let result = eval_expression(engine_state, stack, cond)?; match result { Value::Bool { val, span } => { if val { - let block = context.engine_state.get_block(then_block); - let state = context.enter_scope(); - eval_block(&state, block, input) + let block = engine_state.get_block(then_block); + let mut stack = stack.enter_scope(); + eval_block(&engine_state, &mut stack, block, input) } else if let Some(else_case) = else_case { if let Some(else_expr) = else_case.as_keyword() { if let Some(block_id) = else_expr.as_block() { - let block = context.engine_state.get_block(block_id); - let state = context.enter_scope(); - eval_block(&state, block, input) + let block = engine_state.get_block(block_id); + let mut stack = stack.enter_scope(); + eval_block(&engine_state, &mut stack, block, input) } else { - eval_expression(context, else_expr).map(|x| x.into_pipeline_data()) + eval_expression(&engine_state, stack, else_expr) + .map(|x| x.into_pipeline_data()) } } else { - eval_expression(context, else_case).map(|x| x.into_pipeline_data()) + eval_expression(&engine_state, stack, else_case) + .map(|x| x.into_pipeline_data()) } } else { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/let_.rs b/crates/nu-command/src/core_commands/let_.rs index 64a7437b0a..3e3a942cd3 100644 --- a/crates/nu-command/src/core_commands/let_.rs +++ b/crates/nu-command/src/core_commands/let_.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,7 +27,8 @@ impl Command for Let { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { @@ -39,11 +40,11 @@ impl Command for Let { .as_keyword() .expect("internal error: missing keyword"); - let rhs = eval_expression(context, keyword_expr)?; + let rhs = eval_expression(&engine_state, stack, keyword_expr)?; //println!("Adding: {:?} to {}", rhs, var_id); - context.add_var(var_id, rhs); + stack.add_var(var_id, rhs); Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/core_commands/module.rs b/crates/nu-command/src/core_commands/module.rs index d7e59882ac..2476e6ab95 100644 --- a/crates/nu-command/src/core_commands/module.rs +++ b/crates/nu-command/src/core_commands/module.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -26,7 +26,8 @@ impl Command for Module { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index 17881b2152..6b9cc78852 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; /// Source a file for environment variables. @@ -26,15 +26,16 @@ impl Command for Source { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { // Note: this hidden positional is the block_id that corresponded to the 0th position // it is put here by the parser - let block_id: i64 = call.req(context, 1)?; + let block_id: i64 = call.req(engine_state, stack, 1)?; - let block = context.engine_state.get_block(block_id as usize).clone(); - eval_block(context, &block, input) + let block = engine_state.get_block(block_id as usize).clone(); + eval_block(engine_state, stack, &block, input) } } diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index ed3781b385..dfcc0124ec 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -20,7 +20,8 @@ impl Command for Use { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 1fe5d90ec3..b1ba99470b 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -1,5 +1,3 @@ -use std::{cell::RefCell, rc::Rc}; - use nu_protocol::{ engine::{EngineState, StateWorkingSet}, Signature, @@ -7,11 +5,10 @@ use nu_protocol::{ use crate::*; -pub fn create_default_context() -> Rc> { - let engine_state = Rc::new(RefCell::new(EngineState::new())); +pub fn create_default_context() -> EngineState { + let mut engine_state = EngineState::new(); let delta = { - let engine_state = engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&engine_state); macro_rules! bind_command { ( $command:expr ) => { @@ -90,7 +87,7 @@ pub fn create_default_context() -> Rc> { }; { - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + EngineState::merge_delta(&mut engine_state, delta); } engine_state diff --git a/crates/nu-command/src/env/let_env.rs b/crates/nu-command/src/env/let_env.rs index 112cfa40df..21801939cf 100644 --- a/crates/nu-command/src/env/let_env.rs +++ b/crates/nu-command/src/env/let_env.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,7 +27,8 @@ impl Command for LetEnv { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { @@ -39,12 +40,12 @@ impl Command for LetEnv { .as_keyword() .expect("internal error: missing keyword"); - let rhs = eval_expression(context, keyword_expr)?; + let rhs = eval_expression(engine_state, stack, keyword_expr)?; let rhs = rhs.as_string()?; //println!("Adding: {:?} to {}", rhs, var_id); - context.add_env_var(env_var, rhs); + stack.add_env_var(env_var, rhs); Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index 8b41ead793..8bda299baf 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc}; use nu_engine::eval_block; use nu_parser::parse; use nu_protocol::{ - engine::{Command, EngineState, EvaluationContext, StateWorkingSet}, + engine::{Command, EngineState, EvaluationContext, Stack, StateWorkingSet}, PipelineData, Value, }; @@ -37,7 +37,6 @@ pub fn test_examples(cmd: impl Command + 'static) { let start = std::time::Instant::now(); let (block, delta) = { - let engine_state = engine_state; let mut working_set = StateWorkingSet::new(&*engine_state); let (output, err) = parse(&mut working_set, None, example.example.as_bytes(), false); @@ -48,14 +47,11 @@ pub fn test_examples(cmd: impl Command + 'static) { (output, working_set.render()) }; - EngineState::merge_delta(&mut *engine_state, delta); + EngineState::merge_delta(&mut engine_state, delta); - let state = EvaluationContext { - engine_state: engine_state.clone(), - stack: nu_protocol::engine::Stack::new(), - }; + let mut stack = Stack::new(); - match eval_block(&state, &block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) { Err(err) => panic!("test eval error in `{}`: {:?}", example.example, err), Ok(result) => { let result = result.into_value(); diff --git a/crates/nu-command/src/experimental/git.rs b/crates/nu-command/src/experimental/git.rs index 57fe52c218..f4c9cf1f13 100644 --- a/crates/nu-command/src/experimental/git.rs +++ b/crates/nu-command/src/experimental/git.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; #[derive(Clone)] @@ -20,7 +20,8 @@ impl Command for Git { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/experimental/git_checkout.rs b/crates/nu-command/src/experimental/git_checkout.rs index 02b1ac01a5..0c8be2564f 100644 --- a/crates/nu-command/src/experimental/git_checkout.rs +++ b/crates/nu-command/src/experimental/git_checkout.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -25,7 +25,8 @@ impl Command for GitCheckout { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { @@ -34,7 +35,7 @@ impl Command for GitCheckout { let block = &call.positional[0]; - let out = eval_expression(context, block)?; + let out = eval_expression(engine_state, stack, block)?; let out = out.as_string()?; diff --git a/crates/nu-command/src/experimental/list_git_branches.rs b/crates/nu-command/src/experimental/list_git_branches.rs index 065b5bf2c0..a11c85efbf 100644 --- a/crates/nu-command/src/experimental/list_git_branches.rs +++ b/crates/nu-command/src/experimental/list_git_branches.rs @@ -4,6 +4,8 @@ use std::process::Command as ProcessCommand; use std::process::Stdio; use nu_protocol::ast::Call; +use nu_protocol::engine::EngineState; +use nu_protocol::engine::Stack; use nu_protocol::engine::{Command, EvaluationContext}; use nu_protocol::IntoPipelineData; use nu_protocol::PipelineData; @@ -28,7 +30,8 @@ impl Command for ListGitBranches { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index cbde266c49..5bb1dd928b 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -21,11 +21,12 @@ impl Command for Cd { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - let path: Option = call.opt(context, 0)?; + let path: Option = call.opt(engine_state, stack, 0)?; let path = match path { Some(path) => { @@ -41,7 +42,7 @@ impl Command for Cd { //FIXME: this only changes the current scope, but instead this environment variable //should probably be a block that loads the information from the state in the overlay - context.add_env_var("PWD".into(), path); + stack.add_env_var("PWD".into(), path); Ok(PipelineData::new()) } } diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 71d5a255ac..0283f8d1a6 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -5,7 +5,7 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_path::canonicalize_with; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; use crate::filesystem::util::FileStructure; @@ -38,12 +38,13 @@ impl Command for Cp { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - let source: String = call.req(context, 0)?; - let destination: String = call.req(context, 1)?; + let source: String = call.req(engine_state, stack, 0)?; + let destination: String = call.req(engine_state, stack, 1)?; let interactive = call.has_flag("interactive"); let force = call.has_flag("force"); diff --git a/crates/nu-command/src/filesystem/ls.rs b/crates/nu-command/src/filesystem/ls.rs index 8c35698bb2..6458af7b96 100644 --- a/crates/nu-command/src/filesystem/ls.rs +++ b/crates/nu-command/src/filesystem/ls.rs @@ -1,7 +1,7 @@ use chrono::{DateTime, Utc}; use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,12 +27,13 @@ impl Command for Ls { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { let pattern = if let Some(expr) = call.positional.get(0) { - let result = eval_expression(context, expr)?; + let result = eval_expression(engine_state, stack, expr)?; let mut result = result.as_string()?; let path = std::path::Path::new(&result); diff --git a/crates/nu-command/src/filesystem/mkdir.rs b/crates/nu-command/src/filesystem/mkdir.rs index 43990605b6..adb91f5d8a 100644 --- a/crates/nu-command/src/filesystem/mkdir.rs +++ b/crates/nu-command/src/filesystem/mkdir.rs @@ -3,7 +3,7 @@ use std::env::current_dir; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{ IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, }; @@ -32,13 +32,14 @@ impl Command for Mkdir { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { let path = current_dir()?; let mut directories = call - .rest::(context, 0)? + .rest::(engine_state, stack, 0)? .into_iter() .map(|dir| path.join(dir)) .peekable(); diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index ba709729e1..1e6069b8b1 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -38,13 +38,14 @@ impl Command for Mv { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { // TODO: handle invalid directory or insufficient permissions when moving - let source: String = call.req(context, 0)?; - let destination: String = call.req(context, 1)?; + let source: String = call.req(engine_state, stack, 0)?; + let destination: String = call.req(engine_state, stack, 1)?; let interactive = call.has_flag("interactive"); let force = call.has_flag("force"); diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index d64764d780..35d0f252a3 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -7,7 +7,7 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{ IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, }; @@ -59,15 +59,20 @@ impl Command for Rm { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - rm(context, call) + rm(engine_state, stack, call) } } -fn rm(context: &EvaluationContext, call: &Call) -> Result { +fn rm( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, +) -> Result { let trash = call.has_flag("trash"); let permanent = call.has_flag("permanent"); let interactive = call.has_flag("interactive"); @@ -98,7 +103,7 @@ fn rm(context: &EvaluationContext, call: &Call) -> Result(context, 0)? + .rest::(engine_state, stack, 0)? .into_iter() .map(|path| current_path.join(path)) .peekable(); diff --git a/crates/nu-command/src/filesystem/touch.rs b/crates/nu-command/src/filesystem/touch.rs index 3d323c71db..85c79d0a24 100644 --- a/crates/nu-command/src/filesystem/touch.rs +++ b/crates/nu-command/src/filesystem/touch.rs @@ -2,7 +2,7 @@ use std::fs::OpenOptions; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -29,12 +29,13 @@ impl Command for Touch { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - let target: String = call.req(context, 0)?; - let rest: Vec = call.rest(context, 1)?; + let target: String = call.req(engine_state, stack, 0)?; + let rest: Vec = call.rest(engine_state, stack, 1)?; for (index, item) in vec![target].into_iter().chain(rest).enumerate() { match OpenOptions::new().write(true).create(true).open(&item) { diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index d963fcb35c..789c42c751 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -1,6 +1,6 @@ use nu_engine::eval_block; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; #[derive(Clone)] @@ -53,7 +53,8 @@ impl Command for Each { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { @@ -62,7 +63,8 @@ impl Command for Each { .expect("internal error: expected block"); let numbered = call.has_flag("numbered"); - let context = context.clone(); + let engine_state = engine_state.clone(); + let mut stack = stack.clone(); let span = call.head; match input { @@ -70,14 +72,14 @@ impl Command for Each { .into_range_iter()? .enumerate() .map(move |(idx, x)| { - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { if numbered { - state.add_var( + stack.add_var( *var_id, Value::Record { cols: vec!["index".into(), "item".into()], @@ -92,12 +94,12 @@ impl Command for Each { }, ); } else { - state.add_var(*var_id, x); + stack.add_var(*var_id, x); } } } - match eval_block(&state, block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(v) => v, Err(error) => Value::Error { error }.into_pipeline_data(), } @@ -108,13 +110,13 @@ impl Command for Each { .into_iter() .enumerate() .map(move |(idx, x)| { - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { if numbered { - state.add_var( + stack.add_var( *var_id, Value::Record { cols: vec!["index".into(), "item".into()], @@ -129,12 +131,12 @@ impl Command for Each { }, ); } else { - state.add_var(*var_id, x); + stack.add_var(*var_id, x); } } } - match eval_block(&state, block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(v) => v, Err(error) => Value::Error { error }.into_pipeline_data(), } @@ -144,13 +146,13 @@ impl Command for Each { PipelineData::Stream(stream) => Ok(stream .enumerate() .map(move |(idx, x)| { - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { if numbered { - state.add_var( + stack.add_var( *var_id, Value::Record { cols: vec!["index".into(), "item".into()], @@ -165,12 +167,12 @@ impl Command for Each { }, ); } else { - state.add_var(*var_id, x); + stack.add_var(*var_id, x); } } } - match eval_block(&state, block, PipelineData::new()) { + match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(v) => v, Err(error) => Value::Error { error }.into_pipeline_data(), } @@ -182,12 +184,12 @@ impl Command for Each { let mut output_vals = vec![]; for (col, val) in cols.into_iter().zip(vals.into_iter()) { - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { - state.add_var( + stack.add_var( *var_id, Value::Record { cols: vec!["column".into(), "value".into()], @@ -204,7 +206,7 @@ impl Command for Each { } } - match eval_block(&state, block, PipelineData::new())? { + match eval_block(&engine_state, &mut stack, block, PipelineData::new())? { PipelineData::Value(Value::Record { mut cols, mut vals, .. }) => { @@ -227,16 +229,16 @@ impl Command for Each { .into_pipeline_data()) } PipelineData::Value(x) => { - let block = context.engine_state.get_block(block_id); + let block = engine_state.get_block(block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { - state.add_var(*var_id, x); + stack.add_var(*var_id, x); } } - eval_block(&state, block, PipelineData::new()) + eval_block(&engine_state, &mut stack, block, PipelineData::new()) } } } diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index fd4084e2bf..e7b38df853 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -25,11 +25,12 @@ impl Command for Get { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let cell_path: CellPath = call.req(context, 0)?; + let cell_path: CellPath = call.req(engine_state, stack, 0)?; input .follow_cell_path(&cell_path.members) diff --git a/crates/nu-command/src/filters/length.rs b/crates/nu-command/src/filters/length.rs index 5c7967fe8e..9fa4543dd4 100644 --- a/crates/nu-command/src/filters/length.rs +++ b/crates/nu-command/src/filters/length.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; #[derive(Clone)] @@ -20,7 +20,8 @@ impl Command for Length { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/filters/lines.rs b/crates/nu-command/src/filters/lines.rs index ec59b9d619..bb1db993af 100644 --- a/crates/nu-command/src/filters/lines.rs +++ b/crates/nu-command/src/filters/lines.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Value, ValueStream}; #[derive(Clone)] @@ -25,7 +25,8 @@ impl Command for Lines { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 6849c545c1..5c4c7f4723 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -27,11 +27,12 @@ impl Command for Select { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let columns: Vec = call.rest(context, 0)?; + let columns: Vec = call.rest(engine_state, stack, 0)?; let span = call.head; select(span, columns, input) diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index a65aacf157..5397cddd01 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::{Call, Expr, Expression}; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -21,13 +21,15 @@ impl Command for Where { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let cond = call.positional[0].clone(); - let context = context.enter_scope(); + let engine_state = engine_state.clone(); + let mut stack = stack.enter_scope(); let (var_id, cond) = match cond { Expression { @@ -40,9 +42,9 @@ impl Command for Where { match input { PipelineData::Stream(stream) => Ok(stream .filter(move |value| { - context.add_var(var_id, value.clone()); + stack.add_var(var_id, value.clone()); - let result = eval_expression(&context, &cond); + let result = eval_expression(&engine_state, &mut stack, &cond); match result { Ok(result) => result.is_true(), @@ -53,9 +55,9 @@ impl Command for Where { PipelineData::Value(Value::List { vals, span }) => Ok(vals .into_iter() .filter(move |value| { - context.add_var(var_id, value.clone()); + stack.add_var(var_id, value.clone()); - let result = eval_expression(&context, &cond); + let result = eval_expression(&engine_state, &mut stack, &cond); match result { Ok(result) => result.is_true(), @@ -64,9 +66,9 @@ impl Command for Where { }) .into_pipeline_data()), PipelineData::Value(x) => { - context.add_var(var_id, x.clone()); + stack.add_var(var_id, x.clone()); - let result = eval_expression(&context, &cond)?; + let result = eval_expression(&engine_state, &mut stack, &cond)?; if result.is_true() { Ok(x.into_pipeline_data()) diff --git a/crates/nu-command/src/filters/wrap.rs b/crates/nu-command/src/filters/wrap.rs index 9c924800e7..311f72dbea 100644 --- a/crates/nu-command/src/filters/wrap.rs +++ b/crates/nu-command/src/filters/wrap.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -21,12 +21,13 @@ impl Command for Wrap { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let span = call.head; - let name: String = call.req(context, 0)?; + let name: String = call.req(engine_state, stack, 0)?; match input { PipelineData::Value(Value::List { vals, .. }) => Ok(vals diff --git a/crates/nu-command/src/formats/from/command.rs b/crates/nu-command/src/formats/from/command.rs index 23b3d84f6f..36dd21af8e 100644 --- a/crates/nu-command/src/formats/from/command.rs +++ b/crates/nu-command/src/formats/from/command.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, ShellError, Signature, Value}; #[derive(Clone)] @@ -20,7 +20,8 @@ impl Command for From { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, _call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index 598544aafd..db5af67197 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; #[derive(Clone)] @@ -68,7 +68,8 @@ impl Command for FromJson { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/strings/build_string.rs b/crates/nu-command/src/strings/build_string.rs index 4e80d1128f..1cea5a1a46 100644 --- a/crates/nu-command/src/strings/build_string.rs +++ b/crates/nu-command/src/strings/build_string.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -44,14 +44,15 @@ impl Command for BuildString { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { let output = call .positional .iter() - .map(|expr| eval_expression(context, expr).map(|val| val.into_string())) + .map(|expr| eval_expression(engine_state, stack, expr).map(|val| val.into_string())) .collect::, ShellError>>()?; Ok(Value::String { diff --git a/crates/nu-command/src/strings/size.rs b/crates/nu-command/src/strings/size.rs index b40f3abf4d..0f919f5774 100644 --- a/crates/nu-command/src/strings/size.rs +++ b/crates/nu-command/src/strings/size.rs @@ -3,7 +3,7 @@ extern crate unicode_segmentation; use unicode_segmentation::UnicodeSegmentation; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; @@ -26,11 +26,12 @@ impl Command for Size { fn run( &self, - context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - size(context, call, input) + size(call, input) } fn examples(&self) -> Vec { @@ -101,11 +102,7 @@ impl Command for Size { } } -fn size( - _context: &EvaluationContext, - call: &Call, - input: PipelineData, -) -> Result { +fn size(call: &Call, input: PipelineData) -> Result { let span = call.head; Ok(input .map(move |v| match v.as_string() { diff --git a/crates/nu-command/src/strings/split/chars.rs b/crates/nu-command/src/strings/split/chars.rs index e0ceaa9cb8..f71f8913a8 100644 --- a/crates/nu-command/src/strings/split/chars.rs +++ b/crates/nu-command/src/strings/split/chars.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; @@ -39,7 +39,8 @@ impl Command for SubCommand { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/strings/split/column.rs b/crates/nu-command/src/strings/split/column.rs index 3b7bcae082..d2b370d9d6 100644 --- a/crates/nu-command/src/strings/split/column.rs +++ b/crates/nu-command/src/strings/split/column.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; @@ -34,22 +34,24 @@ impl Command for SubCommand { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - split_column(context, call, input) + split_column(engine_state, stack, call, input) } } fn split_column( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let name_span = call.head; - let separator: Spanned = call.req(context, 0)?; - let rest: Vec> = call.rest(context, 1)?; + let separator: Spanned = call.req(engine_state, stack, 0)?; + let rest: Vec> = call.rest(engine_state, stack, 1)?; let collapse_empty = call.has_flag("collapse-empty"); Ok(input diff --git a/crates/nu-command/src/strings/split/command.rs b/crates/nu-command/src/strings/split/command.rs index 2afaaee625..e25ea589b7 100644 --- a/crates/nu-command/src/strings/split/command.rs +++ b/crates/nu-command/src/strings/split/command.rs @@ -1,7 +1,7 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, IntoPipelineData, PipelineData, Signature, Value, }; @@ -23,12 +23,17 @@ impl Command for SplitCommand { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { Ok(Value::String { - val: get_full_help(&SplitCommand.signature(), &SplitCommand.examples(), context), + val: get_full_help( + &SplitCommand.signature(), + &SplitCommand.examples(), + engine_state, + ), span: call.head, } .into_pipeline_data()) diff --git a/crates/nu-command/src/strings/split/row.rs b/crates/nu-command/src/strings/split/row.rs index 6b24e2c792..5bf8ae02a8 100644 --- a/crates/nu-command/src/strings/split/row.rs +++ b/crates/nu-command/src/strings/split/row.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; @@ -27,21 +27,23 @@ impl Command for SubCommand { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - split_row(context, call, input) + split_row(engine_state, stack, call, input) } } fn split_row( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let name_span = call.head; - let separator: Spanned = call.req(context, 0)?; + let separator: Spanned = call.req(engine_state, stack, 0)?; Ok(input .flat_map(move |x| split_row_helper(&x, &separator, name_span)) diff --git a/crates/nu-command/src/system/benchmark.rs b/crates/nu-command/src/system/benchmark.rs index 932b8b1265..7913c16719 100644 --- a/crates/nu-command/src/system/benchmark.rs +++ b/crates/nu-command/src/system/benchmark.rs @@ -2,7 +2,7 @@ use std::time::Instant; use nu_engine::eval_block; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -27,18 +27,19 @@ impl Command for Benchmark { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { let block = call.positional[0] .as_block() .expect("internal error: expected block"); - let block = context.engine_state.get_block(block); + let block = engine_state.get_block(block); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); let start_time = Instant::now(); - eval_block(&state, block, PipelineData::new())?; + eval_block(&engine_state, &mut stack, block, PipelineData::new())?; let end_time = Instant::now(); println!("{} ms", (end_time - start_time).as_millis()); Ok(PipelineData::new()) diff --git a/crates/nu-command/src/system/ps.rs b/crates/nu-command/src/system/ps.rs index 6e5072ae73..d816a4472f 100644 --- a/crates/nu-command/src/system/ps.rs +++ b/crates/nu-command/src/system/ps.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value, }; use sysinfo::{ProcessExt, System, SystemExt}; @@ -30,7 +30,8 @@ impl Command for Ps { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 9ac2817a48..84a74dc974 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -1,19 +1,21 @@ use std::borrow::Cow; use std::cell::RefCell; +use std::collections::HashMap; use std::env; use std::io::{BufRead, BufReader, Write}; use std::process::{ChildStdin, Command as CommandSys, Stdio}; use std::rc::Rc; use std::sync::mpsc; +use nu_protocol::engine::{EngineState, Stack}; use nu_protocol::{ ast::{Call, Expression}, engine::{Command, EvaluationContext}, ShellError, Signature, SyntaxShape, Value, }; -use nu_protocol::{IntoPipelineData, PipelineData, Span, ValueStream}; +use nu_protocol::{IntoPipelineData, PipelineData, Span, Spanned, ValueStream}; -use nu_engine::eval_expression; +use nu_engine::{eval_expression, CallExt}; const OUTPUT_BUFFER_SIZE: usize = 8192; @@ -37,52 +39,34 @@ impl Command for External { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let command = ExternalCommand::try_new(call, context)?; + let name: Spanned = call.req(engine_state, stack, 0)?; + let args: Vec = call.rest(engine_state, stack, 1)?; + let last_expression = call.has_flag("last_expression"); + let env_vars = stack.get_env_vars(); + + let command = ExternalCommand { + name, + args, + last_expression, + env_vars, + }; command.run_with_input(input) } } -pub struct ExternalCommand<'call, 'contex> { - pub name: &'call Expression, - pub args: &'call [Expression], - pub context: &'contex EvaluationContext, +pub struct ExternalCommand { + pub name: Spanned, + pub args: Vec, pub last_expression: bool, + pub env_vars: HashMap, } -impl<'call, 'contex> ExternalCommand<'call, 'contex> { - pub fn try_new( - call: &'call Call, - context: &'contex EvaluationContext, - ) -> Result { - if call.positional.is_empty() { - return Err(ShellError::ExternalNotSupported(call.head)); - } - - Ok(Self { - name: &call.positional[0], - args: &call.positional[1..], - context, - last_expression: call.has_flag("last_expression"), - }) - } - - pub fn get_name(&self) -> Result { - let value = eval_expression(self.context, self.name)?; - value.as_string() - } - - pub fn get_args(&self) -> Vec { - self.args - .iter() - .filter_map(|expr| eval_expression(self.context, expr).ok()) - .filter_map(|value| value.as_string().ok()) - .collect() - } - +impl ExternalCommand { pub fn run_with_input(&self, input: PipelineData) -> Result { let mut process = self.create_command(); @@ -91,8 +75,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { let path = env::current_dir().unwrap(); process.current_dir(path); - let envs = self.context.stack.get_env_vars(); - process.envs(envs); + process.envs(&self.env_vars); // If the external is not the last command, its output will get piped // either as a string or binary @@ -195,8 +178,8 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { // for minimal builds cwd is unused let mut process = CommandSys::new("cmd"); process.arg("/c"); - process.arg(&self.get_name().unwrap()); - for arg in self.get_args() { + process.arg(&self.name.item); + for arg in &self.args { // Clean the args before we use them: // https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe // cmd.exe needs to have a caret to escape a pipe @@ -205,7 +188,7 @@ impl<'call, 'contex> ExternalCommand<'call, 'contex> { } process } else { - let cmd_with_args = vec![self.get_name().unwrap(), self.get_args().join(" ")].join(" "); + let cmd_with_args = vec![self.name.item.clone(), self.args.join(" ")].join(" "); let mut process = CommandSys::new("sh"); process.arg("-c").arg(cmd_with_args); process diff --git a/crates/nu-command/src/system/sys.rs b/crates/nu-command/src/system/sys.rs index 8541b4649b..b1aa54daa2 100644 --- a/crates/nu-command/src/system/sys.rs +++ b/crates/nu-command/src/system/sys.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value, }; use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt}; @@ -25,7 +25,8 @@ impl Command for Sys { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs index 462c476abd..fb752a58a8 100644 --- a/crates/nu-command/src/viewers/griddle.rs +++ b/crates/nu-command/src/viewers/griddle.rs @@ -2,7 +2,7 @@ use lscolors::{LsColors, Style}; use nu_engine::CallExt; use nu_protocol::{ ast::{Call, PathMember}, - engine::{Command, EvaluationContext}, + engine::{Command, EngineState, EvaluationContext, Stack}, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value, }; use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; @@ -48,13 +48,14 @@ prints out the list properly."# fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let width_param: Option = call.get_flag(context, "width")?; + let width_param: Option = call.get_flag(engine_state, stack, "width")?; let color_param: bool = call.has_flag("color"); - let separator_param: Option = call.get_flag(context, "separator")?; + let separator_param: Option = call.get_flag(engine_state, stack, "separator")?; match input { PipelineData::Value(Value::List { vals, .. }) => { diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 131207f552..2fca815b68 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::{Call, PathMember}; -use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; use nu_table::StyledString; use std::collections::HashMap; @@ -24,7 +24,8 @@ impl Command for Table { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-engine/src/call_ext.rs b/crates/nu-engine/src/call_ext.rs index 9e311600a2..1ea0ef163e 100644 --- a/crates/nu-engine/src/call_ext.rs +++ b/crates/nu-engine/src/call_ext.rs @@ -1,37 +1,50 @@ -use nu_protocol::{ast::Call, engine::EvaluationContext, ShellError}; +use nu_protocol::{ + ast::Call, + engine::{EngineState, EvaluationContext, Stack}, + ShellError, +}; use crate::{eval_expression, FromValue}; pub trait CallExt { fn get_flag( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, name: &str, ) -> Result, ShellError>; fn rest( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, starting_pos: usize, ) -> Result, ShellError>; fn opt( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, pos: usize, ) -> Result, ShellError>; - fn req(&self, context: &EvaluationContext, pos: usize) -> Result; + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result; } impl CallExt for Call { fn get_flag( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, name: &str, ) -> Result, ShellError> { if let Some(expr) = self.get_flag_expr(name) { - let result = eval_expression(context, &expr)?; + let result = eval_expression(engine_state, stack, &expr)?; FromValue::from_value(&result).map(Some) } else { Ok(None) @@ -40,13 +53,14 @@ impl CallExt for Call { fn rest( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, starting_pos: usize, ) -> Result, ShellError> { let mut output = vec![]; for expr in self.positional.iter().skip(starting_pos) { - let result = eval_expression(context, expr)?; + let result = eval_expression(engine_state, stack, expr)?; output.push(FromValue::from_value(&result)?); } @@ -55,20 +69,26 @@ impl CallExt for Call { fn opt( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, pos: usize, ) -> Result, ShellError> { if let Some(expr) = self.nth(pos) { - let result = eval_expression(context, &expr)?; + let result = eval_expression(engine_state, stack, &expr)?; FromValue::from_value(&result).map(Some) } else { Ok(None) } } - fn req(&self, context: &EvaluationContext, pos: usize) -> Result { + fn req( + &self, + engine_state: &EngineState, + stack: &mut Stack, + pos: usize, + ) -> Result { if let Some(expr) = self.nth(pos) { - let result = eval_expression(context, &expr)?; + let result = eval_expression(engine_state, stack, &expr)?; FromValue::from_value(&result) } else { Err(ShellError::AccessBeyondEnd( diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index c028625d77..ce9c3b52b9 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -1,5 +1,8 @@ use itertools::Itertools; -use nu_protocol::{engine::EvaluationContext, Example, Signature, Span, Value}; +use nu_protocol::{ + engine::{EngineState, EvaluationContext}, + Example, Signature, Span, Value, +}; use std::collections::HashMap; const COMMANDS_DOCS_DIR: &str = "docs/commands"; @@ -22,14 +25,13 @@ impl Default for DocumentationConfig { } } -fn generate_doc(name: &str, context: &EvaluationContext) -> (Vec, Vec) { +fn generate_doc(name: &str, engine_state: &EngineState) -> (Vec, Vec) { let mut cols = vec![]; let mut vals = vec![]; - let command = context - .engine_state + let command = engine_state .find_decl(name.as_bytes()) - .map(|decl_id| context.engine_state.get_decl(decl_id)) + .map(|decl_id| engine_state.get_decl(decl_id)) .unwrap_or_else(|| panic!("Expected command '{}' from names to be in registry", name)); cols.push("name".to_string()); @@ -57,7 +59,7 @@ fn generate_doc(name: &str, context: &EvaluationContext) -> (Vec, Vec (Vec, Vec Value { - let signatures = context.get_signatures(); +pub fn generate_docs(engine_state: &EngineState) -> Value { + let signatures = engine_state.get_signatures(); // cmap will map parent commands to it's subcommands e.g. to -> [to csv, to yaml, to bson] let mut cmap: HashMap> = HashMap::new(); @@ -98,11 +100,11 @@ pub fn generate_docs(context: &EvaluationContext) -> Value { if !cmap.contains_key(&sig.name) { continue; } - let mut row_entries = generate_doc(&sig.name, context); + let mut row_entries = generate_doc(&sig.name, engine_state); // Iterate over all the subcommands of the parent command let mut sub_table = Vec::new(); for sub_name in cmap.get(&sig.name).unwrap_or(&Vec::new()) { - let (cols, vals) = generate_doc(sub_name, context); + let (cols, vals) = generate_doc(sub_name, engine_state); sub_table.push(Value::Record { cols, vals, @@ -148,7 +150,7 @@ fn retrieve_doc_link(name: &str) -> Option { pub fn get_documentation( sig: &Signature, examples: &[Example], - context: &EvaluationContext, + engine_state: &EngineState, config: &DocumentationConfig, ) -> String { let cmd_name = &sig.name; @@ -168,7 +170,7 @@ pub fn get_documentation( let mut subcommands = vec![]; if !config.no_subcommands { - let signatures = context.get_signatures(); + let signatures = engine_state.get_signatures(); for sig in signatures { if sig.name.starts_with(&format!("{} ", cmd_name)) { subcommands.push(format!(" {} - {}", sig.name, sig.usage)); @@ -324,15 +326,11 @@ fn get_flags_section(signature: &Signature) -> String { long_desc } -pub fn get_brief_help( - sig: &Signature, - examples: &[Example], - context: &EvaluationContext, -) -> String { +pub fn get_brief_help(sig: &Signature, examples: &[Example], engine_state: &EngineState) -> String { get_documentation( sig, examples, - context, + engine_state, &DocumentationConfig { no_subcommands: false, no_color: false, @@ -341,6 +339,6 @@ pub fn get_brief_help( ) } -pub fn get_full_help(sig: &Signature, examples: &[Example], context: &EvaluationContext) -> String { - get_documentation(sig, examples, context, &DocumentationConfig::default()) +pub fn get_full_help(sig: &Signature, examples: &[Example], engine_state: &EngineState) -> String { + get_documentation(sig, examples, engine_state, &DocumentationConfig::default()) } diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 630067b03e..91901b3de2 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; -use nu_protocol::engine::EvaluationContext; +use nu_protocol::engine::{EngineState, EvaluationContext, Stack}; use nu_protocol::{ IntoPipelineData, PipelineData, Range, ShellError, Span, Spanned, Type, Unit, Value, }; @@ -19,32 +19,33 @@ pub fn eval_operator(op: &Expression) -> Result { } fn eval_call( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { - let decl = context.engine_state.get_decl(call.decl_id); + let decl = engine_state.get_decl(call.decl_id); if call.named.iter().any(|(flag, _)| flag.item == "help") { - let full_help = get_full_help(&decl.signature(), &decl.examples(), context); + let full_help = get_full_help(&decl.signature(), &decl.examples(), engine_state); Ok(Value::String { val: full_help, span: call.head, } .into_pipeline_data()) } else if let Some(block_id) = decl.get_block_id() { - let mut state = context.enter_scope(); + let mut stack = stack.enter_scope(); for (arg, param) in call.positional.iter().zip( decl.signature() .required_positional .iter() .chain(decl.signature().optional_positional.iter()), ) { - let result = eval_expression(&state, arg)?; + let result = eval_expression(engine_state, &mut stack, arg)?; let var_id = param .var_id .expect("internal error: all custom parameters must have var_ids"); - state.add_var(var_id, result); + stack.add_var(var_id, result); } if let Some(rest_positional) = decl.signature().rest_positional { @@ -54,7 +55,7 @@ fn eval_call( decl.signature().required_positional.len() + decl.signature().optional_positional.len(), ) { - let result = eval_expression(&state, arg)?; + let result = eval_expression(&engine_state, &mut stack, arg)?; rest_items.push(result); } @@ -64,7 +65,7 @@ fn eval_call( Span::unknown() }; - state.add_var( + stack.add_var( rest_positional .var_id .expect("Internal error: rest positional parameter lacks var_id"), @@ -81,11 +82,11 @@ fn eval_call( for call_named in &call.named { if call_named.0.item == named.long { if let Some(arg) = &call_named.1 { - let result = eval_expression(&state, arg)?; + let result = eval_expression(&engine_state, &mut stack, arg)?; - state.add_var(var_id, result); + stack.add_var(var_id, result); } else { - state.add_var( + stack.add_var( var_id, Value::Bool { val: true, @@ -98,7 +99,7 @@ fn eval_call( } if !found && named.arg.is_none() { - state.add_var( + stack.add_var( var_id, Value::Bool { val: false, @@ -108,27 +109,27 @@ fn eval_call( } } } - let block = context.engine_state.get_block(block_id); - eval_block(&state, block, input) + let block = engine_state.get_block(block_id); + eval_block(engine_state, &mut stack, block, input) } else { - decl.run(context, call, input) + decl.run(engine_state, stack, call, input) } } fn eval_external( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, name: &str, name_span: &Span, args: &[Expression], input: PipelineData, last_expression: bool, ) -> Result { - let decl_id = context - .engine_state + let decl_id = engine_state .find_decl("run_external".as_bytes()) .ok_or_else(|| ShellError::ExternalNotSupported(*name_span))?; - let command = context.engine_state.get_decl(decl_id); + let command = engine_state.get_decl(decl_id); let mut call = Call::new(); @@ -153,11 +154,12 @@ fn eval_external( )) } - command.run(context, &call, input) + command.run(engine_state, stack, &call, input) } pub fn eval_expression( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, expr: &Expression, ) -> Result { match &expr.expr { @@ -173,13 +175,13 @@ pub fn eval_expression( val: *f, span: expr.span, }), - Expr::ValueWithUnit(e, unit) => match eval_expression(context, e)? { + Expr::ValueWithUnit(e, unit) => match eval_expression(engine_state, stack, e)? { Value::Int { val, .. } => Ok(compute(val, unit.item, unit.span)), _ => Err(ShellError::CantConvert("unit value".into(), e.span)), }, Expr::Range(from, next, to, operator) => { let from = if let Some(f) = from { - eval_expression(context, f)? + eval_expression(engine_state, stack, f)? } else { Value::Nothing { span: Span::unknown(), @@ -187,7 +189,7 @@ pub fn eval_expression( }; let next = if let Some(s) = next { - eval_expression(context, s)? + eval_expression(engine_state, stack, s)? } else { Value::Nothing { span: Span::unknown(), @@ -195,7 +197,7 @@ pub fn eval_expression( }; let to = if let Some(t) = to { - eval_expression(context, t)? + eval_expression(engine_state, stack, t)? } else { Value::Nothing { span: Span::unknown(), @@ -207,7 +209,7 @@ pub fn eval_expression( span: expr.span, }) } - Expr::Var(var_id) => context + Expr::Var(var_id) => stack .get_var(*var_id) .map_err(move |_| ShellError::VariableNotFoundAtRuntime(expr.span)), Expr::CellPath(cell_path) => Ok(Value::CellPath { @@ -215,32 +217,40 @@ pub fn eval_expression( span: expr.span, }), Expr::FullCellPath(cell_path) => { - let value = eval_expression(context, &cell_path.head)?; + let value = eval_expression(engine_state, stack, &cell_path.head)?; value.follow_cell_path(&cell_path.tail) } - Expr::RowCondition(_, expr) => eval_expression(context, expr), + Expr::RowCondition(_, expr) => eval_expression(engine_state, stack, expr), Expr::Call(call) => { // FIXME: protect this collect with ctrl-c Ok(Value::List { - vals: eval_call(context, call, PipelineData::new())?.collect(), + vals: eval_call(engine_state, stack, call, PipelineData::new())?.collect(), span: expr.span, }) } Expr::ExternalCall(name, span, args) => { // FIXME: protect this collect with ctrl-c Ok(Value::List { - vals: eval_external(context, name, span, args, PipelineData::new(), true)? - .collect(), + vals: eval_external( + engine_state, + stack, + name, + span, + args, + PipelineData::new(), + true, + )? + .collect(), span: expr.span, }) } Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }), Expr::BinaryOp(lhs, op, rhs) => { let op_span = op.span; - let lhs = eval_expression(context, lhs)?; + let lhs = eval_expression(engine_state, stack, lhs)?; let op = eval_operator(op)?; - let rhs = eval_expression(context, rhs)?; + let rhs = eval_expression(engine_state, stack, rhs)?; match op { Operator::Plus => lhs.add(op_span, &rhs), @@ -264,13 +274,13 @@ pub fn eval_expression( } } Expr::Subexpression(block_id) => { - let block = context.engine_state.get_block(*block_id); + let block = engine_state.get_block(*block_id); - let state = context.enter_scope(); + let mut stack = stack.enter_scope(); // FIXME: protect this collect with ctrl-c Ok(Value::List { - vals: eval_block(&state, block, PipelineData::new())?.collect(), + vals: eval_block(engine_state, &mut stack, block, PipelineData::new())?.collect(), span: expr.span, }) } @@ -281,7 +291,7 @@ pub fn eval_expression( Expr::List(x) => { let mut output = vec![]; for expr in x { - output.push(eval_expression(context, expr)?); + output.push(eval_expression(engine_state, stack, expr)?); } Ok(Value::List { vals: output, @@ -291,14 +301,14 @@ pub fn eval_expression( Expr::Table(headers, vals) => { let mut output_headers = vec![]; for expr in headers { - output_headers.push(eval_expression(context, expr)?.as_string()?); + output_headers.push(eval_expression(engine_state, stack, expr)?.as_string()?); } let mut output_rows = vec![]; for val in vals { let mut row = vec![]; for expr in val { - row.push(eval_expression(context, expr)?); + row.push(eval_expression(engine_state, stack, expr)?); } output_rows.push(Value::Record { cols: output_headers.clone(), @@ -311,7 +321,7 @@ pub fn eval_expression( span: expr.span, }) } - Expr::Keyword(_, _, expr) => eval_expression(context, expr), + Expr::Keyword(_, _, expr) => eval_expression(engine_state, stack, expr), Expr::String(s) => Ok(Value::String { val: s.clone(), span: expr.span, @@ -330,7 +340,8 @@ pub fn eval_expression( } pub fn eval_block( - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, block: &Block, mut input: PipelineData, ) -> Result { @@ -342,14 +353,15 @@ pub fn eval_block( expr: Expr::Call(call), .. } => { - input = eval_call(context, call, input)?; + input = eval_call(engine_state, stack, call, input)?; } Expression { expr: Expr::ExternalCall(name, name_span, args), .. } => { input = eval_external( - context, + engine_state, + stack, name, name_span, args, @@ -359,7 +371,7 @@ pub fn eval_block( } elem => { - input = eval_expression(context, elem)?.into_pipeline_data(); + input = eval_expression(engine_state, stack, elem)?.into_pipeline_data(); } } } diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index da45d1f1c4..1b708f27e6 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -2,7 +2,7 @@ use nu_parser::ParseError; use nu_parser::*; use nu_protocol::{ ast::{Expr, Expression, Pipeline, Statement}, - engine::{Command, EngineState, StateWorkingSet}, + engine::{Command, EngineState, Stack, StateWorkingSet}, Signature, SyntaxShape, }; @@ -32,7 +32,8 @@ impl Command for Let { fn run( &self, - _context: &nu_protocol::engine::EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, _call: &nu_protocol::ast::Call, _input: nu_protocol::PipelineData, ) -> Result { diff --git a/crates/nu-protocol/src/engine/command.rs b/crates/nu-protocol/src/engine/command.rs index a8b3a5581d..6a6955c182 100644 --- a/crates/nu-protocol/src/engine/command.rs +++ b/crates/nu-protocol/src/engine/command.rs @@ -1,6 +1,6 @@ use crate::{ast::Call, value::Value, BlockId, Example, PipelineData, ShellError, Signature}; -use super::EvaluationContext; +use super::{EngineState, EvaluationContext, Stack}; pub trait Command: Send + Sync + CommandClone { fn name(&self) -> &str; @@ -17,7 +17,8 @@ pub trait Command: Send + Sync + CommandClone { fn run( &self, - context: &EvaluationContext, + engine_state: &EngineState, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result; diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index 4c2a36313b..b7037a4bc6 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -1,7 +1,9 @@ use crate::ast::Call; use crate::engine::Command; use crate::engine::CommandClone; +use crate::engine::EngineState; use crate::engine::EvaluationContext; +use crate::engine::Stack; use crate::BlockId; use crate::PipelineData; use crate::SyntaxShape; @@ -357,7 +359,8 @@ impl Command for Predeclaration { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, _call: &Call, _input: PipelineData, ) -> Result { @@ -386,7 +389,8 @@ impl Command for BlockCommand { fn run( &self, - _context: &EvaluationContext, + _engine_state: &EngineState, + _stack: &mut Stack, _call: &Call, _input: PipelineData, ) -> Result { diff --git a/src/main.rs b/src/main.rs index 0ccece42fb..9a2726c8af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use nu_parser::parse; use nu_protocol::{ ast::Call, engine::{EngineState, EvaluationContext, Stack, StateWorkingSet}, - ShellError, Value, + IntoPipelineData, PipelineData, ShellError, Value, }; use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt}; @@ -82,14 +82,13 @@ fn main() -> Result<()> { miette_hook(x); })); - let engine_state = create_default_context(); + let mut engine_state = create_default_context(); if let Some(path) = std::env::args().nth(1) { let file = std::fs::read(&path).into_diagnostic()?; let (block, delta) = { - let engine_state = engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&engine_state); let (output, err) = parse(&mut working_set, Some(&path), &file, false); if let Some(err) = err { report_error(&working_set, &err); @@ -99,20 +98,16 @@ fn main() -> Result<()> { (output, working_set.render()) }; - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + EngineState::merge_delta(&mut engine_state, delta); - let state = EvaluationContext { - engine_state: engine_state.clone(), - stack: nu_protocol::engine::Stack::new(), - }; + let mut stack = nu_protocol::engine::Stack::new(); - match eval_block(&state, &block, Value::nothing()) { - Ok(value) => { - println!("{}", value.into_string()); + match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) { + Ok(pipeline_data) => { + println!("{}", pipeline_data.collect_string()); } Err(err) => { - let engine_state = engine_state.borrow(); - let working_set = StateWorkingSet::new(&*engine_state); + let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &err); @@ -127,28 +122,9 @@ fn main() -> Result<()> { let completer = NuCompleter::new(engine_state.clone()); let mut entry_num = 0; - let mut line_editor = Reedline::create() - .into_diagnostic()? - .with_history(Box::new( - FileBackedHistory::with_file(1000, "history.txt".into()).into_diagnostic()?, - )) - .into_diagnostic()? - .with_highlighter(Box::new(NuHighlighter { - engine_state: engine_state.clone(), - })) - .with_completion_action_handler(Box::new(FuzzyCompletion { - completer: Box::new(completer), - })) - // .with_completion_action_handler(Box::new( - // ListCompletionHandler::default().with_completer(Box::new(completer)), - // )) - .with_validator(Box::new(NuValidator { - engine_state: engine_state.clone(), - })); - let default_prompt = DefaultPrompt::new(1); let mut nu_prompt = NushellPrompt::new(); - let stack = nu_protocol::engine::Stack::new(); + let mut stack = nu_protocol::engine::Stack::new(); // Load config startup file if let Some(mut config_path) = nu_path::config_dir() { @@ -162,15 +138,34 @@ fn main() -> Result<()> { let config_filename = config_path.to_string_lossy().to_owned(); if let Ok(contents) = std::fs::read_to_string(&config_path) { - eval_source(engine_state.clone(), &stack, &contents, &config_filename); + eval_source(&mut engine_state, &mut stack, &contents, &config_filename); } } } loop { + let mut line_editor = Reedline::create() + .into_diagnostic()? + .with_history(Box::new( + FileBackedHistory::with_file(1000, "history.txt".into()).into_diagnostic()?, + )) + .into_diagnostic()? + .with_highlighter(Box::new(NuHighlighter { + engine_state: engine_state.clone(), + })) + .with_completion_action_handler(Box::new(FuzzyCompletion { + completer: Box::new(completer.clone()), + })) + // .with_completion_action_handler(Box::new( + // ListCompletionHandler::default().with_completer(Box::new(completer)), + // )) + .with_validator(Box::new(NuValidator { + engine_state: engine_state.clone(), + })); + let prompt = update_prompt( PROMPT_COMMAND, - engine_state.clone(), + &engine_state, &stack, &mut nu_prompt, &default_prompt, @@ -184,25 +179,27 @@ fn main() -> Result<()> { if s.trim() == "exit" { break; } else if s.trim() == "vars" { - engine_state.borrow().print_vars(); + engine_state.print_vars(); continue; } else if s.trim() == "decls" { - engine_state.borrow().print_decls(); + engine_state.print_decls(); continue; } else if s.trim() == "blocks" { - engine_state.borrow().print_blocks(); + engine_state.print_blocks(); continue; } else if s.trim() == "stack" { stack.print_stack(); continue; } else if s.trim() == "contents" { - engine_state.borrow().print_contents(); + engine_state.print_contents(); continue; } + let mut engine_state = engine_state.clone(); + eval_source( - engine_state.clone(), - &stack, + &mut engine_state, + &mut stack, &s, &format!("entry #{}", entry_num), ); @@ -229,16 +226,19 @@ fn main() -> Result<()> { } } -fn print_value(value: Value, state: &EvaluationContext) -> Result<(), ShellError> { +fn print_value(value: Value, engine_state: &EngineState) -> Result<(), ShellError> { // If the table function is in the declarations, then we can use it // to create the table value that will be printed in the terminal - let engine_state = state.engine_state.borrow(); let output = match engine_state.find_decl("table".as_bytes()) { Some(decl_id) => { - let table = engine_state - .get_decl(decl_id) - .run(state, &Call::new(), value)?; - table.into_string() + let mut stack = Stack::new(); + let table = engine_state.get_decl(decl_id).run( + engine_state, + &mut stack, + &Call::new(), + value.into_pipeline_data(), + )?; + table.collect_string() } None => value.into_string(), }; @@ -254,7 +254,7 @@ fn print_value(value: Value, state: &EvaluationContext) -> Result<(), ShellError fn update_prompt<'prompt>( env_variable: &str, - engine_state: Rc>, + engine_state: &EngineState, stack: &Stack, nu_prompt: &'prompt mut NushellPrompt, default_prompt: &'prompt DefaultPrompt, @@ -271,8 +271,7 @@ fn update_prompt<'prompt>( } let (block, delta) = { - let ref_engine_state = engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&ref_engine_state); + let mut working_set = StateWorkingSet::new(&engine_state); let (output, err) = parse(&mut working_set, None, prompt_command.as_bytes(), false); if let Some(err) = err { report_error(&working_set, &err); @@ -281,26 +280,13 @@ fn update_prompt<'prompt>( (output, working_set.render()) }; - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + let mut stack = stack.clone(); - let state = nu_protocol::engine::EvaluationContext { - engine_state: engine_state.clone(), - stack: stack.clone(), - }; - - let evaluated_prompt = match eval_block(&state, &block, Value::nothing()) { - Ok(value) => match value.as_string() { - Ok(prompt) => prompt, - Err(err) => { - let engine_state = engine_state.borrow(); - let working_set = StateWorkingSet::new(&*engine_state); - report_error(&working_set, &err); - return default_prompt as &dyn Prompt; - } - }, + let evaluated_prompt = match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) + { + Ok(pipeline_data) => pipeline_data.collect_string(), Err(err) => { - let engine_state = engine_state.borrow(); - let working_set = StateWorkingSet::new(&*engine_state); + let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &err); return default_prompt as &dyn Prompt; } @@ -312,14 +298,13 @@ fn update_prompt<'prompt>( } fn eval_source( - engine_state: Rc>, - stack: &Stack, + engine_state: &mut EngineState, + stack: &mut Stack, source: &str, fname: &str, ) -> bool { let (block, delta) = { - let engine_state = engine_state.borrow(); - let mut working_set = StateWorkingSet::new(&*engine_state); + let mut working_set = StateWorkingSet::new(&engine_state); let (output, err) = parse( &mut working_set, Some(fname), // format!("entry #{}", entry_num) @@ -333,26 +318,19 @@ fn eval_source( (output, working_set.render()) }; - EngineState::merge_delta(&mut *engine_state.borrow_mut(), delta); + EngineState::merge_delta(engine_state, delta); - let state = nu_protocol::engine::EvaluationContext { - engine_state: engine_state.clone(), - stack: stack.clone(), - }; - - match eval_block(&state, &block, Value::nothing()) { - Ok(value) => { - if let Err(err) = print_value(value, &state) { - let engine_state = engine_state.borrow(); - let working_set = StateWorkingSet::new(&*engine_state); + match eval_block(&engine_state, stack, &block, PipelineData::new()) { + Ok(pipeline_data) => { + if let Err(err) = print_value(pipeline_data.into_value(), &engine_state) { + let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &err); return false; } } Err(err) => { - let engine_state = engine_state.borrow(); - let working_set = StateWorkingSet::new(&*engine_state); + let working_set = StateWorkingSet::new(&engine_state); report_error(&working_set, &err); return false; From baac60a5a71336882af37b94474710a365738cbc Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 25 Oct 2021 19:42:38 +1300 Subject: [PATCH 08/16] WIP --- crates/nu-protocol/src/engine/engine_state.rs | 4 ++-- src/main.rs | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index a828530376..c6f2ea11ad 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -204,7 +204,7 @@ impl EngineState { pub fn get_span_contents(&self, span: &Span) -> &[u8] { for (contents, start, finish) in &self.file_contents { - if span.start >= *start && span.start < *finish { + if span.start >= *start && span.start <= *finish { return &contents[(span.start - start)..(span.end - start)]; } } @@ -550,7 +550,7 @@ impl<'a> StateWorkingSet<'a> { let permanent_end = self.permanent_state.next_span_start(); if permanent_end <= span.start { for (contents, start, finish) in &self.delta.file_contents { - if (span.start >= *start) && (span.start < *finish) { + if (span.start >= *start) && (span.start <= *finish) { return &contents[(span.start - permanent_end)..(span.end - permanent_end)]; } } diff --git a/src/main.rs b/src/main.rs index 9a2726c8af..eb724c347b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -195,8 +195,6 @@ fn main() -> Result<()> { continue; } - let mut engine_state = engine_state.clone(); - eval_source( &mut engine_state, &mut stack, @@ -304,7 +302,7 @@ fn eval_source( fname: &str, ) -> bool { let (block, delta) = { - let mut working_set = StateWorkingSet::new(&engine_state); + let mut working_set = StateWorkingSet::new(engine_state); let (output, err) = parse( &mut working_set, Some(fname), // format!("entry #{}", entry_num) @@ -320,17 +318,17 @@ fn eval_source( EngineState::merge_delta(engine_state, delta); - match eval_block(&engine_state, stack, &block, PipelineData::new()) { + match eval_block(engine_state, stack, &block, PipelineData::new()) { Ok(pipeline_data) => { - if let Err(err) = print_value(pipeline_data.into_value(), &engine_state) { - let working_set = StateWorkingSet::new(&engine_state); + if let Err(err) = print_value(pipeline_data.into_value(), engine_state) { + let working_set = StateWorkingSet::new(engine_state); report_error(&working_set, &err); return false; } } Err(err) => { - let working_set = StateWorkingSet::new(&engine_state); + let working_set = StateWorkingSet::new(engine_state); report_error(&working_set, &err); return false; From 5d190176038efe412351340afcd6a03d938b7c17 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 05:58:58 +1300 Subject: [PATCH 09/16] WIP --- crates/nu-cli/src/completions.rs | 6 ++--- crates/nu-cli/src/validation.rs | 2 -- .../nu-command/src/conversions/into/binary.rs | 6 ++--- .../src/conversions/into/command.rs | 2 +- .../src/conversions/into/filesize.rs | 2 +- crates/nu-command/src/conversions/into/int.rs | 2 +- crates/nu-command/src/core_commands/alias.rs | 6 ++--- crates/nu-command/src/core_commands/def.rs | 6 ++--- crates/nu-command/src/core_commands/do_.rs | 4 ++-- .../src/core_commands/export_def.rs | 6 ++--- crates/nu-command/src/core_commands/for_.rs | 4 ++-- crates/nu-command/src/core_commands/help.rs | 2 +- crates/nu-command/src/core_commands/hide.rs | 6 ++--- crates/nu-command/src/core_commands/if_.rs | 12 +++++----- crates/nu-command/src/core_commands/let_.rs | 6 ++--- crates/nu-command/src/core_commands/module.rs | 6 ++--- crates/nu-command/src/core_commands/source.rs | 4 ++-- crates/nu-command/src/core_commands/use_.rs | 6 ++--- crates/nu-command/src/env/let_env.rs | 4 ++-- crates/nu-command/src/example_test.rs | 6 ++--- crates/nu-command/src/experimental/git.rs | 2 +- .../src/experimental/git_checkout.rs | 2 +- .../src/experimental/list_git_branches.rs | 3 ++- crates/nu-command/src/filesystem/cd.rs | 4 ++-- crates/nu-command/src/filesystem/cp.rs | 4 ++-- crates/nu-command/src/filesystem/ls.rs | 2 +- crates/nu-command/src/filesystem/mkdir.rs | 6 ++--- crates/nu-command/src/filesystem/mv.rs | 4 ++-- crates/nu-command/src/filesystem/rm.rs | 6 ++--- crates/nu-command/src/filesystem/touch.rs | 4 ++-- crates/nu-command/src/filters/each.rs | 4 ++-- crates/nu-command/src/filters/get.rs | 4 ++-- crates/nu-command/src/filters/length.rs | 2 +- crates/nu-command/src/filters/lines.rs | 8 ++----- crates/nu-command/src/filters/select.rs | 2 +- crates/nu-command/src/filters/where_.rs | 4 ++-- crates/nu-command/src/filters/wrap.rs | 2 +- crates/nu-command/src/formats/from/command.rs | 4 ++-- crates/nu-command/src/formats/from/json.rs | 2 +- crates/nu-command/src/strings/build_string.rs | 2 +- crates/nu-command/src/strings/size.rs | 2 +- crates/nu-command/src/strings/split/chars.rs | 2 +- crates/nu-command/src/strings/split/column.rs | 2 +- .../nu-command/src/strings/split/command.rs | 2 +- crates/nu-command/src/strings/split/row.rs | 2 +- crates/nu-command/src/system/benchmark.rs | 7 +++--- crates/nu-command/src/system/ps.rs | 2 +- crates/nu-command/src/system/run_external.rs | 12 +++------- crates/nu-command/src/system/sys.rs | 2 +- crates/nu-command/src/viewers/griddle.rs | 2 +- crates/nu-command/src/viewers/table.rs | 2 +- crates/nu-engine/src/call_ext.rs | 2 +- crates/nu-engine/src/documentation.rs | 5 +---- crates/nu-engine/src/eval.rs | 6 ++--- crates/nu-protocol/src/engine/command.rs | 4 ++-- crates/nu-protocol/src/engine/engine_state.rs | 22 ++++++++++++++----- .../src/engine/evaluation_context.rs | 2 +- crates/nu-protocol/src/signature.rs | 3 --- src/main.rs | 15 ++++++------- 59 files changed, 125 insertions(+), 140 deletions(-) diff --git a/crates/nu-cli/src/completions.rs b/crates/nu-cli/src/completions.rs index 837d633f6e..7e3e4f08d1 100644 --- a/crates/nu-cli/src/completions.rs +++ b/crates/nu-cli/src/completions.rs @@ -1,10 +1,8 @@ -use std::{cell::RefCell, rc::Rc}; - use nu_engine::eval_block; use nu_parser::{flatten_block, parse}; use nu_protocol::{ - engine::{EngineState, EvaluationContext, Stack, StateWorkingSet}, - PipelineData, Value, + engine::{EngineState, Stack, StateWorkingSet}, + PipelineData, }; use reedline::Completer; diff --git a/crates/nu-cli/src/validation.rs b/crates/nu-cli/src/validation.rs index 058bc303c5..9e306596c4 100644 --- a/crates/nu-cli/src/validation.rs +++ b/crates/nu-cli/src/validation.rs @@ -1,5 +1,3 @@ -use std::{cell::RefCell, rc::Rc}; - use nu_parser::{parse, ParseError}; use nu_protocol::engine::{EngineState, StateWorkingSet}; use reedline::{ValidationResult, Validator}; diff --git a/crates/nu-command/src/conversions/into/binary.rs b/crates/nu-command/src/conversions/into/binary.rs index e6c697e56f..c1f39e26ef 100644 --- a/crates/nu-command/src/conversions/into/binary.rs +++ b/crates/nu-command/src/conversions/into/binary.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; @@ -26,8 +26,8 @@ impl Command for SubCommand { fn run( &self, - engine_state: &EngineState, - stack: &mut Stack, + _engine_state: &EngineState, + _stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { diff --git a/crates/nu-command/src/conversions/into/command.rs b/crates/nu-command/src/conversions/into/command.rs index a745834dc7..6054010580 100644 --- a/crates/nu-command/src/conversions/into/command.rs +++ b/crates/nu-command/src/conversions/into/command.rs @@ -1,7 +1,7 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, IntoPipelineData, PipelineData, Signature, Value, }; diff --git a/crates/nu-command/src/conversions/into/filesize.rs b/crates/nu-command/src/conversions/into/filesize.rs index a5aa0d6c19..1fa67ef940 100644 --- a/crates/nu-command/src/conversions/into/filesize.rs +++ b/crates/nu-command/src/conversions/into/filesize.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; diff --git a/crates/nu-command/src/conversions/into/int.rs b/crates/nu-command/src/conversions/into/int.rs index a4f31f2d70..c8f018fc5f 100644 --- a/crates/nu-command/src/conversions/into/int.rs +++ b/crates/nu-command/src/conversions/into/int.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; diff --git a/crates/nu-command/src/core_commands/alias.rs b/crates/nu-command/src/core_commands/alias.rs index 3ed9b97d84..e9c585c23c 100644 --- a/crates/nu-command/src/core_commands/alias.rs +++ b/crates/nu-command/src/core_commands/alias.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Alias; @@ -28,7 +28,7 @@ impl Command for Alias { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/def.rs b/crates/nu-command/src/core_commands/def.rs index 3eb3a6307e..f83e1f3cad 100644 --- a/crates/nu-command/src/core_commands/def.rs +++ b/crates/nu-command/src/core_commands/def.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Def; @@ -29,7 +29,7 @@ impl Command for Def { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/do_.rs b/crates/nu-command/src/core_commands/do_.rs index 2b38dd4277..2ddf48ed21 100644 --- a/crates/nu-command/src/core_commands/do_.rs +++ b/crates/nu-command/src/core_commands/do_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -80,6 +80,6 @@ impl Command for Do { ) } } - eval_block(&engine_state, &mut stack, block, input) + eval_block(engine_state, &mut stack, block, input) } } diff --git a/crates/nu-command/src/core_commands/export_def.rs b/crates/nu-command/src/core_commands/export_def.rs index 910716c9f3..d56add47c8 100644 --- a/crates/nu-command/src/core_commands/export_def.rs +++ b/crates/nu-command/src/core_commands/export_def.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct ExportDef; @@ -29,7 +29,7 @@ impl Command for ExportDef { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index 1539690e2d..4714d31cd9 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; #[derive(Clone)] @@ -56,7 +56,7 @@ impl Command for For { .expect("internal error: expected block"); let engine_state = engine_state.clone(); - let mut stack = stack.enter_scope(); + let stack = stack.enter_scope(); match values { Value::List { vals, span } => Ok(vals diff --git a/crates/nu-command/src/core_commands/help.rs b/crates/nu-command/src/core_commands/help.rs index 990acb4c71..06f0e208f8 100644 --- a/crates/nu-command/src/core_commands/help.rs +++ b/crates/nu-command/src/core_commands/help.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, span, Example, IntoPipelineData, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value, }; diff --git a/crates/nu-command/src/core_commands/hide.rs b/crates/nu-command/src/core_commands/hide.rs index 57f2a10928..843299abaa 100644 --- a/crates/nu-command/src/core_commands/hide.rs +++ b/crates/nu-command/src/core_commands/hide.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Hide; @@ -22,7 +22,7 @@ impl Command for Hide { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/if_.rs b/crates/nu-command/src/core_commands/if_.rs index 0ea5c8785d..431145d15b 100644 --- a/crates/nu-command/src/core_commands/if_.rs +++ b/crates/nu-command/src/core_commands/if_.rs @@ -1,6 +1,6 @@ use nu_engine::{eval_block, eval_expression}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -41,23 +41,23 @@ impl Command for If { let result = eval_expression(engine_state, stack, cond)?; match result { - Value::Bool { val, span } => { + Value::Bool { val, .. } => { if val { let block = engine_state.get_block(then_block); let mut stack = stack.enter_scope(); - eval_block(&engine_state, &mut stack, block, input) + eval_block(engine_state, &mut stack, block, input) } else if let Some(else_case) = else_case { if let Some(else_expr) = else_case.as_keyword() { if let Some(block_id) = else_expr.as_block() { let block = engine_state.get_block(block_id); let mut stack = stack.enter_scope(); - eval_block(&engine_state, &mut stack, block, input) + eval_block(engine_state, &mut stack, block, input) } else { - eval_expression(&engine_state, stack, else_expr) + eval_expression(engine_state, stack, else_expr) .map(|x| x.into_pipeline_data()) } } else { - eval_expression(&engine_state, stack, else_case) + eval_expression(engine_state, stack, else_case) .map(|x| x.into_pipeline_data()) } } else { diff --git a/crates/nu-command/src/core_commands/let_.rs b/crates/nu-command/src/core_commands/let_.rs index 3e3a942cd3..7ccde47e78 100644 --- a/crates/nu-command/src/core_commands/let_.rs +++ b/crates/nu-command/src/core_commands/let_.rs @@ -1,7 +1,7 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Let; @@ -40,7 +40,7 @@ impl Command for Let { .as_keyword() .expect("internal error: missing keyword"); - let rhs = eval_expression(&engine_state, stack, keyword_expr)?; + let rhs = eval_expression(engine_state, stack, keyword_expr)?; //println!("Adding: {:?} to {}", rhs, var_id); diff --git a/crates/nu-command/src/core_commands/module.rs b/crates/nu-command/src/core_commands/module.rs index 2476e6ab95..4fe16f615b 100644 --- a/crates/nu-command/src/core_commands/module.rs +++ b/crates/nu-command/src/core_commands/module.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Module; @@ -28,7 +28,7 @@ impl Command for Module { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index 6b9cc78852..d60f330d34 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,7 +1,7 @@ use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape}; /// Source a file for environment variables. #[derive(Clone)] diff --git a/crates/nu-command/src/core_commands/use_.rs b/crates/nu-command/src/core_commands/use_.rs index dfcc0124ec..27635687d5 100644 --- a/crates/nu-command/src/core_commands/use_.rs +++ b/crates/nu-command/src/core_commands/use_.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Use; @@ -22,7 +22,7 @@ impl Command for Use { &self, _engine_state: &EngineState, _stack: &mut Stack, - call: &Call, + _call: &Call, _input: PipelineData, ) -> Result { Ok(PipelineData::new()) diff --git a/crates/nu-command/src/env/let_env.rs b/crates/nu-command/src/env/let_env.rs index 21801939cf..16e742f85b 100644 --- a/crates/nu-command/src/env/let_env.rs +++ b/crates/nu-command/src/env/let_env.rs @@ -1,7 +1,7 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct LetEnv; diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index 8bda299baf..c7ca4f0011 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -1,10 +1,8 @@ -use std::{cell::RefCell, rc::Rc}; - use nu_engine::eval_block; use nu_parser::parse; use nu_protocol::{ - engine::{Command, EngineState, EvaluationContext, Stack, StateWorkingSet}, - PipelineData, Value, + engine::{Command, EngineState, Stack, StateWorkingSet}, + PipelineData, }; use super::{From, Into, Split}; diff --git a/crates/nu-command/src/experimental/git.rs b/crates/nu-command/src/experimental/git.rs index f4c9cf1f13..bb1463bcb2 100644 --- a/crates/nu-command/src/experimental/git.rs +++ b/crates/nu-command/src/experimental/git.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/experimental/git_checkout.rs b/crates/nu-command/src/experimental/git_checkout.rs index 0c8be2564f..66b68c533d 100644 --- a/crates/nu-command/src/experimental/git_checkout.rs +++ b/crates/nu-command/src/experimental/git_checkout.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/experimental/list_git_branches.rs b/crates/nu-command/src/experimental/list_git_branches.rs index a11c85efbf..19c171bcec 100644 --- a/crates/nu-command/src/experimental/list_git_branches.rs +++ b/crates/nu-command/src/experimental/list_git_branches.rs @@ -4,9 +4,9 @@ use std::process::Command as ProcessCommand; use std::process::Stdio; use nu_protocol::ast::Call; +use nu_protocol::engine::Command; use nu_protocol::engine::EngineState; use nu_protocol::engine::Stack; -use nu_protocol::engine::{Command, EvaluationContext}; use nu_protocol::IntoPipelineData; use nu_protocol::PipelineData; use nu_protocol::{Signature, Value}; @@ -46,6 +46,7 @@ impl Command for ListGitBranches { let s = String::from_utf8_lossy(&val).to_string(); + #[allow(clippy::needless_collect)] let lines: Vec<_> = s .lines() .filter_map(|x| { diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 5bb1dd928b..2986413bed 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Cd; diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 0283f8d1a6..4de1af2a1d 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -5,8 +5,8 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_path::canonicalize_with; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape}; use crate::filesystem::util::FileStructure; diff --git a/crates/nu-command/src/filesystem/ls.rs b/crates/nu-command/src/filesystem/ls.rs index 6458af7b96..a21acafb0f 100644 --- a/crates/nu-command/src/filesystem/ls.rs +++ b/crates/nu-command/src/filesystem/ls.rs @@ -1,7 +1,7 @@ use chrono::{DateTime, Utc}; use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/filesystem/mkdir.rs b/crates/nu-command/src/filesystem/mkdir.rs index adb91f5d8a..c4ecc874ba 100644 --- a/crates/nu-command/src/filesystem/mkdir.rs +++ b/crates/nu-command/src/filesystem/mkdir.rs @@ -3,10 +3,8 @@ use std::env::current_dir; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{ - IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, -}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] pub struct Mkdir; diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index 1e6069b8b1..74a759cdd6 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -4,8 +4,8 @@ use std::path::{Path, PathBuf}; use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape}; #[derive(Clone)] pub struct Mv; diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 35d0f252a3..6851410829 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -7,10 +7,8 @@ use super::util::get_interactive_confirmation; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{ - IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, -}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] pub struct Rm; diff --git a/crates/nu-command/src/filesystem/touch.rs b/crates/nu-command/src/filesystem/touch.rs index 85c79d0a24..04188d9ec7 100644 --- a/crates/nu-command/src/filesystem/touch.rs +++ b/crates/nu-command/src/filesystem/touch.rs @@ -2,8 +2,8 @@ use std::fs::OpenOptions; use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape}; #[derive(Clone)] pub struct Touch; diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 789c42c751..b7feafe073 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -1,6 +1,6 @@ use nu_engine::eval_block; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; #[derive(Clone)] @@ -64,7 +64,7 @@ impl Command for Each { let numbered = call.has_flag("numbered"); let engine_state = engine_state.clone(); - let mut stack = stack.clone(); + let stack = stack.clone(); let span = call.head; match input { diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index e7b38df853..ffaf6a98ac 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Get; diff --git a/crates/nu-command/src/filters/length.rs b/crates/nu-command/src/filters/length.rs index 9fa4543dd4..0ab8690cf4 100644 --- a/crates/nu-command/src/filters/length.rs +++ b/crates/nu-command/src/filters/length.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/filters/lines.rs b/crates/nu-command/src/filters/lines.rs index bb1db993af..b1a11b5768 100644 --- a/crates/nu-command/src/filters/lines.rs +++ b/crates/nu-command/src/filters/lines.rs @@ -1,9 +1,6 @@ -use std::cell::RefCell; -use std::rc::Rc; - use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Value, ValueStream}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Value}; #[derive(Clone)] pub struct Lines; @@ -30,7 +27,6 @@ impl Command for Lines { call: &Call, input: PipelineData, ) -> Result { - let span = call.head; match input { #[allow(clippy::needless_collect)] // Collect is needed because the string may not live long enough for diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 5c4c7f4723..1a43094ec8 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::{Call, CellPath}; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index 5397cddd01..16b74efcc3 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::{Call, Expr, Expression}; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value}; #[derive(Clone)] @@ -52,7 +52,7 @@ impl Command for Where { } }) .into_pipeline_data()), - PipelineData::Value(Value::List { vals, span }) => Ok(vals + PipelineData::Value(Value::List { vals, .. }) => Ok(vals .into_iter() .filter(move |value| { stack.add_var(var_id, value.clone()); diff --git a/crates/nu-command/src/filters/wrap.rs b/crates/nu-command/src/filters/wrap.rs index 311f72dbea..d06324725b 100644 --- a/crates/nu-command/src/filters/wrap.rs +++ b/crates/nu-command/src/filters/wrap.rs @@ -1,6 +1,6 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, Signature, SyntaxShape, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/formats/from/command.rs b/crates/nu-command/src/formats/from/command.rs index 36dd21af8e..8aede1def5 100644 --- a/crates/nu-command/src/formats/from/command.rs +++ b/crates/nu-command/src/formats/from/command.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, ShellError, Signature, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, ShellError, Signature}; #[derive(Clone)] pub struct From; diff --git a/crates/nu-command/src/formats/from/json.rs b/crates/nu-command/src/formats/from/json.rs index db5af67197..fab0cf9682 100644 --- a/crates/nu-command/src/formats/from/json.rs +++ b/crates/nu-command/src/formats/from/json.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; #[derive(Clone)] diff --git a/crates/nu-command/src/strings/build_string.rs b/crates/nu-command/src/strings/build_string.rs index 1cea5a1a46..7e87b01ffb 100644 --- a/crates/nu-command/src/strings/build_string.rs +++ b/crates/nu-command/src/strings/build_string.rs @@ -1,6 +1,6 @@ use nu_engine::eval_expression; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; diff --git a/crates/nu-command/src/strings/size.rs b/crates/nu-command/src/strings/size.rs index 0f919f5774..251a6b1c7c 100644 --- a/crates/nu-command/src/strings/size.rs +++ b/crates/nu-command/src/strings/size.rs @@ -3,7 +3,7 @@ extern crate unicode_segmentation; use unicode_segmentation::UnicodeSegmentation; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; diff --git a/crates/nu-command/src/strings/split/chars.rs b/crates/nu-command/src/strings/split/chars.rs index f71f8913a8..f553e41b83 100644 --- a/crates/nu-command/src/strings/split/chars.rs +++ b/crates/nu-command/src/strings/split/chars.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; diff --git a/crates/nu-command/src/strings/split/column.rs b/crates/nu-command/src/strings/split/column.rs index d2b370d9d6..8090c4d237 100644 --- a/crates/nu-command/src/strings/split/column.rs +++ b/crates/nu-command/src/strings/split/column.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; diff --git a/crates/nu-command/src/strings/split/command.rs b/crates/nu-command/src/strings/split/command.rs index e25ea589b7..e6b30b3cce 100644 --- a/crates/nu-command/src/strings/split/command.rs +++ b/crates/nu-command/src/strings/split/command.rs @@ -1,7 +1,7 @@ use nu_engine::get_full_help; use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, IntoPipelineData, PipelineData, Signature, Value, }; diff --git a/crates/nu-command/src/strings/split/row.rs b/crates/nu-command/src/strings/split/row.rs index 5bf8ae02a8..80bd303945 100644 --- a/crates/nu-command/src/strings/split/row.rs +++ b/crates/nu-command/src/strings/split/row.rs @@ -1,7 +1,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; diff --git a/crates/nu-command/src/system/benchmark.rs b/crates/nu-command/src/system/benchmark.rs index 7913c16719..f1b6edbfc7 100644 --- a/crates/nu-command/src/system/benchmark.rs +++ b/crates/nu-command/src/system/benchmark.rs @@ -2,8 +2,8 @@ use std::time::Instant; use nu_engine::eval_block; use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; -use nu_protocol::{PipelineData, Signature, SyntaxShape, Value}; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{PipelineData, Signature, SyntaxShape}; #[derive(Clone)] pub struct Benchmark; @@ -39,7 +39,8 @@ impl Command for Benchmark { let mut stack = stack.enter_scope(); let start_time = Instant::now(); - eval_block(&engine_state, &mut stack, block, PipelineData::new())?; + eval_block(engine_state, &mut stack, block, PipelineData::new())?.into_value(); + let end_time = Instant::now(); println!("{} ms", (end_time - start_time).as_millis()); Ok(PipelineData::new()) diff --git a/crates/nu-command/src/system/ps.rs b/crates/nu-command/src/system/ps.rs index d816a4472f..efff137da4 100644 --- a/crates/nu-command/src/system/ps.rs +++ b/crates/nu-command/src/system/ps.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value, }; use sysinfo::{ProcessExt, System, SystemExt}; diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 84a74dc974..75e551ceee 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -1,21 +1,15 @@ use std::borrow::Cow; -use std::cell::RefCell; use std::collections::HashMap; use std::env; use std::io::{BufRead, BufReader, Write}; use std::process::{ChildStdin, Command as CommandSys, Stdio}; -use std::rc::Rc; use std::sync::mpsc; use nu_protocol::engine::{EngineState, Stack}; -use nu_protocol::{ - ast::{Call, Expression}, - engine::{Command, EvaluationContext}, - ShellError, Signature, SyntaxShape, Value, -}; -use nu_protocol::{IntoPipelineData, PipelineData, Span, Spanned, ValueStream}; +use nu_protocol::{ast::Call, engine::Command, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{IntoPipelineData, PipelineData, Span, Spanned}; -use nu_engine::{eval_expression, CallExt}; +use nu_engine::CallExt; const OUTPUT_BUFFER_SIZE: usize = 8192; diff --git a/crates/nu-command/src/system/sys.rs b/crates/nu-command/src/system/sys.rs index b1aa54daa2..442a4136ca 100644 --- a/crates/nu-command/src/system/sys.rs +++ b/crates/nu-command/src/system/sys.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Value, }; use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt}; diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs index fb752a58a8..07faac1c27 100644 --- a/crates/nu-command/src/viewers/griddle.rs +++ b/crates/nu-command/src/viewers/griddle.rs @@ -2,7 +2,7 @@ use lscolors::{LsColors, Style}; use nu_engine::CallExt; use nu_protocol::{ ast::{Call, PathMember}, - engine::{Command, EngineState, EvaluationContext, Stack}, + engine::{Command, EngineState, Stack}, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value, }; use nu_term_grid::grid::{Alignment, Cell, Direction, Filling, Grid, GridOptions}; diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 2fca815b68..bd1a432c5f 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::{Call, PathMember}; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Span, Value}; use nu_table::StyledString; use std::collections::HashMap; diff --git a/crates/nu-engine/src/call_ext.rs b/crates/nu-engine/src/call_ext.rs index 1ea0ef163e..256320b565 100644 --- a/crates/nu-engine/src/call_ext.rs +++ b/crates/nu-engine/src/call_ext.rs @@ -1,6 +1,6 @@ use nu_protocol::{ ast::Call, - engine::{EngineState, EvaluationContext, Stack}, + engine::{EngineState, Stack}, ShellError, }; diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index ce9c3b52b9..ea0bb17e6e 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -1,8 +1,5 @@ use itertools::Itertools; -use nu_protocol::{ - engine::{EngineState, EvaluationContext}, - Example, Signature, Span, Value, -}; +use nu_protocol::{engine::EngineState, Example, Signature, Span, Value}; use std::collections::HashMap; const COMMANDS_DOCS_DIR: &str = "docs/commands"; diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 91901b3de2..b75419e768 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,5 +1,5 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; -use nu_protocol::engine::{EngineState, EvaluationContext, Stack}; +use nu_protocol::engine::{EngineState, Stack}; use nu_protocol::{ IntoPipelineData, PipelineData, Range, ShellError, Span, Spanned, Type, Unit, Value, }; @@ -55,7 +55,7 @@ fn eval_call( decl.signature().required_positional.len() + decl.signature().optional_positional.len(), ) { - let result = eval_expression(&engine_state, &mut stack, arg)?; + let result = eval_expression(engine_state, &mut stack, arg)?; rest_items.push(result); } @@ -82,7 +82,7 @@ fn eval_call( for call_named in &call.named { if call_named.0.item == named.long { if let Some(arg) = &call_named.1 { - let result = eval_expression(&engine_state, &mut stack, arg)?; + let result = eval_expression(engine_state, &mut stack, arg)?; stack.add_var(var_id, result); } else { diff --git a/crates/nu-protocol/src/engine/command.rs b/crates/nu-protocol/src/engine/command.rs index 6a6955c182..295898207e 100644 --- a/crates/nu-protocol/src/engine/command.rs +++ b/crates/nu-protocol/src/engine/command.rs @@ -1,6 +1,6 @@ -use crate::{ast::Call, value::Value, BlockId, Example, PipelineData, ShellError, Signature}; +use crate::{ast::Call, BlockId, Example, PipelineData, ShellError, Signature}; -use super::{EngineState, EvaluationContext, Stack}; +use super::{EngineState, Stack}; pub trait Command: Send + Sync + CommandClone { fn name(&self) -> &str; diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index c6f2ea11ad..de240af11c 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -1,7 +1,7 @@ use super::Command; use crate::{ast::Block, BlockId, DeclId, Example, Signature, Span, Type, VarId}; use core::panic; -use std::{collections::HashMap, slice::Iter}; +use std::collections::HashMap; #[derive(Clone)] pub struct EngineState { @@ -167,7 +167,7 @@ impl EngineState { pub fn print_contents(&self) { for (contents, _, _) in self.file_contents.iter() { - let string = String::from_utf8_lossy(&contents); + let string = String::from_utf8_lossy(contents); println!("{}", string); } } @@ -204,7 +204,7 @@ impl EngineState { pub fn get_span_contents(&self, span: &Span) -> &[u8] { for (contents, start, finish) in &self.file_contents { - if span.start >= *start && span.start <= *finish { + if span.start >= *start && span.end <= *finish { return &contents[(span.start - start)..(span.end - start)]; } } @@ -262,7 +262,11 @@ impl EngineState { } pub fn next_span_start(&self) -> usize { - self.file_contents.len() + if let Some((_, _, last)) = self.file_contents.last() { + *last + } else { + 0 + } } pub fn files(&self) -> impl Iterator { @@ -494,7 +498,13 @@ impl<'a> StateWorkingSet<'a> { } pub fn next_span_start(&self) -> usize { - self.permanent_state.next_span_start() + self.delta.file_contents.len() + let permanent_span_start = self.permanent_state.next_span_start(); + + if let Some((_, _, last)) = self.delta.file_contents.last() { + permanent_span_start + *last + } else { + permanent_span_start + } } pub fn global_span_offset(&self) -> usize { @@ -550,7 +560,7 @@ impl<'a> StateWorkingSet<'a> { let permanent_end = self.permanent_state.next_span_start(); if permanent_end <= span.start { for (contents, start, finish) in &self.delta.file_contents { - if (span.start >= *start) && (span.start <= *finish) { + if (span.start >= *start) && (span.end <= *finish) { return &contents[(span.start - permanent_end)..(span.end - permanent_end)]; } } diff --git a/crates/nu-protocol/src/engine/evaluation_context.rs b/crates/nu-protocol/src/engine/evaluation_context.rs index 5fd4d17bcc..a67318bd51 100644 --- a/crates/nu-protocol/src/engine/evaluation_context.rs +++ b/crates/nu-protocol/src/engine/evaluation_context.rs @@ -1,5 +1,5 @@ use super::EngineState; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::collections::HashMap; use crate::{Example, ShellError, Signature, Value, VarId}; diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index b7037a4bc6..caeda66362 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -1,13 +1,10 @@ use crate::ast::Call; use crate::engine::Command; -use crate::engine::CommandClone; use crate::engine::EngineState; -use crate::engine::EvaluationContext; use crate::engine::Stack; use crate::BlockId; use crate::PipelineData; use crate::SyntaxShape; -use crate::Value; use crate::VarId; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/main.rs b/src/main.rs index eb724c347b..02ded94a1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, io::Write, rc::Rc}; +use std::io::Write; use dialoguer::{ console::{Style, Term}, @@ -12,7 +12,7 @@ use nu_engine::eval_block; use nu_parser::parse; use nu_protocol::{ ast::Call, - engine::{EngineState, EvaluationContext, Stack, StateWorkingSet}, + engine::{EngineState, Stack, StateWorkingSet}, IntoPipelineData, PipelineData, ShellError, Value, }; use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt}; @@ -268,23 +268,22 @@ fn update_prompt<'prompt>( return nu_prompt as &dyn Prompt; } - let (block, delta) = { - let mut working_set = StateWorkingSet::new(&engine_state); + let block = { + let mut working_set = StateWorkingSet::new(engine_state); let (output, err) = parse(&mut working_set, None, prompt_command.as_bytes(), false); if let Some(err) = err { report_error(&working_set, &err); return default_prompt as &dyn Prompt; } - (output, working_set.render()) + output }; let mut stack = stack.clone(); - let evaluated_prompt = match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) - { + let evaluated_prompt = match eval_block(engine_state, &mut stack, &block, PipelineData::new()) { Ok(pipeline_data) => pipeline_data.collect_string(), Err(err) => { - let working_set = StateWorkingSet::new(&engine_state); + let working_set = StateWorkingSet::new(engine_state); report_error(&working_set, &err); return default_prompt as &dyn Prompt; } From f84582ca2b453a516da8fc7c3e68655f91453156 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 06:46:26 +1300 Subject: [PATCH 10/16] WIP --- crates/nu-protocol/src/engine/mod.rs | 4 +- .../{evaluation_context.rs => stack.rs} | 42 +------------------ 2 files changed, 3 insertions(+), 43 deletions(-) rename crates/nu-protocol/src/engine/{evaluation_context.rs => stack.rs} (69%) diff --git a/crates/nu-protocol/src/engine/mod.rs b/crates/nu-protocol/src/engine/mod.rs index e6b7eb5d3d..81228717b8 100644 --- a/crates/nu-protocol/src/engine/mod.rs +++ b/crates/nu-protocol/src/engine/mod.rs @@ -1,9 +1,9 @@ mod call_info; mod command; mod engine_state; -mod evaluation_context; +mod stack; pub use call_info::*; pub use command::*; pub use engine_state::*; -pub use evaluation_context::*; +pub use stack::*; diff --git a/crates/nu-protocol/src/engine/evaluation_context.rs b/crates/nu-protocol/src/engine/stack.rs similarity index 69% rename from crates/nu-protocol/src/engine/evaluation_context.rs rename to crates/nu-protocol/src/engine/stack.rs index a67318bd51..b08000a578 100644 --- a/crates/nu-protocol/src/engine/evaluation_context.rs +++ b/crates/nu-protocol/src/engine/stack.rs @@ -1,46 +1,6 @@ -use super::EngineState; use std::collections::HashMap; -use crate::{Example, ShellError, Signature, Value, VarId}; - -#[derive(Clone)] -pub struct EvaluationContext { - pub engine_state: Box, - pub stack: Stack, -} - -impl EvaluationContext { - pub fn get_var(&self, var_id: VarId) -> Result { - self.stack.get_var(var_id) - } - - pub fn enter_scope(&self) -> EvaluationContext { - Self { - engine_state: self.engine_state.clone(), - stack: self.stack.clone().enter_scope(), - } - } - - pub fn add_var(&mut self, var_id: VarId, value: Value) { - self.stack.add_var(var_id, value); - } - - pub fn add_env_var(&mut self, var: String, value: String) { - self.stack.add_env_var(var, value); - } - - pub fn print_stack(&self) { - self.stack.print_stack(); - } - - pub fn get_signatures(&self) -> Vec { - self.engine_state.get_signatures() - } - - pub fn get_signatures_with_examples(&self) -> Vec<(Signature, Vec)> { - self.engine_state.get_signatures_with_examples() - } -} +use crate::{ShellError, Value, VarId}; #[derive(Debug, Clone)] pub struct StackFrame { From d29208dd9e9393b07a3d7b954f1fe7a5b26cda5a Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 09:04:23 +1300 Subject: [PATCH 11/16] WIP --- crates/nu-command/src/core_commands/do_.rs | 2 +- crates/nu-command/src/core_commands/for_.rs | 17 +- crates/nu-command/src/core_commands/if_.rs | 4 +- crates/nu-command/src/filters/each.rs | 15 +- crates/nu-command/src/filters/where_.rs | 4 +- crates/nu-command/src/system/benchmark.rs | 2 +- crates/nu-engine/src/eval.rs | 8 +- crates/nu-parser/src/flatten.rs | 2 +- crates/nu-parser/src/lib.rs | 2 +- crates/nu-parser/src/parser.rs | 182 +++++++++++++++++++- crates/nu-protocol/src/ast/block.rs | 6 +- crates/nu-protocol/src/ast/expr.rs | 1 + crates/nu-protocol/src/ast/expression.rs | 1 + crates/nu-protocol/src/engine/stack.rs | 100 +++++------ 14 files changed, 265 insertions(+), 81 deletions(-) diff --git a/crates/nu-command/src/core_commands/do_.rs b/crates/nu-command/src/core_commands/do_.rs index 2ddf48ed21..482a25f841 100644 --- a/crates/nu-command/src/core_commands/do_.rs +++ b/crates/nu-command/src/core_commands/do_.rs @@ -40,7 +40,7 @@ impl Command for Do { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.collect_captures(&block.captures); let params: Vec<_> = block .signature diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index 4714d31cd9..d85a42617a 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -51,22 +51,22 @@ impl Command for For { .expect("internal error: missing keyword"); let values = eval_expression(engine_state, stack, keyword_expr)?; - let block = call.positional[2] + let block_id = call.positional[2] .as_block() .expect("internal error: expected block"); let engine_state = engine_state.clone(); - let stack = stack.enter_scope(); + let block = engine_state.get_block(block_id); + let mut stack = stack.collect_captures(&block.captures); match values { Value::List { vals, span } => Ok(vals .into_iter() .map(move |x| { - let block = engine_state.get_block(block); - let mut stack = stack.clone(); stack.add_var(var_id, x); + let block = engine_state.get_block(block_id); match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(value) => Value::List { vals: value.collect(), @@ -79,12 +79,9 @@ impl Command for For { Value::Range { val, span } => Ok(val .into_range_iter()? .map(move |x| { - let block = engine_state.get_block(block); - - let mut stack = stack.enter_scope(); - stack.add_var(var_id, x); + let block = engine_state.get_block(block_id); match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { Ok(value) => Value::List { vals: value.collect(), @@ -95,10 +92,6 @@ impl Command for For { }) .into_pipeline_data()), x => { - let block = engine_state.get_block(block); - - let mut stack = stack.enter_scope(); - stack.add_var(var_id, x); eval_block(&engine_state, &mut stack, block, PipelineData::new()) diff --git a/crates/nu-command/src/core_commands/if_.rs b/crates/nu-command/src/core_commands/if_.rs index 431145d15b..f5bc36516c 100644 --- a/crates/nu-command/src/core_commands/if_.rs +++ b/crates/nu-command/src/core_commands/if_.rs @@ -44,13 +44,13 @@ impl Command for If { Value::Bool { val, .. } => { if val { let block = engine_state.get_block(then_block); - let mut stack = stack.enter_scope(); + let mut stack = stack.collect_captures(&block.captures); eval_block(engine_state, &mut stack, block, input) } else if let Some(else_case) = else_case { if let Some(else_expr) = else_case.as_keyword() { if let Some(block_id) = else_expr.as_block() { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.collect_captures(&block.captures); eval_block(engine_state, &mut stack, block, input) } else { eval_expression(engine_state, stack, else_expr) diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index b7feafe073..6cbaf8c0e9 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -64,7 +64,8 @@ impl Command for Each { let numbered = call.has_flag("numbered"); let engine_state = engine_state.clone(); - let stack = stack.clone(); + let block = engine_state.get_block(block_id); + let mut stack = stack.collect_captures(&block.captures); let span = call.head; match input { @@ -74,7 +75,7 @@ impl Command for Each { .map(move |(idx, x)| { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.clone(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { @@ -112,7 +113,8 @@ impl Command for Each { .map(move |(idx, x)| { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.clone(); + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { if numbered { @@ -148,7 +150,8 @@ impl Command for Each { .map(move |(idx, x)| { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.clone(); + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { if numbered { @@ -186,7 +189,8 @@ impl Command for Each { for (col, val) in cols.into_iter().zip(vals.into_iter()) { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.clone(); + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { stack.add_var( @@ -231,7 +235,6 @@ impl Command for Each { PipelineData::Value(x) => { let block = engine_state.get_block(block_id); - let mut stack = stack.enter_scope(); if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { stack.add_var(*var_id, x); diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index 16b74efcc3..d479835ef8 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -29,7 +29,9 @@ impl Command for Where { let cond = call.positional[0].clone(); let engine_state = engine_state.clone(); - let mut stack = stack.enter_scope(); + + // FIXME: very expensive + let mut stack = stack.clone(); let (var_id, cond) = match cond { Expression { diff --git a/crates/nu-command/src/system/benchmark.rs b/crates/nu-command/src/system/benchmark.rs index f1b6edbfc7..7b99c2009a 100644 --- a/crates/nu-command/src/system/benchmark.rs +++ b/crates/nu-command/src/system/benchmark.rs @@ -37,7 +37,7 @@ impl Command for Benchmark { .expect("internal error: expected block"); let block = engine_state.get_block(block); - let mut stack = stack.enter_scope(); + let mut stack = stack.collect_captures(&block.captures); let start_time = Instant::now(); eval_block(engine_state, &mut stack, block, PipelineData::new())?.into_value(); diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index b75419e768..fce4519b01 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -33,7 +33,9 @@ fn eval_call( } .into_pipeline_data()) } else if let Some(block_id) = decl.get_block_id() { - let mut stack = stack.enter_scope(); + let block = engine_state.get_block(block_id); + + let mut stack = stack.collect_captures(&block.captures); for (arg, param) in call.positional.iter().zip( decl.signature() .required_positional @@ -109,7 +111,6 @@ fn eval_call( } } } - let block = engine_state.get_block(block_id); eval_block(engine_state, &mut stack, block, input) } else { decl.run(engine_state, stack, call, input) @@ -212,6 +213,7 @@ pub fn eval_expression( Expr::Var(var_id) => stack .get_var(*var_id) .map_err(move |_| ShellError::VariableNotFoundAtRuntime(expr.span)), + Expr::VarDecl(_) => Ok(Value::Nothing { span: expr.span }), Expr::CellPath(cell_path) => Ok(Value::CellPath { val: cell_path.clone(), span: expr.span, @@ -276,7 +278,7 @@ pub fn eval_expression( Expr::Subexpression(block_id) => { let block = engine_state.get_block(*block_id); - let mut stack = stack.enter_scope(); + let mut stack = stack.collect_captures(&block.captures); // FIXME: protect this collect with ctrl-c Ok(Value::List { diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs index 8ce976b9c7..c244f4242a 100644 --- a/crates/nu-parser/src/flatten.rs +++ b/crates/nu-parser/src/flatten.rs @@ -194,7 +194,7 @@ pub fn flatten_expression( } output } - Expr::Var(_) => { + Expr::Var(_) | Expr::VarDecl(_) => { vec![(expr.span, FlatShape::Variable)] } } diff --git a/crates/nu-parser/src/lib.rs b/crates/nu-parser/src/lib.rs index 0fd2f3ec8c..8fc5e559c8 100644 --- a/crates/nu-parser/src/lib.rs +++ b/crates/nu-parser/src/lib.rs @@ -13,4 +13,4 @@ pub use lite_parse::{lite_parse, LiteBlock}; pub use parse_keywords::{ parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use, }; -pub use parser::{parse, Import, VarDecl}; +pub use parser::{find_captures_in_expr, parse, Import, VarDecl}; diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 8a5a2c1401..893c5f492e 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1806,7 +1806,7 @@ pub fn parse_var_with_opt_type( ( Expression { - expr: Expr::Var(id), + expr: Expr::VarDecl(id), span: span(&spans[*spans_idx - 1..*spans_idx + 1]), ty, custom_completion: None, @@ -1817,7 +1817,7 @@ pub fn parse_var_with_opt_type( let id = working_set.add_variable(bytes[0..(bytes.len() - 1)].to_vec(), Type::Unknown); ( Expression { - expr: Expr::Var(id), + expr: Expr::VarDecl(id), span: spans[*spans_idx], ty: Type::Unknown, custom_completion: None, @@ -1830,7 +1830,7 @@ pub fn parse_var_with_opt_type( ( Expression { - expr: Expr::Var(id), + expr: Expr::VarDecl(id), span: span(&spans[*spans_idx..*spans_idx + 1]), ty: Type::Unknown, custom_completion: None, @@ -2574,6 +2574,11 @@ pub fn parse_block_expression( } } + let mut seen = vec![]; + let captures = find_captures_in_block(working_set, &output, &mut seen); + + output.captures = captures; + working_set.exit_scope(); let block_id = working_set.add_block(output); @@ -3041,6 +3046,177 @@ pub fn parse_block( (block, error) } +fn find_captures_in_block( + working_set: &StateWorkingSet, + block: &Block, + seen: &mut Vec, +) -> Vec { + let mut output = vec![]; + + for flag in &block.signature.named { + if let Some(var_id) = flag.var_id { + seen.push(var_id); + } + } + + for positional in &block.signature.required_positional { + if let Some(var_id) = positional.var_id { + seen.push(var_id); + } + } + for positional in &block.signature.optional_positional { + if let Some(var_id) = positional.var_id { + seen.push(var_id); + } + } + for positional in &block.signature.rest_positional { + if let Some(var_id) = positional.var_id { + seen.push(var_id); + } + } + + for stmt in &block.stmts { + match stmt { + Statement::Pipeline(pipeline) => { + let result = find_captures_in_pipeline(working_set, pipeline, seen); + output.extend(&result); + } + Statement::Declaration(_) => {} + } + } + + output +} + +fn find_captures_in_pipeline( + working_set: &StateWorkingSet, + pipeline: &Pipeline, + seen: &mut Vec, +) -> Vec { + let mut output = vec![]; + for expr in &pipeline.expressions { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + + output +} + +pub fn find_captures_in_expr( + working_set: &StateWorkingSet, + expr: &Expression, + seen: &mut Vec, +) -> Vec { + let mut output = vec![]; + match &expr.expr { + Expr::BinaryOp(lhs, _, rhs) => { + let lhs_result = find_captures_in_expr(working_set, lhs, seen); + let rhs_result = find_captures_in_expr(working_set, rhs, seen); + + output.extend(&lhs_result); + output.extend(&rhs_result); + } + Expr::Block(block_id) => { + let block = working_set.get_block(*block_id); + let result = find_captures_in_block(working_set, block, seen); + output.extend(&result); + } + Expr::Bool(_) => {} + Expr::Call(call) => { + for named in &call.named { + if let Some(arg) = &named.1 { + let result = find_captures_in_expr(working_set, arg, seen); + output.extend(&result); + } + } + + for positional in &call.positional { + let result = find_captures_in_expr(working_set, positional, seen); + output.extend(&result); + } + } + Expr::CellPath(_) => {} + Expr::ExternalCall(_, _, exprs) => { + for expr in exprs { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + } + Expr::Filepath(_) => {} + Expr::Float(_) => {} + Expr::FullCellPath(cell_path) => { + let result = find_captures_in_expr(working_set, &cell_path.head, seen); + output.extend(&result); + } + Expr::Garbage => {} + Expr::GlobPattern(_) => {} + Expr::Int(_) => {} + Expr::Keyword(_, _, expr) => { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + Expr::List(exprs) => { + for expr in exprs { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + } + Expr::Operator(_) => {} + Expr::Range(expr1, expr2, expr3, _) => { + if let Some(expr) = expr1 { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + if let Some(expr) = expr2 { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + if let Some(expr) = expr3 { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + } + Expr::RowCondition(var_id, expr) => { + seen.push(*var_id); + + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + Expr::Signature(_) => {} + Expr::String(_) => {} + Expr::Subexpression(block_id) => { + let block = working_set.get_block(*block_id); + let result = find_captures_in_block(working_set, block, seen); + output.extend(&result); + } + Expr::Table(headers, values) => { + for header in headers { + let result = find_captures_in_expr(working_set, header, seen); + output.extend(&result); + } + for row in values { + for cell in row { + let result = find_captures_in_expr(working_set, cell, seen); + output.extend(&result); + } + } + } + Expr::ValueWithUnit(expr, _) => { + let result = find_captures_in_expr(working_set, expr, seen); + output.extend(&result); + } + Expr::Var(var_id) => { + if !seen.contains(var_id) { + output.push(*var_id); + } + } + Expr::VarDecl(var_id) => { + seen.push(*var_id); + } + } + output +} + // Parses a vector of u8 to create an AST Block. If a file name is given, then // the name is stored in the working set. When parsing a source without a file // name, the source of bytes is stored as "source" diff --git a/crates/nu-protocol/src/ast/block.rs b/crates/nu-protocol/src/ast/block.rs index 70273816b5..8ae5aa99ae 100644 --- a/crates/nu-protocol/src/ast/block.rs +++ b/crates/nu-protocol/src/ast/block.rs @@ -1,6 +1,6 @@ use std::ops::{Index, IndexMut}; -use crate::{DeclId, Signature}; +use crate::{DeclId, Signature, VarId}; use super::Statement; @@ -9,6 +9,7 @@ pub struct Block { pub signature: Box, pub stmts: Vec, pub exports: Vec<(Vec, DeclId)>, // Assuming just defs for now + pub captures: Vec, } impl Block { @@ -47,6 +48,7 @@ impl Block { signature: Box::new(Signature::new("")), stmts: vec![], exports: vec![], + captures: vec![], } } @@ -55,6 +57,7 @@ impl Block { signature: self.signature, stmts: self.stmts, exports, + captures: self.captures, } } } @@ -68,6 +71,7 @@ where signature: Box::new(Signature::new("")), stmts: stmts.collect(), exports: vec![], + captures: vec![], } } } diff --git a/crates/nu-protocol/src/ast/expr.rs b/crates/nu-protocol/src/ast/expr.rs index e1baae1ac1..f01c815fde 100644 --- a/crates/nu-protocol/src/ast/expr.rs +++ b/crates/nu-protocol/src/ast/expr.rs @@ -13,6 +13,7 @@ pub enum Expr { RangeOperator, ), Var(VarId), + VarDecl(VarId), Call(Box), ExternalCall(String, Span, Vec), Operator(Operator), diff --git a/crates/nu-protocol/src/ast/expression.rs b/crates/nu-protocol/src/ast/expression.rs index 5627b167c2..7278cdb374 100644 --- a/crates/nu-protocol/src/ast/expression.rs +++ b/crates/nu-protocol/src/ast/expression.rs @@ -77,6 +77,7 @@ impl Expression { pub fn as_var(&self) -> Option { match self.expr { Expr::Var(var_id) => Some(var_id), + Expr::VarDecl(var_id) => Some(var_id), _ => None, } } diff --git a/crates/nu-protocol/src/engine/stack.rs b/crates/nu-protocol/src/engine/stack.rs index b08000a578..4918f98657 100644 --- a/crates/nu-protocol/src/engine/stack.rs +++ b/crates/nu-protocol/src/engine/stack.rs @@ -3,14 +3,11 @@ use std::collections::HashMap; use crate::{ShellError, Value, VarId}; #[derive(Debug, Clone)] -pub struct StackFrame { +pub struct Stack { pub vars: HashMap, pub env_vars: HashMap, } -#[derive(Clone, Debug)] -pub struct Stack(Vec); - impl Default for Stack { fn default() -> Self { Self::new() @@ -19,77 +16,82 @@ impl Default for Stack { impl Stack { pub fn new() -> Stack { - Stack(vec![StackFrame { + Stack { vars: HashMap::new(), env_vars: HashMap::new(), - }]) + } } pub fn get_var(&self, var_id: VarId) -> Result { - for frame in self.0.iter().rev() { - if let Some(v) = frame.vars.get(&var_id) { - return Ok(v.clone()); - } + if let Some(v) = self.vars.get(&var_id) { + return Ok(v.clone()); } Err(ShellError::InternalError("variable not found".into())) } pub fn add_var(&mut self, var_id: VarId, value: Value) { - let frame = self - .0 - .last_mut() - .expect("internal error: can't access stack frame"); - frame.vars.insert(var_id, value); + self.vars.insert(var_id, value); } pub fn add_env_var(&mut self, var: String, value: String) { - let frame = self - .0 - .last_mut() - .expect("internal error: can't access stack frame"); - frame.env_vars.insert(var, value); + self.env_vars.insert(var, value); } - pub fn enter_scope(&self) -> Stack { - // FIXME: VERY EXPENSIVE to clone entire stack - let mut output = self.clone(); - output.0.push(StackFrame { - vars: HashMap::new(), - env_vars: HashMap::new(), - }); + pub fn collect_captures(&self, captures: &[VarId]) -> Stack { + let mut output = Stack::new(); - output - } - - pub fn get_env_vars(&self) -> HashMap { - let mut output = HashMap::new(); - - for frame in &self.0 { - output.extend(frame.env_vars.clone().into_iter()); + for capture in captures { + output.vars.insert( + *capture, + self.get_var(*capture) + .expect("internal error: capture of missing variable"), + ); } output } + // pub fn enter_scope(&self) -> Stack { + // // FIXME: VERY EXPENSIVE to clone entire stack + // let mut output = self.clone(); + // output.0.push(StackFrame { + // vars: HashMap::new(), + // env_vars: HashMap::new(), + // }); + + // output + // } + + pub fn get_env_vars(&self) -> HashMap { + // let mut output = HashMap::new(); + + // for frame in &self.0 { + // output.extend(frame.env_vars.clone().into_iter()); + // } + + // output + self.env_vars.clone() + } + pub fn get_env_var(&self, name: &str) -> Option { - for frame in self.0.iter().rev() { - if let Some(v) = frame.env_vars.get(name) { - return Some(v.to_string()); - } + // for frame in self.0.iter().rev() { + if let Some(v) = self.env_vars.get(name) { + return Some(v.to_string()); } + // } None } pub fn print_stack(&self) { - for frame in self.0.iter().rev() { - println!("===frame==="); - println!("vars:"); - for (var, val) in &frame.vars { - println!(" {}: {:?}", var, val); - } - println!("env vars:"); - for (var, val) in &frame.env_vars { - println!(" {}: {:?}", var, val); - } + // for frame in self.0.iter().rev() { + // println!("===frame==="); + println!("vars:"); + for (var, val) in &self.vars { + println!(" {}: {:?}", var, val); } + println!("env vars:"); + for (var, val) in &self.env_vars { + println!(" {}: {:?}", var, val); + } + // } } } From 85a69c0a4598d95ac784d523514fffa81f922593 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 10:14:21 +1300 Subject: [PATCH 12/16] WIP --- TODO.md | 1 + crates/nu-cli/src/completions.rs | 1 + .../nu-command/src/conversions/into/binary.rs | 32 +++++---- .../src/conversions/into/filesize.rs | 36 +++++----- crates/nu-command/src/conversions/into/int.rs | 32 +++++---- crates/nu-command/src/core_commands/for_.rs | 14 ++-- crates/nu-command/src/filters/length.rs | 2 +- crates/nu-command/src/strings/size.rs | 24 +++---- crates/nu-command/src/strings/split/chars.rs | 6 +- crates/nu-command/src/strings/split/column.rs | 6 +- crates/nu-command/src/strings/split/row.rs | 6 +- crates/nu-engine/src/eval.rs | 35 ++++------ crates/nu-protocol/src/engine/stack.rs | 10 +-- crates/nu-protocol/src/pipeline_data.rs | 66 ++++++++++++++++++- 14 files changed, 151 insertions(+), 120 deletions(-) diff --git a/TODO.md b/TODO.md index f16902de6d..507079c9d7 100644 --- a/TODO.md +++ b/TODO.md @@ -30,6 +30,7 @@ - [x] Handling rows with missing columns during a cell path - [x] finish operator type-checking - [x] Config file loading +- [x] block variable captures - [ ] Input/output types - [ ] Support for `$in` - [ ] ctrl-c support diff --git a/crates/nu-cli/src/completions.rs b/crates/nu-cli/src/completions.rs index 7e3e4f08d1..43f7f92229 100644 --- a/crates/nu-cli/src/completions.rs +++ b/crates/nu-cli/src/completions.rs @@ -77,6 +77,7 @@ impl Completer for NuCompleter { let v: Vec<_> = match result { Ok(pd) => pd + .into_iter() .map(move |x| { let s = x.as_string().expect( "FIXME: better error handling for custom completions", diff --git a/crates/nu-command/src/conversions/into/binary.rs b/crates/nu-command/src/conversions/into/binary.rs index c1f39e26ef..4704b20329 100644 --- a/crates/nu-command/src/conversions/into/binary.rs +++ b/crates/nu-command/src/conversions/into/binary.rs @@ -1,7 +1,7 @@ use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, + Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; #[derive(Clone)] @@ -92,23 +92,21 @@ fn into_binary( let head = call.head; // let column_paths: Vec = call.rest(context, 0)?; - Ok(input - .map(move |v| { - action(v, head) - // FIXME: Add back in cell_path support - // if column_paths.is_empty() { - // action(v, head) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = - // ret.swap_data_by_cell_path(path, Box::new(move |old| action(old, old.tag())))?; - // } + input.map(move |v| { + action(v, head) + // FIXME: Add back in cell_path support + // if column_paths.is_empty() { + // action(v, head) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = + // ret.swap_data_by_cell_path(path, Box::new(move |old| action(old, old.tag())))?; + // } - // Ok(ret) - // } - }) - .into_pipeline_data()) + // Ok(ret) + // } + }) } fn int_to_endian(n: i64) -> Vec { diff --git a/crates/nu-command/src/conversions/into/filesize.rs b/crates/nu-command/src/conversions/into/filesize.rs index 1fa67ef940..68c9746e7f 100644 --- a/crates/nu-command/src/conversions/into/filesize.rs +++ b/crates/nu-command/src/conversions/into/filesize.rs @@ -1,7 +1,7 @@ use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, + Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; #[derive(Clone)] @@ -120,26 +120,24 @@ fn into_filesize( let head = call.head; // let call_paths: Vec = args.rest(0)?; - Ok(input - .map(move |v| { - action(v, head) + input.map(move |v| { + action(v, head) - // FIXME: Add back cell_path support - // if column_paths.is_empty() { - // action(&v, v.tag()) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = ret.swap_data_by_column_path( - // path, - // Box::new(move |old| action(old, old.tag())), - // )?; - // } + // FIXME: Add back cell_path support + // if column_paths.is_empty() { + // action(&v, v.tag()) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = ret.swap_data_by_column_path( + // path, + // Box::new(move |old| action(old, old.tag())), + // )?; + // } - // Ok(ret) - // } - }) - .into_pipeline_data()) + // Ok(ret) + // } + }) } pub fn action(input: Value, span: Span) -> Value { diff --git a/crates/nu-command/src/conversions/into/int.rs b/crates/nu-command/src/conversions/into/int.rs index c8f018fc5f..eb76ef9aa2 100644 --- a/crates/nu-command/src/conversions/into/int.rs +++ b/crates/nu-command/src/conversions/into/int.rs @@ -1,7 +1,7 @@ use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, + Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, }; #[derive(Clone)] @@ -96,23 +96,21 @@ fn into_int( let head = call.head; // let column_paths: Vec = call.rest(context, 0)?; - Ok(input - .map(move |v| { - action(v, head) - // FIXME: Add back cell_path support - // if column_paths.is_empty() { - // action(&v, v.tag()) - // } else { - // let mut ret = v; - // for path in &column_paths { - // ret = ret - // .swap_data_by_column_path(path, Box::new(move |old| action(old, old.tag())))?; - // } + input.map(move |v| { + action(v, head) + // FIXME: Add back cell_path support + // if column_paths.is_empty() { + // action(&v, v.tag()) + // } else { + // let mut ret = v; + // for path in &column_paths { + // ret = ret + // .swap_data_by_column_path(path, Box::new(move |old| action(old, old.tag())))?; + // } - // Ok(ret) - // } - }) - .into_pipeline_data()) + // Ok(ret) + // } + }) } pub fn action(input: Value, span: Span) -> Value { diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index d85a42617a..f9278de05e 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -60,7 +60,7 @@ impl Command for For { let mut stack = stack.collect_captures(&block.captures); match values { - Value::List { vals, span } => Ok(vals + Value::List { vals, .. } => Ok(vals .into_iter() .map(move |x| { let mut stack = stack.clone(); @@ -68,25 +68,19 @@ impl Command for For { let block = engine_state.get_block(block_id); match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { - Ok(value) => Value::List { - vals: value.collect(), - span, - }, + Ok(pipeline_data) => pipeline_data.into_value(), Err(error) => Value::Error { error }, } }) .into_pipeline_data()), - Value::Range { val, span } => Ok(val + Value::Range { val, .. } => Ok(val .into_range_iter()? .map(move |x| { stack.add_var(var_id, x); let block = engine_state.get_block(block_id); match eval_block(&engine_state, &mut stack, block, PipelineData::new()) { - Ok(value) => Value::List { - vals: value.collect(), - span, - }, + Ok(pipeline_data) => pipeline_data.into_value(), Err(error) => Value::Error { error }, } }) diff --git a/crates/nu-command/src/filters/length.rs b/crates/nu-command/src/filters/length.rs index 0ab8690cf4..724018f851 100644 --- a/crates/nu-command/src/filters/length.rs +++ b/crates/nu-command/src/filters/length.rs @@ -32,7 +32,7 @@ impl Command for Length { } .into_pipeline_data()), _ => Ok(Value::Int { - val: input.count() as i64, + val: input.into_iter().count() as i64, span: call.head, } .into_pipeline_data()), diff --git a/crates/nu-command/src/strings/size.rs b/crates/nu-command/src/strings/size.rs index 251a6b1c7c..96bf047b91 100644 --- a/crates/nu-command/src/strings/size.rs +++ b/crates/nu-command/src/strings/size.rs @@ -4,9 +4,7 @@ use unicode_segmentation::UnicodeSegmentation; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{ - Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, -}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, Type, Value}; #[derive(Clone)] pub struct Size; @@ -104,18 +102,16 @@ impl Command for Size { fn size(call: &Call, input: PipelineData) -> Result { let span = call.head; - Ok(input - .map(move |v| match v.as_string() { - Ok(s) => count(&s, span), - Err(_) => Value::Error { - error: ShellError::PipelineMismatch { - expected: Type::String, - expected_span: span, - origin: span, - }, + input.map(move |v| match v.as_string() { + Ok(s) => count(&s, span), + Err(_) => Value::Error { + error: ShellError::PipelineMismatch { + expected: Type::String, + expected_span: span, + origin: span, }, - }) - .into_pipeline_data()) + }, + }) } fn count(contents: &str, span: Span) -> Value { diff --git a/crates/nu-command/src/strings/split/chars.rs b/crates/nu-command/src/strings/split/chars.rs index f553e41b83..163d5bb110 100644 --- a/crates/nu-command/src/strings/split/chars.rs +++ b/crates/nu-command/src/strings/split/chars.rs @@ -1,7 +1,7 @@ use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, + Example, PipelineData, ShellError, Signature, Span, Type, Value, }; #[derive(Clone)] @@ -54,9 +54,7 @@ fn split_chars( ) -> Result { let span = call.head; - Ok(input - .flat_map(move |x| split_chars_helper(&x, span)) - .into_pipeline_data()) + input.flat_map(move |x| split_chars_helper(&x, span)) } fn split_chars_helper(v: &Value, name: Span) -> Vec { diff --git a/crates/nu-command/src/strings/split/column.rs b/crates/nu-command/src/strings/split/column.rs index 8090c4d237..6dedde4090 100644 --- a/crates/nu-command/src/strings/split/column.rs +++ b/crates/nu-command/src/strings/split/column.rs @@ -2,7 +2,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, + PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; #[derive(Clone)] @@ -54,9 +54,7 @@ fn split_column( let rest: Vec> = call.rest(engine_state, stack, 1)?; let collapse_empty = call.has_flag("collapse-empty"); - Ok(input - .map(move |x| split_column_helper(&x, &separator, &rest, collapse_empty, name_span)) - .into_pipeline_data()) + input.map(move |x| split_column_helper(&x, &separator, &rest, collapse_empty, name_span)) } fn split_column_helper( diff --git a/crates/nu-command/src/strings/split/row.rs b/crates/nu-command/src/strings/split/row.rs index 80bd303945..880672faff 100644 --- a/crates/nu-command/src/strings/split/row.rs +++ b/crates/nu-command/src/strings/split/row.rs @@ -2,7 +2,7 @@ use nu_engine::CallExt; use nu_protocol::{ ast::Call, engine::{Command, EngineState, Stack}, - IntoPipelineData, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, + PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Type, Value, }; #[derive(Clone)] @@ -45,9 +45,7 @@ fn split_row( let name_span = call.head; let separator: Spanned = call.req(engine_state, stack, 0)?; - Ok(input - .flat_map(move |x| split_row_helper(&x, &separator, name_span)) - .into_pipeline_data()) + input.flat_map(move |x| split_row_helper(&x, &separator, name_span)) } fn split_row_helper(v: &Value, separator: &Spanned, name: Span) -> Vec { diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index fce4519b01..2a568b7901 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -226,26 +226,20 @@ pub fn eval_expression( Expr::RowCondition(_, expr) => eval_expression(engine_state, stack, expr), Expr::Call(call) => { // FIXME: protect this collect with ctrl-c - Ok(Value::List { - vals: eval_call(engine_state, stack, call, PipelineData::new())?.collect(), - span: expr.span, - }) + Ok(eval_call(engine_state, stack, call, PipelineData::new())?.into_value()) } Expr::ExternalCall(name, span, args) => { // FIXME: protect this collect with ctrl-c - Ok(Value::List { - vals: eval_external( - engine_state, - stack, - name, - span, - args, - PipelineData::new(), - true, - )? - .collect(), - span: expr.span, - }) + Ok(eval_external( + engine_state, + stack, + name, + span, + args, + PipelineData::new(), + true, + )? + .into_value()) } Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }), Expr::BinaryOp(lhs, op, rhs) => { @@ -278,13 +272,8 @@ pub fn eval_expression( Expr::Subexpression(block_id) => { let block = engine_state.get_block(*block_id); - let mut stack = stack.collect_captures(&block.captures); - // FIXME: protect this collect with ctrl-c - Ok(Value::List { - vals: eval_block(engine_state, &mut stack, block, PipelineData::new())?.collect(), - span: expr.span, - }) + Ok(eval_block(engine_state, stack, block, PipelineData::new())?.into_value()) } Expr::Block(block_id) => Ok(Value::Block { val: *block_id, diff --git a/crates/nu-protocol/src/engine/stack.rs b/crates/nu-protocol/src/engine/stack.rs index 4918f98657..3a0e46a1de 100644 --- a/crates/nu-protocol/src/engine/stack.rs +++ b/crates/nu-protocol/src/engine/stack.rs @@ -40,11 +40,11 @@ impl Stack { let mut output = Stack::new(); for capture in captures { - output.vars.insert( - *capture, - self.get_var(*capture) - .expect("internal error: capture of missing variable"), - ); + // Note: this assumes we have calculated captures correctly and that commands + // that take in a var decl will manually set this into scope when running the blocks + if let Ok(value) = self.get_var(*capture) { + output.vars.insert(*capture, value); + } } output diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs index d8c1836ee5..db77ad61f7 100644 --- a/crates/nu-protocol/src/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -38,6 +38,51 @@ impl PipelineData { PipelineData::Value(v) => v.follow_cell_path(cell_path), } } + + /// Simplified mapper to help with simple values also. For full iterator support use `.into_iter()` instead + pub fn map(self, mut f: F) -> Result + where + Self: Sized, + F: FnMut(Value) -> Value + 'static + Send, + { + match self { + PipelineData::Value(Value::List { vals, .. }) => { + Ok(vals.into_iter().map(f).into_pipeline_data()) + } + PipelineData::Stream(stream) => Ok(stream.map(f).into_pipeline_data()), + PipelineData::Value(Value::Range { val, .. }) => { + Ok(val.into_range_iter()?.map(f).into_pipeline_data()) + } + PipelineData::Value(v) => { + let output = f(v); + match output { + Value::Error { error } => Err(error), + v => Ok(v.into_pipeline_data()), + } + } + } + } + + /// Simplified flatmapper. For full iterator support use `.into_iter()` instead + pub fn flat_map(self, mut f: F) -> Result + where + Self: Sized, + U: IntoIterator, + ::IntoIter: 'static + Send, + F: FnMut(Value) -> U + 'static + Send, + { + match self { + PipelineData::Value(Value::List { vals, .. }) => { + Ok(vals.into_iter().map(f).flatten().into_pipeline_data()) + } + PipelineData::Stream(stream) => Ok(stream.map(f).flatten().into_pipeline_data()), + PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() { + Ok(iter) => Ok(iter.map(f).flatten().into_pipeline_data()), + Err(error) => Err(error), + }, + PipelineData::Value(v) => Ok(f(v).into_iter().into_pipeline_data()), + } + } } impl Default for PipelineData { @@ -46,11 +91,28 @@ impl Default for PipelineData { } } -impl Iterator for PipelineData { +pub struct PipelineIterator(PipelineData); + +impl IntoIterator for PipelineData { + type Item = Value; + + type IntoIter = PipelineIterator; + + fn into_iter(self) -> Self::IntoIter { + match self { + PipelineData::Value(Value::List { vals, .. }) => PipelineIterator( + PipelineData::Stream(ValueStream(Box::new(vals.into_iter()))), + ), + x => PipelineIterator(x), + } + } +} + +impl Iterator for PipelineIterator { type Item = Value; fn next(&mut self) -> Option { - match self { + match &mut self.0 { PipelineData::Value(Value::Nothing { .. }) => None, PipelineData::Value(v) => { let prev = std::mem::take(v); From 4be61ce604f9a20b3b0b6170cc1ef65470369c93 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 11:18:45 +1300 Subject: [PATCH 13/16] Tests pass --- src/tests.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index da428731f1..f990e6cc87 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -249,32 +249,32 @@ fn alias_2() -> TestResult { #[test] fn block_param1() -> TestResult { - run_test("[3] | each { $it + 10 }", "[13]") + run_test("[3] | each { $it + 10 } | get 0", "13") } #[test] fn block_param2() -> TestResult { - run_test("[3] | each { |y| $y + 10 }", "[13]") + run_test("[3] | each { |y| $y + 10 } | get 0", "13") } #[test] fn block_param3_list_iteration() -> TestResult { - run_test("[1,2,3] | each { $it + 10 }", "[11, 12, 13]") + run_test("[1,2,3] | each { $it + 10 } | get 1", "12") } #[test] fn block_param4_list_iteration() -> TestResult { - run_test("[1,2,3] | each { |y| $y + 10 }", "[11, 12, 13]") + run_test("[1,2,3] | each { |y| $y + 10 } | get 2", "13") } #[test] fn range_iteration1() -> TestResult { - run_test("1..4 | each { |y| $y + 10 }", "[11, 12, 13, 14]") + run_test("1..4 | each { |y| $y + 10 } | get 0", "11") } #[test] fn range_iteration2() -> TestResult { - run_test("4..1 | each { |y| $y + 100 }", "[104, 103, 102, 101]") + run_test("4..1 | each { |y| $y + 100 } | get 3", "101") } #[test] @@ -311,22 +311,22 @@ fn build_string3() -> TestResult { #[test] fn build_string4() -> TestResult { run_test( - "['sam','rick','pete'] | each { build-string $it ' is studying'}", - "[sam is studying, rick is studying, pete is studying]", + "['sam','rick','pete'] | each { build-string $it ' is studying'} | get 2", + "pete is studying", ) } #[test] fn build_string5() -> TestResult { run_test( - "['sam','rick','pete'] | each { |x| build-string $x ' is studying'}", - "[sam is studying, rick is studying, pete is studying]", + "['sam','rick','pete'] | each { |x| build-string $x ' is studying'} | get 1", + "rick is studying", ) } #[test] fn cell_path_subexpr1() -> TestResult { - run_test("([[lang, gems]; [nu, 100]]).lang", "[nu]") + run_test("([[lang, gems]; [nu, 100]]).lang | get 0", "nu") } #[test] @@ -336,7 +336,7 @@ fn cell_path_subexpr2() -> TestResult { #[test] fn cell_path_var1() -> TestResult { - run_test("let x = [[lang, gems]; [nu, 100]]; $x.lang", "[nu]") + run_test("let x = [[lang, gems]; [nu, 100]]; $x.lang | get 0", "nu") } #[test] @@ -352,21 +352,21 @@ fn custom_rest_var() -> TestResult { #[test] fn row_iteration() -> TestResult { run_test( - "[[name, size]; [tj, 100], [rl, 200]] | each { $it.size * 8 }", - "[800, 1600]", + "[[name, size]; [tj, 100], [rl, 200]] | each { $it.size * 8 } | get 1", + "1600", ) } #[test] fn record_iteration() -> TestResult { - run_test("([[name, level]; [aa, 100], [bb, 200]] | each { $it | each { |x| if $x.column == \"level\" { $x.value + 100 } else { $x.value } } }).level", "[200, 300]") + run_test("([[name, level]; [aa, 100], [bb, 200]] | each { $it | each { |x| if $x.column == \"level\" { $x.value + 100 } else { $x.value } } }).level | get 1", "300") } #[test] fn row_condition1() -> TestResult { run_test( - "([[name, size]; [a, 1], [b, 2], [c, 3]] | where size < 3).name", - "[a, b]", + "([[name, size]; [a, 1], [b, 2], [c, 3]] | where size < 3).name | get 1", + "b", ) } From c18f0dcc849f43d72f2ceb1ce1bba458790b12e3 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 11:24:10 +1300 Subject: [PATCH 14/16] range display touchup --- crates/nu-protocol/src/value/mod.rs | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 3cd0b0a480..b8b2c3041a 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -167,17 +167,9 @@ impl Value { Value::Filesize { val, .. } => format_filesize(val), Value::Duration { val, .. } => format_duration(val), Value::Date { val, .. } => HumanTime::from(val).to_string(), - Value::Range { val, .. } => match val.into_range_iter() { - Ok(iter) => { - format!( - "range: [{}]", - iter.map(|x| x.into_string()) - .collect::>() - .join(", ") - ) - } - Err(error) => format!("{:?}", error), - }, + Value::Range { val, .. } => { + format!("{}..{}", val.from.into_string(), val.to.into_string()) + } Value::String { val, .. } => val, Value::List { vals: val, .. } => format!( "[{}]", @@ -210,15 +202,9 @@ impl Value { Value::Filesize { val, .. } => format!("{} bytes", val), Value::Duration { val, .. } => format!("{} ns", val), Value::Date { val, .. } => format!("{:?}", val), - Value::Range { val, .. } => match val.into_range_iter() { - Ok(iter) => iter - .map(|x| x.into_string()) - .collect::>() - .join(", "), - Err(error) => { - format!("{:?}", error) - } - }, + Value::Range { val, .. } => { + format!("{}..{}", val.from.into_string(), val.to.into_string()) + } Value::String { val, .. } => val, Value::List { vals: val, .. } => val .into_iter() From 962adf5a1206fa2a5c0845af98a8bca048003803 Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 11:56:29 +1300 Subject: [PATCH 15/16] add threading --- crates/nu-command/src/system/run_external.rs | 50 ++++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 75e551ceee..a985bc8bb1 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::env; use std::io::{BufRead, BufReader, Write}; -use std::process::{ChildStdin, Command as CommandSys, Stdio}; +use std::process::{Command as CommandSys, Stdio}; use std::sync::mpsc; use nu_protocol::engine::{EngineState, Stack}; @@ -79,11 +79,7 @@ impl ExternalCommand { // If there is an input from the pipeline. The stdin from the process // is piped so it can be used to send the input information - if let PipelineData::Value(Value::String { .. }) = input { - process.stdin(Stdio::piped()); - } - - if let PipelineData::Stream { .. } = input { + if !matches!(input, PipelineData::Value(Value::Nothing { .. })) { process.stdin(Stdio::piped()); } @@ -95,17 +91,30 @@ impl ExternalCommand { Ok(mut child) => { // if there is a string or a stream, that is sent to the pipe std if let Some(mut stdin_write) = child.stdin.take() { - for value in input { - match value { - Value::String { val, span: _ } => { - self.write_to_stdin(&mut stdin_write, val.as_bytes())? + std::thread::spawn(move || { + for value in input.into_iter() { + match value { + Value::String { val, span: _ } => { + if stdin_write.write(val.as_bytes()).is_err() { + return Ok(()); + } + } + Value::Binary { val, span: _ } => { + if stdin_write.write(&val).is_err() { + return Ok(()); + } + } + x => { + if stdin_write.write(x.into_string().as_bytes()).is_err() { + return Err(()); + } + } } - Value::Binary { val, span: _ } => { - self.write_to_stdin(&mut stdin_write, &val)? - } - _ => continue, } - } + Ok(()) + }); + } else { + println!("Couldn't take stdin"); } // If this external is not the last expression, then its output is piped to a channel @@ -188,17 +197,6 @@ impl ExternalCommand { process } } - - fn write_to_stdin(&self, stdin_write: &mut ChildStdin, val: &[u8]) -> Result<(), ShellError> { - if stdin_write.write(val).is_err() { - Err(ShellError::ExternalCommand( - "Error writing input to stdin".to_string(), - self.name.span, - )) - } else { - Ok(()) - } - } } // The piped data from stdout from the external command can be either String From df07ed5bf633324503054fb86591c8a88271178b Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 26 Oct 2021 12:12:27 +1300 Subject: [PATCH 16/16] Remove debug message --- Cargo.lock | 32 ++++++++++---------- crates/nu-command/src/system/run_external.rs | 2 -- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4ea08395e..0fe327602a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,9 +74,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152" dependencies = [ "addr2line", "cc", @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "byte-unit" -version = "4.0.12" +version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063197e6eb4b775b64160dedde7a0986bb2836cce140e9492e9e96f28e18bcd8" +checksum = "956ffc5b0ec7d7a6949e3f21fd63ba5af4cffdc2ba1e0b7bf62b481458c4ae7f" dependencies = [ "utf8-width", ] @@ -403,9 +403,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] @@ -439,9 +439,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" [[package]] name = "linked-hash-map" @@ -538,9 +538,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", @@ -717,9 +717,9 @@ dependencies = [ [[package]] name = "object" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "memchr", ] @@ -778,9 +778,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "predicates" @@ -1192,9 +1192,9 @@ dependencies = [ [[package]] name = "termtree" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fbf2dd23e79c28ccfa2472d3e6b3b189866ffef1aeb91f17c2d968b6586378" +checksum = "76565a2f8df1d2170b5c365aa39d0623fd93fec20545edde299233cea82d0f16" [[package]] name = "textwrap" diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index a985bc8bb1..c1f27e58bc 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -113,8 +113,6 @@ impl ExternalCommand { } Ok(()) }); - } else { - println!("Couldn't take stdin"); } // If this external is not the last expression, then its output is piped to a channel