diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs index 3871cd8c2..3cce2c3b7 100644 --- a/crates/nu-cli/src/lib.rs +++ b/crates/nu-cli/src/lib.rs @@ -25,7 +25,6 @@ pub use print::Print; pub use prompt::NushellPrompt; pub use repl::evaluate_repl; pub use syntax_highlight::NuHighlighter; -pub use util::print_pipeline_data; pub use util::{eval_source, gather_parent_env_vars, get_init_cwd, report_error}; pub use validation::NuValidator; diff --git a/crates/nu-cli/src/print.rs b/crates/nu-cli/src/print.rs index 134a998ff..7a9cd137f 100644 --- a/crates/nu-cli/src/print.rs +++ b/crates/nu-cli/src/print.rs @@ -34,7 +34,7 @@ impl Command for Print { let head = call.head; for arg in args { - crate::util::print_pipeline_data(arg.into_pipeline_data(), engine_state, stack)?; + arg.into_pipeline_data().print(engine_state, stack)?; } Ok(PipelineData::new(head)) diff --git a/crates/nu-cli/src/util.rs b/crates/nu-cli/src/util.rs index cbabe6c66..8ce44b430 100644 --- a/crates/nu-cli/src/util.rs +++ b/crates/nu-cli/src/util.rs @@ -4,94 +4,13 @@ use nu_engine::eval_block; use nu_parser::{lex, parse, unescape_unquote_string, Token, TokenContents}; use nu_protocol::engine::StateWorkingSet; use nu_protocol::{ - ast::Call, engine::{EngineState, Stack}, PipelineData, ShellError, Span, Value, }; #[cfg(windows)] use nu_utils::enable_vt_processing; -use std::io::Write; use std::path::PathBuf; -pub fn print_pipeline_data( - input: PipelineData, - engine_state: &EngineState, - stack: &mut Stack, -) -> 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 config = engine_state.get_config(); - - let stdout = std::io::stdout(); - - if let PipelineData::ExternalStream { - stdout: stream, - exit_code, - .. - } = input - { - if let Some(stream) = stream { - for s in stream { - let _ = stdout.lock().write_all(s?.as_binary()?); - } - } - - // Make sure everything has finished - if let Some(exit_code) = exit_code { - let _: Vec<_> = exit_code.into_iter().collect(); - } - - return Ok(()); - } - - match engine_state.find_decl("table".as_bytes()) { - Some(decl_id) => { - let table = engine_state.get_decl(decl_id).run( - engine_state, - stack, - &Call::new(Span::new(0, 0)), - input, - )?; - - for item in table { - let stdout = std::io::stdout(); - - if let Value::Error { error } = item { - return Err(error); - } - - let mut out = item.into_string("\n", config); - out.push('\n'); - - match stdout.lock().write_all(out.as_bytes()) { - Ok(_) => (), - Err(err) => eprintln!("{}", err), - }; - } - } - None => { - for item in input { - let stdout = std::io::stdout(); - - if let Value::Error { error } = item { - return Err(error); - } - - let mut out = item.into_string("\n", config); - out.push('\n'); - - match stdout.lock().write_all(out.as_bytes()) { - Ok(_) => (), - Err(err) => eprintln!("{}", err), - }; - } - } - }; - - Ok(()) -} - // This will collect environment variables from std::env and adds them to a stack. // // In order to ensure the values have spans, it first creates a dummy file, writes the collected @@ -329,7 +248,7 @@ pub fn eval_source( set_last_exit_code(stack, 0); } - if let Err(err) = print_pipeline_data(pipeline_data, engine_state, stack) { + if let Err(err) = pipeline_data.print(engine_state, stack) { let working_set = StateWorkingSet::new(engine_state); report_error(&working_set, &err); diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs index ba694e154..39aa6323a 100644 --- a/crates/nu-protocol/src/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -1,6 +1,13 @@ -use std::sync::{atomic::AtomicBool, Arc}; +use std::{ + io::Write, + sync::{atomic::AtomicBool, Arc}, +}; -use crate::{ast::PathMember, Config, ListStream, RawStream, ShellError, Span, Value}; +use crate::{ + ast::{Call, PathMember}, + engine::{EngineState, Stack}, + Config, ListStream, RawStream, ShellError, Span, Value, +}; /// The foundational abstraction for input and output to commands /// @@ -408,6 +415,81 @@ impl PipelineData { } } } + + pub fn print(self, engine_state: &EngineState, stack: &mut Stack) -> 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 config = engine_state.get_config(); + + let stdout = std::io::stdout(); + + if let PipelineData::ExternalStream { + stdout: stream, + exit_code, + .. + } = self + { + if let Some(stream) = stream { + for s in stream { + let _ = stdout.lock().write_all(s?.as_binary()?); + } + } + + // Make sure everything has finished + if let Some(exit_code) = exit_code { + let _: Vec<_> = exit_code.into_iter().collect(); + } + + return Ok(()); + } + + match engine_state.find_decl("table".as_bytes()) { + Some(decl_id) => { + let table = engine_state.get_decl(decl_id).run( + engine_state, + stack, + &Call::new(Span::new(0, 0)), + self, + )?; + + for item in table { + let stdout = std::io::stdout(); + + if let Value::Error { error } = item { + return Err(error); + } + + let mut out = item.into_string("\n", config); + out.push('\n'); + + match stdout.lock().write_all(out.as_bytes()) { + Ok(_) => (), + Err(err) => eprintln!("{}", err), + }; + } + } + None => { + for item in self { + let stdout = std::io::stdout(); + + if let Value::Error { error } = item { + return Err(error); + } + + let mut out = item.into_string("\n", config); + out.push('\n'); + + match stdout.lock().write_all(out.as_bytes()) { + Ok(_) => (), + Err(err) => eprintln!("{}", err), + }; + } + } + }; + + Ok(()) + } } pub struct PipelineIterator(PipelineData);