From 1ce3c2a848b6a693a0a04699185d38fa9500c70b Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 2 Mar 2024 11:31:47 +0100 Subject: [PATCH] Add the missing print command --- src/commands.rs | 79 +++++++++++++++++++++++++++++++++++++++++ src/context/bindings.rs | 5 ++- src/lib.rs | 1 + tests/test_eval.rs | 10 ++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/commands.rs diff --git a/src/commands.rs b/src/commands.rs new file mode 100644 index 0000000..f2878c3 --- /dev/null +++ b/src/commands.rs @@ -0,0 +1,79 @@ +/// Copy of the nushell print command with a slight adjustment for pipelines +/// Source: https://github.com/nushell/nushell/blob/98525043edd20abb62da09726d75816d09d68f1e/crates/nu-cli/src/print.rs +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Category, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Type, Value, +}; + +use crate::NewEmpty; + +#[derive(Clone)] +pub struct PrintCommand; + +impl Command for PrintCommand { + fn name(&self) -> &str { + "print" + } + + fn signature(&self) -> Signature { + Signature::build("print") + .input_output_types(vec![ + (Type::Nothing, Type::Nothing), + (Type::Any, Type::Nothing), + ]) + .allow_variants_without_examples(true) + .rest("rest", SyntaxShape::Any, "the values to print") + .switch( + "no-newline", + "print without inserting a newline for the line ending", + Some('n'), + ) + .switch("stderr", "print to stderr instead of stdout", Some('e')) + .category(Category::Strings) + } + + fn usage(&self) -> &str { + "Print the given values to stdout." + } + + fn extra_usage(&self) -> &str { + r#"Unlike `echo`, this command does not return any value (`print | describe` will return "nothing"). +Since this command has no output, there is no point in piping it with other commands. +`print` may be used inside blocks of code (e.g.: hooks) to display text during execution without interfering with the pipeline. +When used inside a pipeline it passes the input forward as output without interfering with it. +"# + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let args: Vec = call.rest(engine_state, stack, 0)?; + let no_newline = call.has_flag(engine_state, stack, "no-newline")?; + let to_stderr = call.has_flag(engine_state, stack, "stderr")?; + + let input_val = input.into_value(Span::empty()); + + // This will allow for easy printing of pipelines as well + if !args.is_empty() { + for arg in args { + arg.into_pipeline_data() + .print(engine_state, stack, no_newline, to_stderr)?; + } + } else if !input_val.is_nothing() { + input_val.clone().into_pipeline_data().print( + engine_state, + stack, + no_newline, + to_stderr, + )?; + } + + Ok(input_val.into_pipeline_data()) + } +} diff --git a/src/context/bindings.rs b/src/context/bindings.rs index fbd6112..14964e9 100644 --- a/src/context/bindings.rs +++ b/src/context/bindings.rs @@ -2,7 +2,7 @@ use nu_cmd_lang::*; use nu_command::*; use nu_protocol::engine::{EngineState, StateWorkingSet}; -use crate::error::CrateResult; +use crate::{commands::PrintCommand, error::CrateResult}; macro_rules! bind_commands { ($engine_state:expr, $( $command:expr),* $(,)? ) => { @@ -42,6 +42,7 @@ pub fn bind_core_commands(engine_state: &mut EngineState) -> CrateResult<()> { Hide, HideEnv, If, + PrintCommand, Ignore, Overlay, OverlayUse, @@ -66,6 +67,7 @@ pub fn bind_debug_commands(engine_state: &mut EngineState) -> CrateResult<()> { engine_state, Ast, Debug, + DebugInfo, Explain, Inspect, Metadata, @@ -106,6 +108,7 @@ pub fn bind_filter_commands(engine_state: &mut EngineState) -> CrateResult<()> { GroupBy, Headers, Insert, + Items, Join, SplitBy, Take, diff --git a/src/lib.rs b/src/lib.rs index c4e8cdd..075fc2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![doc=include_str!("../README.md")] pub(crate) mod argument; +pub mod commands; pub(crate) mod context; pub(crate) mod error; pub(crate) mod into_expression; diff --git a/tests/test_eval.rs b/tests/test_eval.rs index 1fcd36d..e68bf66 100644 --- a/tests/test_eval.rs +++ b/tests/test_eval.rs @@ -15,6 +15,16 @@ fn it_evals_strings() { ctx.print_pipeline(pipeline).unwrap() } +#[test] +fn it_evals_print() { + let mut ctx = get_context(); + ctx.eval_raw( + r#"print "Hello World from this eval using print""#, + PipelineData::empty(), + ) + .unwrap(); +} + #[test] fn it_reports_parse_errors() { let mut ctx = get_context();