From 1d945d8ce3681d93021a1e1fdb898647729db69d Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Sat, 11 Sep 2021 00:54:24 -0400 Subject: [PATCH 01/24] added source command --- crates/nu-command/Cargo.toml | 3 +- crates/nu-command/src/default_context.rs | 4 +- crates/nu-command/src/lib.rs | 2 + crates/nu-command/src/source.rs | 117 +++++++++++++++++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 crates/nu-command/src/source.rs diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 6cc6ae2f63..1d64aca4d4 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] nu-protocol = { path = "../nu-protocol" } -nu-engine = { path = "../nu-engine" } \ No newline at end of file +nu-engine = { path = "../nu-engine" } +nu-parser = {path = "../nu-parser"} \ No newline at end of file diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index fbaaaf537b..a9278dcc08 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -5,7 +5,7 @@ use nu_protocol::{ Signature, SyntaxShape, }; -use crate::{Alias, Benchmark, BuildString, Def, Do, Each, For, If, Length, Let, LetEnv}; +use crate::{Alias, Benchmark, BuildString, Def, Do, Each, For, If, Length, Let, LetEnv, Source}; pub fn create_default_context() -> Rc> { let engine_state = Rc::new(RefCell::new(EngineState::new())); @@ -39,6 +39,8 @@ pub fn create_default_context() -> Rc> { working_set.add_decl(Box::new(Length)); + working_set.add_decl(Box::new(Source)); + let sig = Signature::build("exit"); working_set.add_decl(sig.predeclare()); let sig = Signature::build("vars"); diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 3e7d99e7d7..dad3122926 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -10,6 +10,7 @@ mod if_; mod length; mod let_; mod let_env; +mod source; pub use alias::Alias; pub use benchmark::Benchmark; @@ -23,3 +24,4 @@ pub use if_::If; pub use length::Length; pub use let_::Let; pub use let_env::LetEnv; +pub use source::Source; diff --git a/crates/nu-command/src/source.rs b/crates/nu-command/src/source.rs new file mode 100644 index 0000000000..b50c7bfca9 --- /dev/null +++ b/crates/nu-command/src/source.rs @@ -0,0 +1,117 @@ +use nu_engine::{eval_block, eval_expression}; +use nu_parser::parse; +use nu_protocol::ast::{Block, Call}; +use nu_protocol::engine::{Command, EngineState, EvaluationContext, StateWorkingSet}; +use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; +use std::task::Context; +use std::{borrow::Cow, path::Path, path::PathBuf}; + +/// Source a file for environment variables. +pub struct Source; + +impl Command for Source { + fn name(&self) -> &str { + "source" + } + + fn signature(&self) -> Signature { + Signature::build("source").required( + "filename", + SyntaxShape::FilePath, + "the filepath to the script file to source", + ) + } + + fn usage(&self) -> &str { + "Runs a script file in the current context." + } + + fn run( + &self, + _context: &EvaluationContext, + call: &Call, + input: Value, + ) -> Result { + source(_context, call, input) + } +} + +pub fn source(ctx: &EvaluationContext, call: &Call, input: Value) -> Result { + let filename = call.positional[0] + .as_string() + .expect("internal error: missing file name"); + + let source_file = Path::new(&filename); + + // This code is in the current Nushell version + // ...Not entirely sure what it's doing or if there's an equivalent in engine-q + + // Note: this is a special case for setting the context from a command + // In this case, if we don't set it now, we'll lose the scope that this + // variable should be set into. + + // let lib_dirs = &ctx + // .configs() + // .lock() + // .global_config + // .as_ref() + // .map(|configuration| match configuration.var("lib_dirs") { + // Some(paths) => paths + // .table_entries() + // .cloned() + // .map(|path| path.as_string()) + // .collect(), + // None => vec![], + // }); + + // if let Some(dir) = lib_dirs { + // for lib_path in dir { + // match lib_path { + // Ok(name) => { + // let path = PathBuf::from(name).join(source_file); + + // if let Ok(contents) = + // std::fs::read_to_string(&expand_path(Cow::Borrowed(path.as_path()))) + // { + // let result = script::run_script_standalone(contents, true, ctx, false); + + // if let Err(err) = result { + // ctx.error(err); + // } + // return Ok(OutputStream::empty()); + // } + // } + // Err(reason) => { + // ctx.error(reason.clone()); + // } + // } + // } + // } + + // This is to stay consistent w/ the code taken from nushell + let path = source_file; + + let contents = std::fs::read(path); + + match contents { + Ok(contents) => { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + + let (block, err) = parse(&mut working_set, None, &contents, true); + if let Some(e) = err { + // Be more specific here: need to convert parse error to string + Err(ShellError::InternalError("Parse error in file".to_string())) + } else { + let result = eval_block(ctx, &block, input); + match result { + Err(e) => Err(e), + _ => Ok(Value::nothing()), + } + } + } + Err(_) => Err(ShellError::InternalError( + "Can't load file to source".to_string(), + )), + } +} From 719920fa37ee9bd9210f5a46eeaf32a2292c706c Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Mon, 27 Sep 2021 08:10:18 -0400 Subject: [PATCH 02/24] tried to move source command into parser (still doesn't compile) --- Cargo.lock | 1 + crates/nu-command/src/source.rs | 2 +- crates/nu-engine/src/eval.rs | 15 +++- crates/nu-parser/src/parser.rs | 108 +++++++++++++++++++++++++- crates/nu-protocol/src/value/mod.rs | 1 + crates/nu-protocol/src/value/range.rs | 1 + example.nu | 1 + 7 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 example.nu diff --git a/Cargo.lock b/Cargo.lock index 8948993d4c..acfbf68bc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,7 @@ name = "nu-command" version = "0.1.0" dependencies = [ "nu-engine", + "nu-parser", "nu-protocol", ] diff --git a/crates/nu-command/src/source.rs b/crates/nu-command/src/source.rs index b50c7bfca9..1997bbea82 100644 --- a/crates/nu-command/src/source.rs +++ b/crates/nu-command/src/source.rs @@ -101,7 +101,7 @@ pub fn source(ctx: &EvaluationContext, call: &Call, input: Value) -> Result Result { @@ -239,3 +240,15 @@ pub fn eval_block( Ok(input) } + +// pub fn eval(context: &EvaluationContext, script: &str) -> Result { +// let engine_state = EngineState::new(); +// let mut working_set = StateWorkingSet::new(&engine_state); + +// let (block, err) = parse(&mut working_set, None, b"3", true); +// if let Some(e) = err { +// Err(e) +// } else { +// eval_block(context, &block, Value::nothing()) +// } +// } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 86271281be..cab66c3e8d 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use crate::{ lex, lite_parse, type_check::{math_result_type, type_compatible}, @@ -10,7 +12,7 @@ use nu_protocol::{ RangeInclusion, RangeOperator, Statement, }, engine::StateWorkingSet, - span, Flag, PositionalArg, Signature, Span, SyntaxShape, Type, VarId, + span, Flag, PositionalArg, ShellError, Signature, Span, SyntaxShape, Type, VarId, }; #[derive(Debug, Clone)] @@ -2299,6 +2301,7 @@ pub fn parse_def_predecl(working_set: &mut StateWorkingSet, spans: &[Span]) { } } +/// Parser for the def command pub fn parse_def( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2381,6 +2384,7 @@ pub fn parse_def( } } +/// Parser for the alias command pub fn parse_alias( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2436,6 +2440,7 @@ pub fn parse_alias( ) } +/// Parse let command pub fn parse_let( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2480,6 +2485,105 @@ pub fn parse_let( ) } +/// Parser for the source command +pub fn parse_source( + working_set: &mut StateWorkingSet, + spans: &[Span], +) -> (Statement, Option) { + let mut error = None; + let name = working_set.get_span_contents(spans[0]); + + if name == b"source" { + let (name_expr, err) = parse_string(working_set, spans[1]); + error = error.or(err); + + if let Some(filename) = name_expr.as_string() { + let source_file = Path::new(&filename); + // This is to stay consistent w/ the code taken from nushell + let path = source_file; + + let contents = std::fs::read(path); + + match contents { + Ok(contents) => { + let (block, err) = parse( + &mut working_set, + path.file_name().and_then(|x| x.to_str()), + &contents, + true, + ); + if let Some(e) = err { + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }])), + err, + ) + } else { + let block_id = working_set.add_block(block); + ( + // Why creating a pipeline here for only one expression? + // Is there a way to only make this a declaration? + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Subexpression(block_id), + span: span(spans), + ty: Type::Unknown, // FIXME + }])), + None, + ) + } + } + Err(e) => ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }])), + Some(ParseError::UnknownState(e.into(), span(spans))), + ), //(ShellError::InternalError("Can't load file to source".to_string())), + } + } else { + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }])), + Some(ParseError::Mismatch( + "string".into(), + // Can this be better? + "incompatible string".into(), + spans[1], + )), + ) + } + } else { + // Not source command? + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }])), + error, + ) + } + // ( + // Statement::Pipeline(Pipeline::from_vec(vec![Expression { + // expr: Expr::Garbage, + // span: span(spans), + // ty: Type::Unknown, + // }])), + // Some(ParseError::UnknownState( + // "internal error: let statement unparseable".into(), + // span(spans), + // )), + // ) +} + +/// Parse a statement. Check if def, let, alias, or source command can process it properly pub fn parse_statement( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2491,6 +2595,8 @@ pub fn parse_statement( (stmt, None) } else if let (stmt, None) = parse_alias(working_set, spans) { (stmt, None) + } else if let (decl, None) = parse_source(working_set, spans) { + (decl, None) } else { let (expr, err) = parse_expression(working_set, spans); (Statement::Pipeline(Pipeline::from_vec(vec![expr])), err) diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index d02f1ce2d4..815a0fabfd 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -179,6 +179,7 @@ impl Value { } } + /// Follow a given column path into the value: for example accessing nth elements in a stream or list pub fn follow_cell_path(self, column_path: &[PathMember]) -> Result { let mut current = self; for member in column_path { diff --git a/crates/nu-protocol/src/value/range.rs b/crates/nu-protocol/src/value/range.rs index 54d836de16..6c7de36166 100644 --- a/crates/nu-protocol/src/value/range.rs +++ b/crates/nu-protocol/src/value/range.rs @@ -1,5 +1,6 @@ use crate::{ast::RangeInclusion, *}; +/// A Range is an iterator over integers. #[derive(Debug, Clone, PartialEq)] pub struct Range { pub from: Value, diff --git a/example.nu b/example.nu new file mode 100644 index 0000000000..a157d1a3ce --- /dev/null +++ b/example.nu @@ -0,0 +1 @@ +length [1,2,3,4] \ No newline at end of file From 2b5ef1b2d7bbc4c68ac686578994bd5518361a7a Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Mon, 27 Sep 2021 08:10:45 -0400 Subject: [PATCH 03/24] Removed extra file --- crates/nu-command/src/source.rs | 139 ++++++++++++++++---------------- example.nu | 1 - 2 files changed, 70 insertions(+), 70 deletions(-) delete mode 100644 example.nu diff --git a/crates/nu-command/src/source.rs b/crates/nu-command/src/source.rs index 1997bbea82..566c898ef5 100644 --- a/crates/nu-command/src/source.rs +++ b/crates/nu-command/src/source.rs @@ -32,86 +32,87 @@ impl Command for Source { call: &Call, input: Value, ) -> Result { - source(_context, call, input) + Ok(Value::Nothing { span: call.head }) + // source(_context, call, input) } } -pub fn source(ctx: &EvaluationContext, call: &Call, input: Value) -> Result { - let filename = call.positional[0] - .as_string() - .expect("internal error: missing file name"); +// pub fn source(ctx: &EvaluationContext, call: &Call, input: Value) -> Result { +// let filename = call.positional[0] +// .as_string() +// .expect("internal error: missing file name"); - let source_file = Path::new(&filename); +// let source_file = Path::new(&filename); - // This code is in the current Nushell version - // ...Not entirely sure what it's doing or if there's an equivalent in engine-q +// // This code is in the current Nushell version +// // ...Not entirely sure what it's doing or if there's an equivalent in engine-q - // Note: this is a special case for setting the context from a command - // In this case, if we don't set it now, we'll lose the scope that this - // variable should be set into. +// // Note: this is a special case for setting the context from a command +// // In this case, if we don't set it now, we'll lose the scope that this +// // variable should be set into. - // let lib_dirs = &ctx - // .configs() - // .lock() - // .global_config - // .as_ref() - // .map(|configuration| match configuration.var("lib_dirs") { - // Some(paths) => paths - // .table_entries() - // .cloned() - // .map(|path| path.as_string()) - // .collect(), - // None => vec![], - // }); +// // let lib_dirs = &ctx +// // .configs() +// // .lock() +// // .global_config +// // .as_ref() +// // .map(|configuration| match configuration.var("lib_dirs") { +// // Some(paths) => paths +// // .table_entries() +// // .cloned() +// // .map(|path| path.as_string()) +// // .collect(), +// // None => vec![], +// // }); - // if let Some(dir) = lib_dirs { - // for lib_path in dir { - // match lib_path { - // Ok(name) => { - // let path = PathBuf::from(name).join(source_file); +// // if let Some(dir) = lib_dirs { +// // for lib_path in dir { +// // match lib_path { +// // Ok(name) => { +// // let path = PathBuf::from(name).join(source_file); - // if let Ok(contents) = - // std::fs::read_to_string(&expand_path(Cow::Borrowed(path.as_path()))) - // { - // let result = script::run_script_standalone(contents, true, ctx, false); +// // if let Ok(contents) = +// // std::fs::read_to_string(&expand_path(Cow::Borrowed(path.as_path()))) +// // { +// // let result = script::run_script_standalone(contents, true, ctx, false); - // if let Err(err) = result { - // ctx.error(err); - // } - // return Ok(OutputStream::empty()); - // } - // } - // Err(reason) => { - // ctx.error(reason.clone()); - // } - // } - // } - // } +// // if let Err(err) = result { +// // ctx.error(err); +// // } +// // return Ok(OutputStream::empty()); +// // } +// // } +// // Err(reason) => { +// // ctx.error(reason.clone()); +// // } +// // } +// // } +// // } - // This is to stay consistent w/ the code taken from nushell - let path = source_file; +// // This is to stay consistent w/ the code taken from nushell +// let path = source_file; - let contents = std::fs::read(path); +// let contents = std::fs::read(path); - match contents { - Ok(contents) => { - let engine_state = EngineState::new(); - let mut working_set = StateWorkingSet::new(&engine_state); +// match contents { +// Ok(contents) => { +// let engine_state = EngineState::new(); +// let mut working_set = StateWorkingSet::new(&engine_state); - let (block, err) = parse(&mut working_set, None, &contents, true); - if let Some(e) = err { - // Be more specific here: need to convert parse error to string - Err(e.into()) - } else { - let result = eval_block(ctx, &block, input); - match result { - Err(e) => Err(e), - _ => Ok(Value::nothing()), - } - } - } - Err(_) => Err(ShellError::InternalError( - "Can't load file to source".to_string(), - )), - } -} +// let (block, err) = parse(&mut working_set, None, &contents, true); +// if let Some(e) = err { +// // Be more specific here: need to convert parse error to string +// Err(e.into()) +// } else { +// let result = eval_block(ctx, &block, input); +// match result { +// Err(e) => Err(e), +// _ => Ok(Value::nothing()), +// } +// } +// } +// Err(_) => Err(ShellError::InternalError( +// "Can't load file to source".to_string(), +// )), +// } +// } diff --git a/example.nu b/example.nu deleted file mode 100644 index a157d1a3ce..0000000000 --- a/example.nu +++ /dev/null @@ -1 +0,0 @@ -length [1,2,3,4] \ No newline at end of file From e00755a2e9dac3679f5ab6c1fa701d584d545251 Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Thu, 30 Sep 2021 23:04:56 -0400 Subject: [PATCH 04/24] fix compile errors --- Cargo.lock | 24 +++---- crates/nu-parser/src/parser.rs | 128 +++++++++++++-------------------- 2 files changed, 63 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acfbf68bc9..a9b6b51227 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" dependencies = [ "cfg-if", ] @@ -190,9 +190,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.101" +version = "0.2.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" [[package]] name = "lock_api" @@ -477,8 +477,8 @@ dependencies = [ [[package]] name = "reedline" -version = "0.1.0" -source = "git+https://github.com/jntrnr/reedline?branch=main#cd87851ad9f238b491062bb854d65489ca2c4c1c" +version = "0.2.0" +source = "git+https://github.com/jntrnr/reedline?branch=main#93c2146fcf4257c40426bc2f0c6903d4115caaf1" dependencies = [ "chrono", "crossterm", @@ -567,9 +567,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "syn" -version = "1.0.76" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" +checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" dependencies = [ "proc-macro2", "quote", @@ -624,9 +624,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index cab66c3e8d..38b5123763 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2490,97 +2490,71 @@ pub fn parse_source( working_set: &mut StateWorkingSet, spans: &[Span], ) -> (Statement, Option) { - let mut error = None; let name = working_set.get_span_contents(spans[0]); if name == b"source" { - let (name_expr, err) = parse_string(working_set, spans[1]); - error = error.or(err); + if let Some(decl_id) = working_set.find_decl(b"source") { + let (call, call_span, _) = + parse_internal_call(working_set, spans[0], &spans[1..], decl_id); - if let Some(filename) = name_expr.as_string() { - let source_file = Path::new(&filename); - // This is to stay consistent w/ the code taken from nushell - let path = source_file; + // Command and one file name + if spans.len() >= 2 { + let name_expr = working_set.get_span_contents(spans[1]); + if let Ok(filename) = String::from_utf8(name_expr.to_vec()) { + let source_file = Path::new(&filename); - let contents = std::fs::read(path); + let path = source_file; + let contents = std::fs::read(path); - match contents { - Ok(contents) => { - let (block, err) = parse( - &mut working_set, - path.file_name().and_then(|x| x.to_str()), - &contents, - true, - ); - if let Some(e) = err { - ( - Statement::Pipeline(Pipeline::from_vec(vec![Expression { - expr: Expr::Garbage, - span: span(spans), - ty: Type::Unknown, - }])), - err, - ) - } else { - let block_id = working_set.add_block(block); - ( - // Why creating a pipeline here for only one expression? - // Is there a way to only make this a declaration? - Statement::Pipeline(Pipeline::from_vec(vec![Expression { - expr: Expr::Subexpression(block_id), - span: span(spans), - ty: Type::Unknown, // FIXME - }])), - None, - ) + if let Ok(contents) = contents { + let (block, err) = parse( + working_set, + path.file_name().and_then(|x| x.to_str()), + &contents, + true, + ); + if let None = err { + // Successful parse + // What should I be doing here? + let block_id = working_set.add_block(block); + // return ( + // // Successful parse + // // Why creating a pipeline here for only one expression? + // // Is there a way to only make this a declaration? + // Statement::Pipeline(Pipeline::from_vec(vec![Expression { + // expr: Expr::Subexpression(block_id), + // span: span(spans), + // ty: Type::Unknown, // FIXME + // }])), + // None, + // ); + } } } - Err(e) => ( - Statement::Pipeline(Pipeline::from_vec(vec![Expression { - expr: Expr::Garbage, - span: span(spans), - ty: Type::Unknown, - }])), - Some(ParseError::UnknownState(e.into(), span(spans))), - ), //(ShellError::InternalError("Can't load file to source".to_string())), } - } else { - ( + + return ( Statement::Pipeline(Pipeline::from_vec(vec![Expression { - expr: Expr::Garbage, - span: span(spans), + expr: Expr::Call(call), + span: call_span, ty: Type::Unknown, }])), - Some(ParseError::Mismatch( - "string".into(), - // Can this be better? - "incompatible string".into(), - spans[1], - )), - ) + None, + ); } - } else { - // Not source command? - ( - Statement::Pipeline(Pipeline::from_vec(vec![Expression { - expr: Expr::Garbage, - span: span(spans), - ty: Type::Unknown, - }])), - error, - ) } - // ( - // Statement::Pipeline(Pipeline::from_vec(vec![Expression { - // expr: Expr::Garbage, - // span: span(spans), - // ty: Type::Unknown, - // }])), - // Some(ParseError::UnknownState( - // "internal error: let statement unparseable".into(), - // span(spans), - // )), - // ) + + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }])), + Some(ParseError::UnknownState( + "internal error: source statement unparseable".into(), + span(spans), + )), + ) } /// Parse a statement. Check if def, let, alias, or source command can process it properly From adb92b970e3ddf6975f735f04d8898a874ff06dd Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Fri, 1 Oct 2021 22:07:17 -0400 Subject: [PATCH 05/24] nothing --- crates/nu-parser/src/parser.rs | 19 ++++++++----------- example.nu | 1 + 2 files changed, 9 insertions(+), 11 deletions(-) create mode 100644 example.nu diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 38b5123763..76e5c88037 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2507,24 +2507,21 @@ pub fn parse_source( let contents = std::fs::read(path); if let Ok(contents) = contents { + // This will load the defs from the file into the + // working set, if it was a successful parse. let (block, err) = parse( working_set, path.file_name().and_then(|x| x.to_str()), &contents, - true, + false, ); - if let None = err { - // Successful parse - // What should I be doing here? - let block_id = working_set.add_block(block); + if let Some(_) = err { + // Unsuccessful parse of file // return ( - // // Successful parse - // // Why creating a pipeline here for only one expression? - // // Is there a way to only make this a declaration? // Statement::Pipeline(Pipeline::from_vec(vec![Expression { - // expr: Expr::Subexpression(block_id), - // span: span(spans), - // ty: Type::Unknown, // FIXME + // expr: Expr::Call(call), + // span: call_span, + // ty: Type::Unknown, // }])), // None, // ); diff --git a/example.nu b/example.nu new file mode 100644 index 0000000000..75138d409f --- /dev/null +++ b/example.nu @@ -0,0 +1 @@ +alias x = 4 \ No newline at end of file From 2d4e471052d01124214de41c41766910749dc889 Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Fri, 1 Oct 2021 22:17:32 -0400 Subject: [PATCH 06/24] fix more merge conflicts --- Cargo.lock | 32 +++++++------------ crates/nu-command/Cargo.toml | 5 --- crates/nu-command/src/core_commands/mod.rs | 2 ++ .../src/{ => core_commands}/source.rs | 10 ++---- crates/nu-command/src/default_context.rs | 7 ++-- crates/nu-command/src/lib.rs | 25 --------------- crates/nu-engine/src/eval.rs | 5 --- 7 files changed, 18 insertions(+), 68 deletions(-) rename crates/nu-command/src/{ => core_commands}/source.rs (91%) diff --git a/Cargo.lock b/Cargo.lock index cf0b7954ab..f8afa23836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,11 +350,6 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -<<<<<<< HEAD -version = "0.2.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" -======= version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" @@ -368,7 +363,6 @@ dependencies = [ "serde", "serde_test", ] ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 [[package]] name = "lock_api" @@ -405,9 +399,9 @@ dependencies = [ [[package]] name = "miette" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b98aebb9d23c72cb22c089834ea59be059c6f462e844fd9fd18dd0168ad149c" +checksum = "4786c5b04c6f73e96d88444e7f37e241d99479ea5dd88a4887363ab2e03b4e53" dependencies = [ "atty", "backtrace", @@ -424,9 +418,9 @@ dependencies = [ [[package]] name = "miette-derive" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a7cd3347eb52480d4ba59d71ce2b48b8b128034e17068c7e2ff3766c2e87a3" +checksum = "0ee63a981bc9cde5f26665ffd756b624963bf0b5956e0df51e52ef8f6b5466d6" dependencies = [ "proc-macro2", "quote", @@ -504,11 +498,7 @@ version = "0.1.0" dependencies = [ "glob", "nu-engine", -<<<<<<< HEAD - "nu-parser", -======= "nu-json", ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 "nu-protocol", "nu-table", "sysinfo", @@ -812,7 +802,7 @@ dependencies = [ [[package]] name = "reedline" version = "0.2.0" -source = "git+https://github.com/jntrnr/reedline?branch=main#93c2146fcf4257c40426bc2f0c6903d4115caaf1" +source = "git+https://github.com/jntrnr/reedline?branch=main#bfddc5870ca2d8301694b4211bdcdb29e647c6f3" dependencies = [ "chrono", "crossterm", @@ -944,9 +934,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "smawk" @@ -956,9 +946,9 @@ checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" [[package]] name = "supports-color" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f5b0f9e689dd52e27228469dd68b7416b60d75b7571ae9060a5f4c50048fee" +checksum = "3f3cef55878ee693bb9f6765515f52910ec20b776d222fce5d11fbb9f5368028" dependencies = [ "atty", "is_ci", @@ -975,9 +965,9 @@ dependencies = [ [[package]] name = "supports-unicode" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5fa283a620b255940913bd962cda2e6320e3799041f96ac0d7191ff2b4622f" +checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2" dependencies = [ "atty", ] diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index beca24e6ee..eb8e8303ba 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -9,14 +9,9 @@ edition = "2018" nu-engine = { path = "../nu-engine" } nu-json = { path = "../nu-json" } nu-protocol = { path = "../nu-protocol" } -<<<<<<< HEAD -nu-engine = { path = "../nu-engine" } -nu-parser = {path = "../nu-parser"} -======= nu-table = { path = "../nu-table" } # Potential dependencies for extras glob = "0.3.0" thiserror = "1.0.29" sysinfo = "0.20.4" ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 diff --git a/crates/nu-command/src/core_commands/mod.rs b/crates/nu-command/src/core_commands/mod.rs index 4d909467d6..43a5165fc8 100644 --- a/crates/nu-command/src/core_commands/mod.rs +++ b/crates/nu-command/src/core_commands/mod.rs @@ -5,6 +5,7 @@ mod help; mod if_; mod let_; mod module; +mod source; mod use_; pub use alias::Alias; @@ -14,4 +15,5 @@ pub use help::Help; pub use if_::If; pub use let_::Let; pub use module::Module; +pub use source::Source; pub use use_::Use; diff --git a/crates/nu-command/src/source.rs b/crates/nu-command/src/core_commands/source.rs similarity index 91% rename from crates/nu-command/src/source.rs rename to crates/nu-command/src/core_commands/source.rs index 566c898ef5..677c6f5eda 100644 --- a/crates/nu-command/src/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,10 +1,6 @@ -use nu_engine::{eval_block, eval_expression}; -use nu_parser::parse; -use nu_protocol::ast::{Block, Call}; -use nu_protocol::engine::{Command, EngineState, EvaluationContext, StateWorkingSet}; -use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; -use std::task::Context; -use std::{borrow::Cow, path::Path, path::PathBuf}; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{Signature, SyntaxShape, Value}; /// Source a file for environment variables. pub struct Source; diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index d2041573f7..6bc8726adc 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -5,14 +5,11 @@ use nu_protocol::{ Signature, }; -<<<<<<< HEAD -use crate::{Alias, Benchmark, BuildString, Def, Do, Each, For, If, Length, Let, LetEnv, Source}; -======= use crate::{ Alias, Benchmark, BuildString, Def, Do, Each, External, For, From, FromJson, Git, GitCheckout, - Help, If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Ps, Sys, Table, Use, Where, + Help, If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Ps, Source, Sys, Table, Use, + Where, }; ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 pub fn create_default_context() -> Rc> { let engine_state = Rc::new(RefCell::new(EngineState::new())); diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 35b71cfd30..da1fd1a680 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -1,29 +1,5 @@ mod core_commands; mod default_context; -<<<<<<< HEAD -mod do_; -mod each; -mod for_; -mod if_; -mod length; -mod let_; -mod let_env; -mod source; - -pub use alias::Alias; -pub use benchmark::Benchmark; -pub use build_string::BuildString; -pub use def::Def; -pub use default_context::create_default_context; -pub use do_::Do; -pub use each::Each; -pub use for_::For; -pub use if_::If; -pub use length::Length; -pub use let_::Let; -pub use let_env::LetEnv; -pub use source::Source; -======= mod env; mod experimental; mod filesystem; @@ -43,4 +19,3 @@ pub use formats::*; pub use strings::*; pub use system::*; pub use viewers::*; ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 0abb4efbc4..f8b7c633f4 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,12 +1,7 @@ use nu_parser::parse; use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; -<<<<<<< HEAD -use nu_protocol::engine::{EngineState, EvaluationContext, StateWorkingSet}; -use nu_protocol::{Range, ShellError, Span, Value}; -======= use nu_protocol::engine::EvaluationContext; use nu_protocol::{Range, ShellError, Span, Type, Value}; ->>>>>>> 3567bbbf32302dbc3cbf97a39b03efa3bd3e8bb5 pub fn eval_operator(op: &Expression) -> Result { match op { From 8ef16c6da66f4804e10e495735631ea66ec06626 Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Fri, 1 Oct 2021 22:25:35 -0400 Subject: [PATCH 07/24] add source command --- crates/nu-parser/src/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index d88c3f73d7..2dd9714cc2 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1,5 +1,6 @@ use crate::{ lex, lite_parse, + parse_keywords::parse_source, type_check::{math_result_type, type_compatible}, LiteBlock, ParseError, Token, TokenContents, }; @@ -2585,7 +2586,7 @@ pub fn parse_statement( b"alias" => parse_alias(working_set, spans), b"module" => parse_module(working_set, spans), b"use" => parse_use(working_set, spans), - b"source" => parse_use(working_set, spans), + b"source" => parse_source(working_set, spans), _ => { let (expr, err) = parse_expression(working_set, spans); (Statement::Pipeline(Pipeline::from_vec(vec![expr])), err) From 9e7285ad46a28d34f59d1067f80f5d29f544d79e Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Fri, 1 Oct 2021 22:26:52 -0400 Subject: [PATCH 08/24] Delete example.nu --- example.nu | 1 - 1 file changed, 1 deletion(-) delete mode 100644 example.nu diff --git a/example.nu b/example.nu deleted file mode 100644 index 75138d409f..0000000000 --- a/example.nu +++ /dev/null @@ -1 +0,0 @@ -alias x = 4 \ No newline at end of file From 909b7d2160ffbc4289b82c8090a196cb136ec712 Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Sun, 3 Oct 2021 14:23:23 -0400 Subject: [PATCH 09/24] no-op --- crates/nu-command/src/core_commands/source.rs | 6 ++++-- crates/nu-parser/src/parse_keywords.rs | 2 ++ example.nu | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 example.nu diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index 677c6f5eda..76bcc461bb 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,6 +1,8 @@ +use std::path::Path; + use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{Signature, SyntaxShape, Value}; +use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; /// Source a file for environment variables. pub struct Source; @@ -27,7 +29,7 @@ impl Command for Source { _context: &EvaluationContext, call: &Call, input: Value, - ) -> Result { + ) -> Result { Ok(Value::Nothing { span: call.head }) // source(_context, call, input) } diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 1700a71ce8..ffce2acc40 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -581,6 +581,8 @@ pub fn parse_source( // None, // ); } + } else { + // Source file couldn't be parsed correctly } } } diff --git a/example.nu b/example.nu new file mode 100644 index 0000000000..6a1392318a --- /dev/null +++ b/example.nu @@ -0,0 +1,5 @@ +def greet [name] { + echo "hello" $name +} + +greet "world" \ No newline at end of file From 9d49618e87cb6c77f7fc672a123fb638a2938cce Mon Sep 17 00:00:00 2001 From: xiuxiu62 Date: Tue, 5 Oct 2021 12:54:30 -0700 Subject: [PATCH 10/24] add impl From io::Error and dyn Error for ShellError --- crates/nu-protocol/src/shell_error.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index 0bb59291e7..73f5147fa8 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -97,4 +97,20 @@ pub enum ShellError { #[label("{destination_message}")] destination_span: Span, }, + + #[error("Move not possible")] + #[diagnostic(code(nu::shell::move_not_possible_single), url(docsrs))] + MoveNotPossibleSingle(String, #[label("{0}")] Span), +} + +impl From for ShellError { + fn from(input: std::io::Error) -> ShellError { + ShellError::InternalError(format!("{:?}", input)) + } +} + +impl From> for ShellError { + fn from(input: Box) -> ShellError { + ShellError::InternalError(format!("{:?}", input)) + } } From 5da1310696ef807a1d83c0a79c21ebe34184d106 Mon Sep 17 00:00:00 2001 From: xiuxiu62 Date: Tue, 5 Oct 2021 12:55:33 -0700 Subject: [PATCH 11/24] add fs utils --- crates/nu-command/src/filesystem/mod.rs | 3 + crates/nu-command/src/filesystem/util.rs | 82 ++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 crates/nu-command/src/filesystem/util.rs diff --git a/crates/nu-command/src/filesystem/mod.rs b/crates/nu-command/src/filesystem/mod.rs index 90b697fcd8..2d2212766a 100644 --- a/crates/nu-command/src/filesystem/mod.rs +++ b/crates/nu-command/src/filesystem/mod.rs @@ -1,7 +1,10 @@ mod cd; +mod cp; mod ls; mod mv; +mod util; pub use cd::Cd; +pub use cp::Cp; pub use ls::Ls; pub use mv::Mv; diff --git a/crates/nu-command/src/filesystem/util.rs b/crates/nu-command/src/filesystem/util.rs new file mode 100644 index 0000000000..86a0bd4c96 --- /dev/null +++ b/crates/nu-command/src/filesystem/util.rs @@ -0,0 +1,82 @@ +use std::path::{Path, PathBuf}; + +use nu_path::canonicalize_with; +use nu_protocol::ShellError; + +#[derive(Default)] +pub struct FileStructure { + pub resources: Vec, +} + +impl FileStructure { + pub fn new() -> FileStructure { + FileStructure { resources: vec![] } + } + + #[allow(dead_code)] + pub fn contains_more_than_one_file(&self) -> bool { + self.resources.len() > 1 + } + + #[allow(dead_code)] + pub fn contains_files(&self) -> bool { + !self.resources.is_empty() + } + + pub fn paths_applying_with( + &mut self, + to: F, + ) -> Result, Box> + where + F: Fn((PathBuf, usize)) -> Result<(PathBuf, PathBuf), Box>, + { + self.resources + .iter() + .map(|f| (PathBuf::from(&f.location), f.at)) + .map(|f| to(f)) + .collect() + } + + pub fn walk_decorate(&mut self, start_path: &Path) -> Result<(), ShellError> { + self.resources = Vec::::new(); + self.build(start_path, 0)?; + self.resources.sort(); + + Ok(()) + } + + fn build(&mut self, src: &Path, lvl: usize) -> Result<(), ShellError> { + let source = canonicalize_with(src, std::env::current_dir()?)?; + + if source.is_dir() { + for entry in std::fs::read_dir(src)? { + let entry = entry?; + let path = entry.path(); + + if path.is_dir() { + self.build(&path, lvl + 1)?; + } + + self.resources.push(Resource { + location: path.to_path_buf(), + at: lvl, + }); + } + } else { + self.resources.push(Resource { + location: source, + at: lvl, + }); + } + + Ok(()) + } +} + +#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct Resource { + pub at: usize, + pub location: PathBuf, +} + +impl Resource {} From 8dc3ebd6e23123657c8664906b442d093df48aa5 Mon Sep 17 00:00:00 2001 From: xiuxiu62 Date: Tue, 5 Oct 2021 12:55:46 -0700 Subject: [PATCH 12/24] start cp command --- crates/nu-command/src/default_context.rs | 1 + crates/nu-command/src/filesystem/cp.rs | 155 +++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 crates/nu-command/src/filesystem/cp.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 8418b2a384..c36e7ea906 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -17,6 +17,7 @@ pub fn create_default_context() -> Rc> { working_set.add_decl(Box::new(Benchmark)); working_set.add_decl(Box::new(BuildString)); working_set.add_decl(Box::new(Cd)); + working_set.add_decl(Box::new(Cp)); working_set.add_decl(Box::new(Def)); working_set.add_decl(Box::new(Do)); working_set.add_decl(Box::new(Each)); diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs new file mode 100644 index 0000000000..6c6850c9ee --- /dev/null +++ b/crates/nu-command/src/filesystem/cp.rs @@ -0,0 +1,155 @@ +use std::env::current_dir; +use std::path::PathBuf; + +use nu_engine::{eval_expression, CallExt}; +use nu_path::canonicalize_with; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{IntoValueStream, ShellError, Signature, SyntaxShape, Value}; + +use crate::filesystem::util::FileStructure; + +pub struct Cp; + +impl Command for Cp { + fn name(&self) -> &str { + "cp" + } + + fn usage(&self) -> &str { + "Copy files." + } + + fn signature(&self) -> Signature { + Signature::build("cp") + .required("source", SyntaxShape::GlobPattern, "the place to copy from") + .required("destination", SyntaxShape::Filepath, "the place to copy to") + .switch( + "recursive", + "copy recursively through subdirectories", + Some('r'), + ) + } + + fn run( + &self, + context: &EvaluationContext, + call: &Call, + _input: Value, + ) -> Result { + let source: String = call.req(context, 0)?; + let destination: String = call.req(context, 1)?; + + let path: PathBuf = current_dir().unwrap(); + let source = path.join(source.as_str()); + let destination = path.join(destination.as_str()); + + let mut sources = + glob::glob(&source.to_string_lossy()).map_or_else(|_| Vec::new(), Iterator::collect); + if sources.is_empty() { + return Err(ShellError::FileNotFound(call.positional[0].span)); + } + + if sources.len() > 1 && !destination.is_dir() { + return Err(ShellError::MoveNotPossible { + source_message: "Can't move many files".to_string(), + source_span: call.positional[0].span, + destination_message: "into single file".to_string(), + destination_span: call.positional[1].span, + }); + } + + let any_source_is_dir = sources.iter().any(|f| matches!(f, Ok(f) if f.is_dir())); + let recursive = call + .named + .iter() + .fold(false, |acc, p| acc || { &p.0 == "recursive" }); + if any_source_is_dir && !recursive { + return Err(ShellError::MoveNotPossibleSingle( + "Directories must be copied using \"--recursive\"".to_string(), + call.positional[0].span, + )); + } + + // for entry in sources.into_iter().flatten() { + // let mut sources = FileStructure::new(); + // sources.walk_decorate(&entry)?; + + // if entry.is_file() { + // let sources = sources.paths_applying_with(|(source_file, _depth_level)| { + // if destination.is_dir() { + // let mut dest = canonicalize_with(&destination.item, &path)?; + // if let Some(name) = entry.file_name() { + // dest.push(name); + // } + // Ok((source_file, dest)) + // } else { + // Ok((source_file, destination.clone())) + // } + // })?; + + // for (src, dst) in sources { + // if src.is_file() { + // std::fs::copy(src, dst).map_err(|e| { + // ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) + // })?; + // } + // } + // } else if entry.is_dir() { + // let destination = if !destination.exists() { + // destination.clone() + // } else { + // match entry.file_name() { + // Some(name) => destination.join(name), + // None => { + // return Err(ShellError::labeled_error( + // "Copy aborted. Not a valid path", + // "not a valid path", + // dst.tag, + // )) + // } + // } + // }; + + // std::fs::create_dir_all(&destination).map_err(|e| { + // ShellError::labeled_error(e.to_string(), e.to_string(), &dst.tag) + // })?; + + // let sources = sources.paths_applying_with(|(source_file, depth_level)| { + // let mut dest = destination.clone(); + // let path = canonicalize_with(&source_file, &path)?; + + // let comps: Vec<_> = path + // .components() + // .map(|fragment| fragment.as_os_str()) + // .rev() + // .take(1 + depth_level) + // .collect(); + + // for fragment in comps.into_iter().rev() { + // dest.push(fragment); + // } + + // Ok((PathBuf::from(&source_file), dest)) + // })?; + + // let dst_tag = &dst.tag; + // for (src, dst) in sources { + // if src.is_dir() && !dst.exists() { + // std::fs::create_dir_all(&dst).map_err(|e| { + // ShellError::labeled_error(e.to_string(), e.to_string(), dst_tag) + // })?; + // } + + // if src.is_file() { + // std::fs::copy(&src, &dst).map_err(|e| { + // ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) + // })?; + // } + // } + // } + // } + + Ok(Value::Nothing { span: call.head }) + } +} From 8536c12bd9554699020f7b76e7d35e18939a9eaa Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Tue, 5 Oct 2021 12:59:17 -0700 Subject: [PATCH 13/24] change signature name to get, it was (I believe) incorrectly named wrap --- crates/nu-command/src/filters/get.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index c06badbb26..7ad1c12823 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -15,7 +15,7 @@ impl Command for Get { } fn signature(&self) -> nu_protocol::Signature { - Signature::build("wrap").required( + Signature::build("get").required( "cell_path", SyntaxShape::CellPath, "the cell path to the data", From 48f534cd3b93b3f915202635400061784bd892d0 Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Tue, 5 Oct 2021 13:02:56 -0700 Subject: [PATCH 14/24] change location of reedline to nushell from the jt repo --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5aa2a2c69f..5ff65ec7db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "reedline" version = "0.2.0" -source = "git+https://github.com/jntrnr/reedline?branch=main#88bded3417e7f6c1242b444f403448de583357f0" +source = "git+https://github.com/nushell/reedline?branch=main#88bded3417e7f6c1242b444f403448de583357f0" dependencies = [ "chrono", "crossterm", diff --git a/Cargo.toml b/Cargo.toml index 826e3d542e..01c94b401a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser", "crates/nu-command", "crates/nu-protocol"] [dependencies] -reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" } +reedline = { git = "https://github.com/nushell/reedline", branch = "main" } crossterm = "0.21.*" nu-cli = { path="./crates/nu-cli" } nu-command = { path="./crates/nu-command" } From 5cc7fbcde7e1c81b21c4fad55e6c78cabef6370e Mon Sep 17 00:00:00 2001 From: Michael Angerman Date: Tue, 5 Oct 2021 13:03:43 -0700 Subject: [PATCH 15/24] jntrnr to nushell --- crates/nu-cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 5b47189196..3f2f90c7cc 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -12,4 +12,4 @@ nu-protocol = { path = "../nu-protocol" } miette = { version = "3.0.0", features = ["fancy"] } thiserror = "1.0.29" nu-ansi-term = "0.36.0" -reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" } +reedline = { git = "https://github.com/nushell/reedline", branch = "main" } From 74d4c501a8a79de85915d6add55dfd86f012e6e5 Mon Sep 17 00:00:00 2001 From: xiuxiu62 Date: Tue, 5 Oct 2021 14:08:39 -0700 Subject: [PATCH 16/24] add move, recursive fill, and recursive create procedures --- crates/nu-command/src/filesystem/cp.rs | 167 +++++++++++++---------- crates/nu-command/src/filesystem/util.rs | 5 +- crates/nu-protocol/src/shell_error.rs | 14 ++ 3 files changed, 109 insertions(+), 77 deletions(-) diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 6c6850c9ee..d2a4fbb81b 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -44,7 +44,7 @@ impl Command for Cp { let source = path.join(source.as_str()); let destination = path.join(destination.as_str()); - let mut sources = + let sources = glob::glob(&source.to_string_lossy()).map_or_else(|_| Vec::new(), Iterator::collect); if sources.is_empty() { return Err(ShellError::FileNotFound(call.positional[0].span)); @@ -60,10 +60,7 @@ impl Command for Cp { } let any_source_is_dir = sources.iter().any(|f| matches!(f, Ok(f) if f.is_dir())); - let recursive = call - .named - .iter() - .fold(false, |acc, p| acc || { &p.0 == "recursive" }); + let recursive = call.named.iter().any(|p| &p.0 == "recursive"); if any_source_is_dir && !recursive { return Err(ShellError::MoveNotPossibleSingle( "Directories must be copied using \"--recursive\"".to_string(), @@ -71,84 +68,106 @@ impl Command for Cp { )); } - // for entry in sources.into_iter().flatten() { - // let mut sources = FileStructure::new(); - // sources.walk_decorate(&entry)?; + for entry in sources.into_iter().flatten() { + let mut sources = FileStructure::new(); + sources.walk_decorate(&entry)?; - // if entry.is_file() { - // let sources = sources.paths_applying_with(|(source_file, _depth_level)| { - // if destination.is_dir() { - // let mut dest = canonicalize_with(&destination.item, &path)?; - // if let Some(name) = entry.file_name() { - // dest.push(name); - // } - // Ok((source_file, dest)) - // } else { - // Ok((source_file, destination.clone())) - // } - // })?; + if entry.is_file() { + let sources = sources.paths_applying_with(|(source_file, _depth_level)| { + if destination.is_dir() { + let mut dest = canonicalize_with(&destination, &path)?; + if let Some(name) = entry.file_name() { + dest.push(name); + } + Ok((source_file, dest)) + } else { + Ok((source_file, destination.clone())) + } + })?; - // for (src, dst) in sources { - // if src.is_file() { - // std::fs::copy(src, dst).map_err(|e| { - // ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) - // })?; - // } - // } - // } else if entry.is_dir() { - // let destination = if !destination.exists() { - // destination.clone() - // } else { - // match entry.file_name() { - // Some(name) => destination.join(name), - // None => { - // return Err(ShellError::labeled_error( - // "Copy aborted. Not a valid path", - // "not a valid path", - // dst.tag, - // )) - // } - // } - // }; + for (src, dst) in sources { + if src.is_file() { + std::fs::copy(&src, dst).map_err(|e| { + ShellError::MoveNotPossibleSingle( + format!( + "failed to move containing file \"{}\": {}", + src.to_string_lossy(), + e + ), + call.positional[0].span, + ) + })?; + } + } + } else if entry.is_dir() { + let destination = if !destination.exists() { + destination.clone() + } else { + match entry.file_name() { + Some(name) => destination.join(name), + None => { + return Err(ShellError::FileNotFoundCustom( + format!("containing \"{:?}\" is not a valid path", entry), + call.positional[0].span, + )) + } + } + }; - // std::fs::create_dir_all(&destination).map_err(|e| { - // ShellError::labeled_error(e.to_string(), e.to_string(), &dst.tag) - // })?; + std::fs::create_dir_all(&destination).map_err(|e| { + ShellError::MoveNotPossibleSingle( + format!("failed to recursively fill destination: {}", e), + call.positional[1].span, + ) + })?; - // let sources = sources.paths_applying_with(|(source_file, depth_level)| { - // let mut dest = destination.clone(); - // let path = canonicalize_with(&source_file, &path)?; + let sources = sources.paths_applying_with(|(source_file, depth_level)| { + let mut dest = destination.clone(); + let path = canonicalize_with(&source_file, &path)?; - // let comps: Vec<_> = path - // .components() - // .map(|fragment| fragment.as_os_str()) - // .rev() - // .take(1 + depth_level) - // .collect(); + let comps: Vec<_> = path + .components() + .map(|fragment| fragment.as_os_str()) + .rev() + .take(1 + depth_level) + .collect(); - // for fragment in comps.into_iter().rev() { - // dest.push(fragment); - // } + for fragment in comps.into_iter().rev() { + dest.push(fragment); + } - // Ok((PathBuf::from(&source_file), dest)) - // })?; + Ok((PathBuf::from(&source_file), dest)) + })?; - // let dst_tag = &dst.tag; - // for (src, dst) in sources { - // if src.is_dir() && !dst.exists() { - // std::fs::create_dir_all(&dst).map_err(|e| { - // ShellError::labeled_error(e.to_string(), e.to_string(), dst_tag) - // })?; - // } + for (src, dst) in sources { + if src.is_dir() && !dst.exists() { + std::fs::create_dir_all(&dst).map_err(|e| { + ShellError::MoveNotPossibleSingle( + format!( + "failed to create containing directory \"{}\": {}", + dst.to_string_lossy(), + e + ), + call.positional[1].span, + ) + })?; + } - // if src.is_file() { - // std::fs::copy(&src, &dst).map_err(|e| { - // ShellError::labeled_error(e.to_string(), e.to_string(), &name_tag) - // })?; - // } - // } - // } - // } + if src.is_file() { + std::fs::copy(&src, &dst).map_err(|e| { + ShellError::MoveNotPossibleSingle( + format!( + "failed to move containing file \"{}\": {}", + src.to_string_lossy(), + e + ), + call.positional[0].span, + ) + })?; + } + } + } + } Ok(Value::Nothing { span: call.head }) } diff --git a/crates/nu-command/src/filesystem/util.rs b/crates/nu-command/src/filesystem/util.rs index 86a0bd4c96..a2d217cf05 100644 --- a/crates/nu-command/src/filesystem/util.rs +++ b/crates/nu-command/src/filesystem/util.rs @@ -8,17 +8,16 @@ pub struct FileStructure { pub resources: Vec, } +#[allow(dead_code)] impl FileStructure { pub fn new() -> FileStructure { FileStructure { resources: vec![] } } - #[allow(dead_code)] pub fn contains_more_than_one_file(&self) -> bool { self.resources.len() > 1 } - #[allow(dead_code)] pub fn contains_files(&self) -> bool { !self.resources.is_empty() } @@ -33,7 +32,7 @@ impl FileStructure { self.resources .iter() .map(|f| (PathBuf::from(&f.location), f.at)) - .map(|f| to(f)) + .map(to) .collect() } diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index 73f5147fa8..6a7464508e 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -83,10 +83,18 @@ pub enum ShellError { #[diagnostic(code(nu::shell::file_not_found), url(docsrs))] FileNotFound(#[label("file not found")] Span), + #[error("File not found")] + #[diagnostic(code(nu::shell::file_not_found), url(docsrs))] + FileNotFoundCustom(String, #[label("{0}")] Span), + #[error("Directory not found")] #[diagnostic(code(nu::shell::directory_not_found), url(docsrs))] DirectoryNotFound(#[label("directory not found")] Span), + #[error("File not found")] + #[diagnostic(code(nu::shell::file_not_found), url(docsrs))] + DirectoryNotFoundCustom(String, #[label("{0}")] Span), + #[error("Move not possible")] #[diagnostic(code(nu::shell::move_not_possible), url(docsrs))] MoveNotPossible { @@ -109,6 +117,12 @@ impl From for ShellError { } } +impl std::convert::From> for ShellError { + fn from(input: Box) -> ShellError { + ShellError::InternalError(input.to_string()) + } +} + impl From> for ShellError { fn from(input: Box) -> ShellError { ShellError::InternalError(format!("{:?}", input)) From cc8a470668367a337167618e8e023ddec912570c Mon Sep 17 00:00:00 2001 From: xiuxiu62 Date: Tue, 5 Oct 2021 14:13:23 -0700 Subject: [PATCH 17/24] clean up unused imports --- crates/nu-command/src/filesystem/cp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index d2a4fbb81b..6ebc305923 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -1,11 +1,11 @@ use std::env::current_dir; use std::path::PathBuf; -use nu_engine::{eval_expression, CallExt}; +use nu_engine::CallExt; use nu_path::canonicalize_with; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; -use nu_protocol::{IntoValueStream, ShellError, Signature, SyntaxShape, Value}; +use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; use crate::filesystem::util::FileStructure; From b3b51a2ed65e02d9e8eee44189a0b3d2dacd4462 Mon Sep 17 00:00:00 2001 From: jacremer Date: Tue, 5 Oct 2021 15:09:51 -0700 Subject: [PATCH 18/24] drop redundant iter -> vec -> iter --- crates/nu-command/src/filesystem/cp.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index 6ebc305923..79751f2c93 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -124,18 +124,13 @@ impl Command for Cp { let sources = sources.paths_applying_with(|(source_file, depth_level)| { let mut dest = destination.clone(); let path = canonicalize_with(&source_file, &path)?; - - let comps: Vec<_> = path + let components = path .components() .map(|fragment| fragment.as_os_str()) .rev() - .take(1 + depth_level) - .collect(); - - for fragment in comps.into_iter().rev() { - dest.push(fragment); - } + .take(1 + depth_level); + components.for_each(|fragment| dest.push(fragment)); Ok((PathBuf::from(&source_file), dest)) })?; From d6d0bad7aafb620ddd8ab6f2eafa66649a976522 Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Tue, 5 Oct 2021 21:59:16 -0400 Subject: [PATCH 19/24] reverted --- crates/nu-cli/src/syntax_highlight.rs | 4 +- crates/nu-command/src/core_commands/source.rs | 7 ++- crates/nu-parser/src/parse_keywords.rs | 48 ++++++++++++++----- example.nu | 6 +-- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index 87ec535ed0..67198959ba 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -34,7 +34,9 @@ impl Highlighter for NuHighlighter { .to_string(); output.push((Style::new(), gap)); } - + // println!("line: \n{}", line); + // println!("shape: \n{:#?}\n", shape); + // println!("global_span_offset: \n{:#?}\n", global_span_offset); let next_token = line [(shape.0.start - global_span_offset)..(shape.0.end - global_span_offset)] .to_string(); diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index 76bcc461bb..c154566c22 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,5 +1,7 @@ +use std::borrow::Borrow; use std::path::Path; +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}; @@ -30,8 +32,9 @@ impl Command for Source { call: &Call, input: Value, ) -> Result { - Ok(Value::Nothing { span: call.head }) - // source(_context, call, input) + let block = &call.positional[0]; + + Ok(eval_expression(_context, block)?) } } diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index ffce2acc40..44dd96ae26 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -549,8 +549,9 @@ pub fn parse_source( if name == b"source" { if let Some(decl_id) = working_set.find_decl(b"source") { - let (call, call_span, _) = + let (call, call_span, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id); + // println!("\nSpans: {:#?}", spans); // Command and one file name if spans.len() >= 2 { @@ -570,19 +571,44 @@ pub fn parse_source( &contents, false, ); + if let Some(_) = err { // Unsuccessful parse of file - // return ( - // Statement::Pipeline(Pipeline::from_vec(vec![Expression { - // expr: Expr::Call(call), - // span: call_span, - // ty: Type::Unknown, - // }])), - // None, - // ); + return ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call), + span: span(&spans[1..]), + ty: Type::Unknown, + custom_completion: None, + }])), + // Return the file parse error + err, + ); + } else { + // Save the block into the working set + let block_id = working_set.add_block(block); + // println!("CALL:{:?}", call); + + let mut call_with_block = call.clone(); + // println!("CALL_WITH_BLOCK: {:?}", call_with_block); + + call_with_block.positional.push(Expression { + expr: Expr::Block(block_id), + span: span(&spans[1..]), + ty: Type::Unknown, + custom_completion: None, + }); + + return ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call_with_block), + span: call_span, + ty: Type::Unknown, + custom_completion: None, + }])), + None, + ); } - } else { - // Source file couldn't be parsed correctly } } } diff --git a/example.nu b/example.nu index 6a1392318a..a4f40bac8a 100644 --- a/example.nu +++ b/example.nu @@ -1,5 +1,5 @@ -def greet [name] { - echo "hello" $name +def inc [x] { + $x + 1 } -greet "world" \ No newline at end of file +inc 5 \ No newline at end of file From 996ee363b774cc9291371c4fcd18bfd9669ef03d Mon Sep 17 00:00:00 2001 From: Tanishq Kancharla Date: Tue, 5 Oct 2021 22:03:18 -0400 Subject: [PATCH 20/24] comments --- crates/nu-parser/src/parse_keywords.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index e0e72f1807..1069c3c706 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -697,6 +697,8 @@ pub fn parse_source( if name == b"source" { if let Some(decl_id) = working_set.find_decl(b"source") { + // Is this the right call to be using here? + // Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't. let (call, call_span, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id); // println!("\nSpans: {:#?}", spans); @@ -740,6 +742,8 @@ pub fn parse_source( let mut call_with_block = call.clone(); // println!("CALL_WITH_BLOCK: {:?}", call_with_block); + // Adding this expression to the positional creates a syntax highlighting error + // after writing `source example.nu` call_with_block.positional.push(Expression { expr: Expr::Block(block_id), span: span(&spans[1..]), From 7eb022b58cad2a8fdbfe4ff9ef6dc5d9769a9a64 Mon Sep 17 00:00:00 2001 From: JT Date: Wed, 6 Oct 2021 15:29:05 +1300 Subject: [PATCH 21/24] Adapt tk's work for a source command --- crates/nu-cli/src/syntax_highlight.rs | 3 - crates/nu-command/src/core_commands/source.rs | 98 +++---------------- crates/nu-engine/src/eval.rs | 1 - crates/nu-parser/src/parse_keywords.rs | 17 ++-- 4 files changed, 18 insertions(+), 101 deletions(-) diff --git a/crates/nu-cli/src/syntax_highlight.rs b/crates/nu-cli/src/syntax_highlight.rs index fccc0e9544..161801e261 100644 --- a/crates/nu-cli/src/syntax_highlight.rs +++ b/crates/nu-cli/src/syntax_highlight.rs @@ -34,9 +34,6 @@ impl Highlighter for NuHighlighter { .to_string(); output.push((Style::new(), gap)); } - // println!("line: \n{}", line); - // println!("shape: \n{:#?}\n", shape); - // println!("global_span_offset: \n{:#?}\n", global_span_offset); let next_token = line [(shape.0.start - global_span_offset)..(shape.0.end - global_span_offset)] .to_string(); diff --git a/crates/nu-command/src/core_commands/source.rs b/crates/nu-command/src/core_commands/source.rs index 73f5425d27..aacd3564cd 100644 --- a/crates/nu-command/src/core_commands/source.rs +++ b/crates/nu-command/src/core_commands/source.rs @@ -1,7 +1,4 @@ -use std::borrow::Borrow; -use std::path::Path; - -use nu_engine::{eval_block, eval_expression}; +use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EvaluationContext}; use nu_protocol::{ShellError, Signature, SyntaxShape, Value}; @@ -28,92 +25,19 @@ impl Command for Source { fn run( &self, - _context: &EvaluationContext, + context: &EvaluationContext, call: &Call, input: Value, ) -> Result { - let block = &call.positional[0]; + // 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)?; - Ok(eval_expression(_context, block)?) + let block = context + .engine_state + .borrow() + .get_block(block_id as usize) + .clone(); + eval_block(context, &block, input) } } - -// pub fn source(ctx: &EvaluationContext, call: &Call, input: Value) -> Result { -// let filename = call.positional[0] -// .as_string() -// .expect("internal error: missing file name"); - -// let source_file = Path::new(&filename); - -// // This code is in the current Nushell version -// // ...Not entirely sure what it's doing or if there's an equivalent in engine-q - -// // Note: this is a special case for setting the context from a command -// // In this case, if we don't set it now, we'll lose the scope that this -// // variable should be set into. - -// // let lib_dirs = &ctx -// // .configs() -// // .lock() -// // .global_config -// // .as_ref() -// // .map(|configuration| match configuration.var("lib_dirs") { -// // Some(paths) => paths -// // .table_entries() -// // .cloned() -// // .map(|path| path.as_string()) -// // .collect(), -// // None => vec![], -// // }); - -// // if let Some(dir) = lib_dirs { -// // for lib_path in dir { -// // match lib_path { -// // Ok(name) => { -// // let path = PathBuf::from(name).join(source_file); - -// // if let Ok(contents) = -// // std::fs::read_to_string(&expand_path(Cow::Borrowed(path.as_path()))) -// // { -// // let result = script::run_script_standalone(contents, true, ctx, false); - -// // if let Err(err) = result { -// // ctx.error(err); -// // } -// // return Ok(OutputStream::empty()); -// // } -// // } -// // Err(reason) => { -// // ctx.error(reason.clone()); -// // } -// // } -// // } -// // } - -// // This is to stay consistent w/ the code taken from nushell -// let path = source_file; - -// let contents = std::fs::read(path); - -// match contents { -// Ok(contents) => { -// let engine_state = EngineState::new(); -// let mut working_set = StateWorkingSet::new(&engine_state); - -// let (block, err) = parse(&mut working_set, None, &contents, true); -// if let Some(e) = err { -// // Be more specific here: need to convert parse error to string -// Err(e.into()) -// } else { -// let result = eval_block(ctx, &block, input); -// match result { -// Err(e) => Err(e), -// _ => Ok(Value::nothing()), -// } -// } -// } -// Err(_) => Err(ShellError::InternalError( -// "Can't load file to source".to_string(), -// )), -// } -// } diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 7408cf2cc9..d59ff4b3e0 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1,4 +1,3 @@ -use nu_parser::parse; use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; use nu_protocol::engine::EvaluationContext; use nu_protocol::{Range, ShellError, Span, Type, Unit, Value}; diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index c1510edbb7..3abad8e122 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -1,7 +1,7 @@ use nu_protocol::{ ast::{Block, Call, Expr, Expression, ImportPatternMember, Pipeline, Statement}, engine::StateWorkingSet, - span, DeclId, ShellError, Span, SyntaxShape, Type, + span, DeclId, Span, SyntaxShape, Type, }; use std::path::Path; @@ -779,7 +779,6 @@ pub fn parse_source( // Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't. let (call, call_span, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id); - // println!("\nSpans: {:#?}", spans); // Command and one file name if spans.len() >= 2 { @@ -800,7 +799,7 @@ pub fn parse_source( false, ); - if let Some(_) = err { + if err.is_some() { // Unsuccessful parse of file return ( Statement::Pipeline(Pipeline::from_vec(vec![Expression { @@ -815,16 +814,14 @@ pub fn parse_source( } else { // Save the block into the working set let block_id = working_set.add_block(block); - // println!("CALL:{:?}", call); - let mut call_with_block = call.clone(); - // println!("CALL_WITH_BLOCK: {:?}", call_with_block); + let mut call_with_block = call; // Adding this expression to the positional creates a syntax highlighting error // after writing `source example.nu` call_with_block.positional.push(Expression { - expr: Expr::Block(block_id), - span: span(&spans[1..]), + expr: Expr::Int(block_id as i64), + span: spans[1], ty: Type::Unknown, custom_completion: None, }); @@ -849,14 +846,14 @@ pub fn parse_source( ty: Type::Unknown, custom_completion: None, }])), - None, + err, ); } } ( garbage_statement(spans), Some(ParseError::UnknownState( - "internal error: let statement unparseable".into(), + "internal error: source statement unparseable".into(), span(spans), )), ) From 2500f23fcbed079d41c4a6566bc81c3df413dace Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Wed, 6 Oct 2021 15:30:36 +1300 Subject: [PATCH 22/24] Delete example.nu --- example.nu | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 example.nu diff --git a/example.nu b/example.nu deleted file mode 100644 index a4f40bac8a..0000000000 --- a/example.nu +++ /dev/null @@ -1,5 +0,0 @@ -def inc [x] { - $x + 1 -} - -inc 5 \ No newline at end of file From bb126e8e09201b8fd97220f3cc7f79b2fb3c1353 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Thu, 7 Oct 2021 06:36:28 +1300 Subject: [PATCH 23/24] Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..25623d08e8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Nushell Project + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 5021d618002e05675b98c28499390270fa7cf40e Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Thu, 7 Oct 2021 08:43:00 +1300 Subject: [PATCH 24/24] Update TODO.md --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 0a051b75b9..13df448caa 100644 --- a/TODO.md +++ b/TODO.md @@ -24,6 +24,7 @@ - [x] Externals - [x] Modules and imports - [x] Exports +- [x] Source - [ ] Input/output types - [ ] Support for `$in` - [ ] Value serialization @@ -32,7 +33,6 @@ - [ ] ctrl-c support - [ ] operator overflow - [ ] finish operator type-checking -- [ ] Source - [ ] Overlays (replacement for `autoenv`) ## Maybe: