diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index dcdd5e231a..f10801310b 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -290,8 +290,8 @@ pub fn create_default_context(interactive: bool) -> Result, +pub async fn run_script_file( + file_contents: String, redirect_stdin: bool, ) -> Result<(), Box> { let mut syncer = EnvironmentSyncer::new(); @@ -313,9 +313,7 @@ pub async fn run_vec_of_pipelines( let _ = run_startup_commands(&mut context, &config).await; - for pipeline in pipelines { - run_pipeline_standalone(pipeline, redirect_stdin, &mut context, true).await?; - } + run_script_standalone(file_contents, redirect_stdin, &mut context, true).await?; Ok(()) } @@ -475,7 +473,7 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box> { } let line = match convert_rustyline_result_to_string(readline) { - LineResult::Success(s) => process_line(&s, &mut context, false, true).await, + LineResult::Success(s) => process_script(&s, &mut context, false, true).await, x => x, }; @@ -602,8 +600,7 @@ async fn run_startup_commands( } => { for pipeline in pipelines { if let Ok(pipeline_string) = pipeline.as_string() { - let _ = - run_pipeline_standalone(pipeline_string, false, context, false).await; + let _ = run_script_standalone(pipeline_string, false, context, false).await; } } } @@ -618,13 +615,13 @@ async fn run_startup_commands( Ok(()) } -pub async fn run_pipeline_standalone( - pipeline: String, +pub async fn run_script_standalone( + script_text: String, redirect_stdin: bool, context: &mut EvaluationContext, exit_on_error: bool, ) -> Result<(), Box> { - let line = process_line(&pipeline, context, redirect_stdin, false).await; + let line = process_script(&script_text, context, redirect_stdin, false).await; match line { LineResult::Success(line) => { @@ -892,16 +889,16 @@ pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result LineResult { - if line.trim() == "" { - LineResult::Success(line.to_string()) + if script_text.trim() == "" { + LineResult::Success(script_text.to_string()) } else { - let line = chomp_newline(line); + let line = chomp_newline(script_text); ctx.raw_input = line.to_string(); let (result, err) = nu_parser::lite_parse(&line, 0); @@ -930,11 +927,12 @@ pub async fn process_line( // ...then change to this directory if cli_mode && classified_block.block.block.len() == 1 - && classified_block.block.block[0].list.len() == 1 + && classified_block.block.block[0].pipelines.len() == 1 + && classified_block.block.block[0].pipelines[0].list.len() == 1 { if let ClassifiedCommand::Internal(InternalCommand { ref name, ref args, .. - }) = classified_block.block.block[0].list[0] + }) = classified_block.block.block[0].pipelines[0].list[0] { let internal_name = name; let name = args diff --git a/crates/nu-cli/src/commands/benchmark.rs b/crates/nu-cli/src/commands/benchmark.rs index 5991977fb9..7d7bc5c721 100644 --- a/crates/nu-cli/src/commands/benchmark.rs +++ b/crates/nu-cli/src/commands/benchmark.rs @@ -5,7 +5,7 @@ use crate::prelude::*; use heim::cpu::time; use nu_errors::ShellError; use nu_protocol::{ - hir::{Block, ClassifiedCommand, Commands, InternalCommand}, + hir::{Block, ClassifiedCommand, Group, InternalCommand, Pipeline}, Dictionary, Scope, Signature, SyntaxShape, UntaggedValue, Value, }; use rand::{ @@ -175,15 +175,19 @@ where fn add_implicit_autoview(mut block: Block) -> Block { if block.block.is_empty() { - block.push({ - let mut commands = Commands::new(block.span); - commands.push(ClassifiedCommand::Internal(InternalCommand::new( - "autoview".to_string(), - block.span, - block.span, - ))); - commands - }); + let group = Group::new( + vec![{ + let mut commands = Pipeline::new(block.span); + commands.push(ClassifiedCommand::Internal(InternalCommand::new( + "autoview".to_string(), + block.span, + block.span, + ))); + commands + }], + block.span, + ); + block.push(group); } block } diff --git a/crates/nu-cli/src/commands/classified/block.rs b/crates/nu-cli/src/commands/classified/block.rs index ee2aa282d1..9351c2e4a8 100644 --- a/crates/nu-cli/src/commands/classified/block.rs +++ b/crates/nu-cli/src/commands/classified/block.rs @@ -5,7 +5,9 @@ use crate::prelude::*; use crate::stream::InputStream; use futures::stream::TryStreamExt; use nu_errors::ShellError; -use nu_protocol::hir::{Block, ClassifiedCommand, Commands}; +use nu_protocol::hir::{ + Block, Call, ClassifiedCommand, Expression, Pipeline, SpannedExpression, Synthetic, +}; use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value}; use std::sync::atomic::Ordering; @@ -16,35 +18,52 @@ pub(crate) async fn run_block( scope: Arc, ) -> Result { let mut output: Result = Ok(InputStream::empty()); - for pipeline in &block.block { + for group in &block.block { match output { Ok(inp) if inp.is_empty() => {} Ok(inp) => { - let mut output_stream = inp.to_output_stream(); - - loop { - match output_stream.try_next().await { - Ok(Some(ReturnSuccess::Value(Value { - value: UntaggedValue::Error(e), - .. - }))) => return Err(e), - Ok(Some(_item)) => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); + // Run autoview on the values we've seen so far + // We may want to make this configurable for other kinds of hosting + if let Some(autoview) = ctx.get_command("autoview") { + let mut output_stream = ctx + .run_command( + autoview, + Tag::unknown(), + Call::new( + Box::new(SpannedExpression::new( + Expression::Synthetic(Synthetic::String("autoview".into())), + Span::unknown(), + )), + Span::unknown(), + ), + scope.clone(), + inp, + ) + .await?; + loop { + match output_stream.try_next().await { + Ok(Some(ReturnSuccess::Value(Value { + value: UntaggedValue::Error(e), + .. + }))) => return Err(e), + Ok(Some(_item)) => { + if let Some(err) = ctx.get_errors().get(0) { + ctx.clear_errors(); + return Err(err.clone()); + } + if ctx.ctrl_c.load(Ordering::SeqCst) { + break; + } } - if ctx.ctrl_c.load(Ordering::SeqCst) { + Ok(None) => { + if let Some(err) = ctx.get_errors().get(0) { + ctx.clear_errors(); + return Err(err.clone()); + } break; } + Err(e) => return Err(e), } - Ok(None) => { - if let Some(err) = ctx.get_errors().get(0) { - ctx.clear_errors(); - return Err(err.clone()); - } - break; - } - Err(e) => return Err(e), } } } @@ -52,16 +71,54 @@ pub(crate) async fn run_block( return Err(e); } } - output = run_pipeline(pipeline, ctx, input, scope.clone()).await; + output = Ok(InputStream::empty()); + for pipeline in &group.pipelines { + match output { + Ok(inp) if inp.is_empty() => {} + Ok(inp) => { + let mut output_stream = inp.to_output_stream(); - input = InputStream::empty(); + loop { + match output_stream.try_next().await { + Ok(Some(ReturnSuccess::Value(Value { + value: UntaggedValue::Error(e), + .. + }))) => return Err(e), + Ok(Some(_item)) => { + if let Some(err) = ctx.get_errors().get(0) { + ctx.clear_errors(); + return Err(err.clone()); + } + if ctx.ctrl_c.load(Ordering::SeqCst) { + break; + } + } + Ok(None) => { + if let Some(err) = ctx.get_errors().get(0) { + ctx.clear_errors(); + return Err(err.clone()); + } + break; + } + Err(e) => return Err(e), + } + } + } + Err(e) => { + return Err(e); + } + } + output = run_pipeline(pipeline, ctx, input, scope.clone()).await; + + input = InputStream::empty(); + } } output } async fn run_pipeline( - commands: &Commands, + commands: &Pipeline, ctx: &mut EvaluationContext, mut input: InputStream, scope: Arc, diff --git a/crates/nu-cli/src/commands/if_.rs b/crates/nu-cli/src/commands/if_.rs index 8cfb9d1d6d..1a1a13a621 100644 --- a/crates/nu-cli/src/commands/if_.rs +++ b/crates/nu-cli/src/commands/if_.rs @@ -94,9 +94,9 @@ async fn if_command( tag, )); } - match condition.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match condition.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/commands/keep/until.rs b/crates/nu-cli/src/commands/keep/until.rs index c158dfea0b..c15bc58d8a 100644 --- a/crates/nu-cli/src/commands/keep/until.rs +++ b/crates/nu-cli/src/commands/keep/until.rs @@ -51,9 +51,9 @@ impl WholeStreamCommand for SubCommand { tag, )); } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match block.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/commands/keep/while_.rs b/crates/nu-cli/src/commands/keep/while_.rs index aee76a23b2..528b2270ba 100644 --- a/crates/nu-cli/src/commands/keep/while_.rs +++ b/crates/nu-cli/src/commands/keep/while_.rs @@ -50,9 +50,9 @@ impl WholeStreamCommand for SubCommand { tag, )); } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match block.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/commands/skip/until.rs b/crates/nu-cli/src/commands/skip/until.rs index c99d4feebf..d3215753e6 100644 --- a/crates/nu-cli/src/commands/skip/until.rs +++ b/crates/nu-cli/src/commands/skip/until.rs @@ -50,9 +50,9 @@ impl WholeStreamCommand for SubCommand { tag, )); } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match block.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/commands/skip/while_.rs b/crates/nu-cli/src/commands/skip/while_.rs index d0f8167bc9..bb93ac12e7 100644 --- a/crates/nu-cli/src/commands/skip/while_.rs +++ b/crates/nu-cli/src/commands/skip/while_.rs @@ -50,9 +50,9 @@ impl WholeStreamCommand for SubCommand { tag, )); } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match block.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/commands/where_.rs b/crates/nu-cli/src/commands/where_.rs index 7bd3e4d11c..e2c1ab8a95 100644 --- a/crates/nu-cli/src/commands/where_.rs +++ b/crates/nu-cli/src/commands/where_.rs @@ -81,9 +81,9 @@ async fn where_command( tag, )); } - match block.block[0].list.get(0) { - Some(item) => match item { - ClassifiedCommand::Expr(expr) => expr.clone(), + match block.block[0].pipelines.get(0) { + Some(item) => match item.list.get(0) { + Some(ClassifiedCommand::Expr(expr)) => expr.clone(), _ => { return Err(ShellError::labeled_error( "Expected a condition", diff --git a/crates/nu-cli/src/completion/engine.rs b/crates/nu-cli/src/completion/engine.rs index 09bcb19093..969407f0d9 100644 --- a/crates/nu-cli/src/completion/engine.rs +++ b/crates/nu-cli/src/completion/engine.rs @@ -138,7 +138,7 @@ impl<'s> Flatten<'s> { result } - fn pipeline(&self, pipeline: &Commands) -> Vec { + fn pipeline(&self, pipeline: &Pipeline) -> Vec { let mut result = Vec::new(); for command in &pipeline.list { @@ -158,7 +158,11 @@ impl<'s> Flatten<'s> { /// Flattens the block into a Vec of completion locations pub fn completion_locations(&self, block: &Block) -> Vec { - block.block.iter().flat_map(|v| self.pipeline(v)).collect() + block + .block + .iter() + .flat_map(|g| g.pipelines.iter().flat_map(|v| self.pipeline(v))) + .collect() } pub fn new(line: &'s str) -> Flatten<'s> { diff --git a/crates/nu-cli/src/lib.rs b/crates/nu-cli/src/lib.rs index 241bc300e7..2a314f309a 100644 --- a/crates/nu-cli/src/lib.rs +++ b/crates/nu-cli/src/lib.rs @@ -43,8 +43,8 @@ mod examples; pub use crate::cli::cli; pub use crate::cli::{ - create_default_context, parse_and_eval, process_line, register_plugins, - run_pipeline_standalone, run_vec_of_pipelines, LineResult, + create_default_context, parse_and_eval, process_script, register_plugins, run_script_file, + run_script_standalone, LineResult, }; pub use crate::command_registry::CommandRegistry; pub use crate::commands::command::{ diff --git a/crates/nu-cli/src/types/deduction.rs b/crates/nu-cli/src/types/deduction.rs index 3aea91a21e..7c1d836f40 100644 --- a/crates/nu-cli/src/types/deduction.rs +++ b/crates/nu-cli/src/types/deduction.rs @@ -5,8 +5,8 @@ use nu_errors::ShellError; use nu_parser::SignatureRegistry; use nu_protocol::{ hir::{ - Binary, Block, ClassifiedCommand, Commands, Expression, Literal, NamedArguments, - NamedValue, Operator, SpannedExpression, + Binary, Block, ClassifiedCommand, Expression, Literal, NamedArguments, NamedValue, + Operator, Pipeline, SpannedExpression, }, NamedType, PositionalType, Signature, SyntaxShape, }; @@ -318,7 +318,7 @@ fn spanned_to_binary(bin_spanned: &SpannedExpression) -> &Binary { ///Returns result shape of this math expr otherwise fn get_result_shape_of_math_expr( bin: &Binary, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), registry: &CommandRegistry, ) -> Result, ShellError> { let mut shapes: Vec> = vec![]; @@ -388,15 +388,17 @@ impl VarSyntaxShapeDeductor { fn infer_shape(&mut self, block: &Block, registry: &CommandRegistry) -> Result<(), ShellError> { trace!("Infering vars in shape"); - for pipeline in &block.block { - self.infer_pipeline(pipeline, registry)?; + for group in &block.block { + for pipeline in &group.pipelines { + self.infer_pipeline(pipeline, registry)?; + } } Ok(()) } pub fn infer_pipeline( &mut self, - pipeline: &Commands, + pipeline: &Pipeline, registry: &CommandRegistry, ) -> Result<(), ShellError> { trace!("Infering vars in pipeline"); @@ -534,7 +536,7 @@ impl VarSyntaxShapeDeductor { fn infer_shapes_in_expr( &mut self, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), spanned_expr: &SpannedExpression, registry: &CommandRegistry, ) -> Result<(), ShellError> { @@ -660,7 +662,7 @@ impl VarSyntaxShapeDeductor { (var, expr): (&VarUsage, &SpannedExpression), //source_bin is binary having var on one and expr on other side source_bin: &SpannedExpression, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), registry: &CommandRegistry, ) -> Result, ShellError> { get_result_shape_of_math_expr(spanned_to_binary(expr), (pipeline_idx, pipeline), registry) @@ -682,7 +684,7 @@ impl VarSyntaxShapeDeductor { (var, expr): (&VarUsage, &SpannedExpression), //source_bin is binary having var on one and expr on other side source_bin: &SpannedExpression, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), registry: &CommandRegistry, ) -> Result, ShellError> { trace!("Getting shape of binary arg {:?} for var {:?}", expr, var); @@ -714,7 +716,7 @@ impl VarSyntaxShapeDeductor { var: &VarUsage, bin_spanned: &SpannedExpression, list: &[SpannedExpression], - (_pipeline_idx, _pipeline): (usize, &Commands), + (_pipeline_idx, _pipeline): (usize, &Pipeline), _registry: &CommandRegistry, ) -> Option> { let shapes_in_list = list @@ -740,7 +742,7 @@ impl VarSyntaxShapeDeductor { var_side: BinarySide, //Binary having expr on one side and var on other bin_spanned: &SpannedExpression, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), registry: &CommandRegistry, ) -> Result<(), ShellError> { trace!("Infering shapes between var {:?} and expr {:?}", var, expr); @@ -893,7 +895,7 @@ impl VarSyntaxShapeDeductor { fn infer_shapes_in_binary_expr( &mut self, - (pipeline_idx, pipeline): (usize, &Commands), + (pipeline_idx, pipeline): (usize, &Pipeline), bin_spanned: &SpannedExpression, registry: &CommandRegistry, ) -> Result<(), ShellError> { diff --git a/crates/nu-parser/src/lite_parse.rs b/crates/nu-parser/src/lite_parse.rs index d2a3b7eefc..350f9e0f53 100644 --- a/crates/nu-parser/src/lite_parse.rs +++ b/crates/nu-parser/src/lite_parse.rs @@ -117,6 +117,17 @@ impl LiteGroup { pub fn push(&mut self, item: LitePipeline) { self.pipelines.push(item) } + pub fn is_comment(&self) -> bool { + if !self.is_empty() + && !self.pipelines[0].is_empty() + && !self.pipelines[0].commands.is_empty() + && !self.pipelines[0].commands[0].parts.is_empty() + { + self.pipelines[0].commands[0].parts[0].item.starts_with('#') + } else { + false + } + } pub(crate) fn span(&self) -> Span { let start = if !self.pipelines.is_empty() { self.pipelines[0].span().start() @@ -348,7 +359,9 @@ fn group(tokens: Vec) -> (LiteBlock, Option) { pipeline = LitePipeline::new(); } if !group.is_empty() { - groups.push(group); + if !group.is_comment() { + groups.push(group); + } group = LiteGroup::new(); } } @@ -389,7 +402,7 @@ fn group(tokens: Vec) -> (LiteBlock, Option) { if !pipeline.is_empty() { group.push(pipeline); } - if !group.is_empty() { + if !group.is_empty() && !group.is_comment() { groups.push(group); } diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index bad8fdc159..59002084d2 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -3,9 +3,9 @@ use std::path::Path; use log::trace; use nu_errors::{ArgumentError, ParseError}; use nu_protocol::hir::{ - self, Binary, Block, ClassifiedBlock, ClassifiedCommand, ClassifiedPipeline, Commands, - Expression, ExternalRedirection, Flag, FlagKind, InternalCommand, Member, NamedArguments, - Operator, RangeOperator, SpannedExpression, Unit, + self, Binary, Block, ClassifiedBlock, ClassifiedCommand, ClassifiedPipeline, Expression, + ExternalRedirection, Flag, FlagKind, Group, InternalCommand, Member, NamedArguments, Operator, + Pipeline, RangeOperator, SpannedExpression, Unit, }; use nu_protocol::{NamedType, PositionalType, Signature, SyntaxShape, UnspannedPathMember}; use nu_source::{Span, Spanned, SpannedItem}; @@ -584,7 +584,7 @@ fn parse_interpolated_string( } } - let block = vec![Commands { + let pipelines = vec![Pipeline { span: lite_arg.span, list: vec![ClassifiedCommand::Internal(InternalCommand { name: "build-string".to_owned(), @@ -602,8 +602,10 @@ fn parse_interpolated_string( })], }]; + let group = Group::new(pipelines, lite_arg.span); + let call = SpannedExpression { - expr: Expression::Invocation(Block::new(vec![], block, lite_arg.span)), + expr: Expression::Invocation(Block::new(vec![], vec![group], lite_arg.span)), span: lite_arg.span, }; @@ -1341,10 +1343,14 @@ fn parse_positional_argument( parse_math_expression(idx, &lite_cmd.parts[idx..end_idx], registry, true); let span = arg.span; - let mut commands = hir::Commands::new(span); + let mut commands = hir::Pipeline::new(span); commands.push(ClassifiedCommand::Expr(Box::new(arg))); - let block = hir::Block::new(vec![], vec![commands], span); + let block = hir::Block::new( + vec![], + vec![Group::new(vec![commands], lite_cmd.span())], + span, + ); let arg = SpannedExpression::new(Expression::Block(block), span); @@ -1538,7 +1544,7 @@ fn classify_pipeline( lite_pipeline: &LitePipeline, registry: &dyn SignatureRegistry, ) -> (ClassifiedPipeline, Option) { - let mut commands = Commands::new(lite_pipeline.span()); + let mut commands = Pipeline::new(lite_pipeline.span()); let mut error = None; let mut iter = lite_pipeline.commands.iter().peekable(); @@ -1745,10 +1751,10 @@ fn expand_shorthand_forms( } pub fn classify_block(lite_block: &LiteBlock, registry: &dyn SignatureRegistry) -> ClassifiedBlock { - let mut command_list = vec![]; - + let mut block = vec![]; let mut error = None; for lite_group in &lite_block.block { + let mut command_list = vec![]; for lite_pipeline in &lite_group.pipelines { let (lite_pipeline, vars, err) = expand_shorthand_forms(lite_pipeline); if error.is_none() { @@ -1759,7 +1765,8 @@ pub fn classify_block(lite_block: &LiteBlock, registry: &dyn SignatureRegistry) let pipeline = if let Some(vars) = vars { let span = pipeline.commands.span; - let block = hir::Block::new(vec![], vec![pipeline.commands.clone()], span); + let group = Group::new(vec![pipeline.commands.clone()], span); + let block = hir::Block::new(vec![], vec![group], span); let mut call = hir::Call::new( Box::new(SpannedExpression { expr: Expression::string("with-env".to_string()), @@ -1792,7 +1799,7 @@ pub fn classify_block(lite_block: &LiteBlock, registry: &dyn SignatureRegistry) args: call, }); ClassifiedPipeline { - commands: Commands { + commands: Pipeline { list: vec![classified_with_env], span, }, @@ -1806,8 +1813,10 @@ pub fn classify_block(lite_block: &LiteBlock, registry: &dyn SignatureRegistry) error = err; } } + let group = Group::new(command_list, lite_block.span()); + block.push(group); } - let block = Block::new(vec![], command_list, lite_block.span()); + let block = Block::new(vec![], block, lite_block.span()); ClassifiedBlock::new(block, error) } diff --git a/crates/nu-parser/src/shapes.rs b/crates/nu-parser/src/shapes.rs index e8c5322237..2e514ab3f7 100644 --- a/crates/nu-parser/src/shapes.rs +++ b/crates/nu-parser/src/shapes.rs @@ -88,35 +88,39 @@ pub fn expression_to_flat_shape(e: &SpannedExpression) -> Vec pub fn shapes(commands: &Block) -> Vec> { let mut output = vec![]; - for pipeline in &commands.block { - for command in &pipeline.list { - match command { - ClassifiedCommand::Internal(internal) => { - output.append(&mut expression_to_flat_shape(&internal.args.head)); + for group in &commands.block { + for pipeline in &group.pipelines { + for command in &pipeline.list { + match command { + ClassifiedCommand::Internal(internal) => { + output.append(&mut expression_to_flat_shape(&internal.args.head)); - if let Some(positionals) = &internal.args.positional { - for positional_arg in positionals { - output.append(&mut expression_to_flat_shape(positional_arg)); + if let Some(positionals) = &internal.args.positional { + for positional_arg in positionals { + output.append(&mut expression_to_flat_shape(positional_arg)); + } } - } - if let Some(named) = &internal.args.named { - for (_, named_arg) in named.iter() { - match named_arg { - NamedValue::PresentSwitch(span) => { - output.push(FlatShape::Flag.spanned(*span)); + if let Some(named) = &internal.args.named { + for (_, named_arg) in named.iter() { + match named_arg { + NamedValue::PresentSwitch(span) => { + output.push(FlatShape::Flag.spanned(*span)); + } + NamedValue::Value(span, expr) => { + output.push(FlatShape::Flag.spanned(*span)); + output.append(&mut expression_to_flat_shape(expr)); + } + _ => {} } - NamedValue::Value(span, expr) => { - output.push(FlatShape::Flag.spanned(*span)); - output.append(&mut expression_to_flat_shape(expr)); - } - _ => {} } } } + ClassifiedCommand::Expr(expr) => { + output.append(&mut expression_to_flat_shape(expr)) + } + _ => {} } - ClassifiedCommand::Expr(expr) => output.append(&mut expression_to_flat_shape(expr)), - _ => {} } } } diff --git a/crates/nu-protocol/src/hir.rs b/crates/nu-protocol/src/hir.rs index 20fcd8b30e..06ec7a2349 100644 --- a/crates/nu-protocol/src/hir.rs +++ b/crates/nu-protocol/src/hir.rs @@ -62,11 +62,11 @@ impl ClassifiedBlock { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] pub struct ClassifiedPipeline { - pub commands: Commands, + pub commands: Pipeline, } impl ClassifiedPipeline { - pub fn new(commands: Commands) -> ClassifiedPipeline { + pub fn new(commands: Pipeline) -> ClassifiedPipeline { ClassifiedPipeline { commands } } } @@ -92,14 +92,14 @@ impl ClassifiedCommand { } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] -pub struct Commands { +pub struct Pipeline { pub list: Vec, pub span: Span, } -impl Commands { - pub fn new(span: Span) -> Commands { - Commands { list: vec![], span } +impl Pipeline { + pub fn new(span: Span) -> Pipeline { + Pipeline { list: vec![], span } } pub fn push(&mut self, command: ClassifiedCommand) { @@ -111,15 +111,34 @@ impl Commands { } } +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] +pub struct Group { + pub pipelines: Vec, + pub span: Span, +} +impl Group { + pub fn new(pipelines: Vec, span: Span) -> Group { + Group { pipelines, span } + } + + pub fn push(&mut self, pipeline: Pipeline) { + self.pipelines.push(pipeline); + } + + pub fn has_it_usage(&self) -> bool { + self.pipelines.iter().any(|cc| cc.has_it_usage()) + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] pub struct Block { pub params: Vec, - pub block: Vec, + pub block: Vec, pub span: Span, } impl Block { - pub fn new(params: Vec, block: Vec, span: Span) -> Block { + pub fn new(params: Vec, block: Vec, span: Span) -> Block { let mut output = Block { params, block, @@ -130,16 +149,18 @@ impl Block { output } - pub fn push(&mut self, commands: Commands) { - self.block.push(commands); + pub fn push(&mut self, group: Group) { + self.block.push(group); self.infer_params(); } pub fn set_redirect(&mut self, external_redirection: ExternalRedirection) { - if let Some(pipeline) = self.block.last_mut() { - if let Some(command) = pipeline.list.last_mut() { - if let ClassifiedCommand::Internal(internal) = command { - internal.args.external_redirection = external_redirection; + if let Some(group) = self.block.last_mut() { + if let Some(pipeline) = group.pipelines.last_mut() { + if let Some(command) = pipeline.list.last_mut() { + if let ClassifiedCommand::Internal(internal) = command { + internal.args.external_redirection = external_redirection; + } } } } diff --git a/src/main.rs b/src/main.rs index de80711205..2d881a7fa7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use nu_cli::create_default_context; use nu_cli::utils::test_bins as binaries; use std::error::Error; use std::fs::File; -use std::io::{prelude::*, BufReader}; +use std::io::prelude::*; fn main() -> Result<(), Box> { let matches = App::new("nushell") @@ -124,9 +124,12 @@ fn main() -> Result<(), Box> { match matches.values_of("commands") { None => {} Some(values) => { - let pipelines: Vec = values.map(|x| x.to_string()).collect(); - futures::executor::block_on(nu_cli::run_vec_of_pipelines( - pipelines, + let script_text: String = values + .map(|x| x.to_string()) + .collect::>() + .join("\n"); + futures::executor::block_on(nu_cli::run_script_file( + script_text, matches.is_present("stdin"), ))?; return Ok(()); @@ -135,25 +138,12 @@ fn main() -> Result<(), Box> { match matches.value_of("script") { Some(script) => { - let file = File::open(script)?; - let reader = BufReader::new(file); - let pipelines: Vec = reader - .lines() - .filter_map(|x| { - if let Ok(x) = x { - if !x.starts_with('#') { - Some(x) - } else { - None - } - } else { - None - } - }) - .collect(); + let mut file = File::open(script)?; + let mut buffer = String::new(); + file.read_to_string(&mut buffer)?; - futures::executor::block_on(nu_cli::run_vec_of_pipelines( - pipelines, + futures::executor::block_on(nu_cli::run_script_file( + buffer, matches.is_present("stdin"), ))?; return Ok(());