From d856cebebd271caf89e95de63a5edb1d6d6c3c7d Mon Sep 17 00:00:00 2001 From: JT Date: Tue, 2 Nov 2021 16:08:05 +1300 Subject: [PATCH] Add a simple scope variable --- Cargo.lock | 98 +++++++++++++++++++ crates/nu-command/src/default_context.rs | 10 -- crates/nu-engine/src/eval.rs | 69 ++++++++++++- crates/nu-parser/src/parser.rs | 12 ++- crates/nu-protocol/src/engine/engine_state.rs | 41 ++++---- crates/nu-protocol/src/lib.rs | 1 + src/main.rs | 15 --- src/tests.rs | 5 + 8 files changed, 204 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 971d896add..8f5f84fb03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,6 +163,28 @@ dependencies = [ "chrono", ] +[[package]] +name = "chrono-tz" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c01c1c607d25c71bbaa67c113d6c6b36c434744b4fd66691d711b5b1bc0c8b" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + [[package]] name = "console" version = "0.15.0" @@ -622,6 +644,8 @@ version = "0.1.0" dependencies = [ "bytesize", "chrono", + "chrono-humanize", + "chrono-tz", "dialoguer", "glob", "lscolors", @@ -636,6 +660,7 @@ dependencies = [ "sysinfo", "terminal_size", "thiserror", + "titlecase", "trash", "unicode-segmentation", ] @@ -801,6 +826,54 @@ dependencies = [ "winapi", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + +[[package]] +name = "phf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + [[package]] name = "ppv-lite86" version = "0.2.15" @@ -1096,6 +1169,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -1263,6 +1342,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "titlecase" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f565e410cfc24c2f2a89960b023ca192689d7f77d3f8d4f4af50c2d8affe1117" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "trash" version = "1.3.0" @@ -1278,6 +1367,15 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +[[package]] +name = "uncased" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-linebreak" version = "0.1.2" diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 1814d87a8a..ea6f6365be 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -95,16 +95,6 @@ pub fn create_default_context() -> EngineState { let sig = Signature::build("exit"); working_set.add_decl(sig.predeclare()); - let sig = Signature::build("vars"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("decls"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("blocks"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("stack"); - working_set.add_decl(sig.predeclare()); - let sig = Signature::build("contents"); - working_set.add_decl(sig.predeclare()); working_set.render() }; diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 396eab3839..9b000df58e 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -371,12 +371,12 @@ pub fn eval_block( } pub fn eval_variable( - _engine_state: &EngineState, + engine_state: &EngineState, stack: &Stack, var_id: VarId, span: Span, ) -> Result { - if var_id == 0 { + if var_id == nu_protocol::NU_VARIABLE_ID { // $nu let mut output_cols = vec![]; let mut output_vals = vec![]; @@ -425,6 +425,71 @@ pub fn eval_variable( output_vals.push(Value::String { val: cwd, span }) } + Ok(Value::Record { + cols: output_cols, + vals: output_vals, + span, + }) + } else if var_id == nu_protocol::SCOPE_VARIABLE_ID { + let mut output_cols = vec![]; + let mut output_vals = vec![]; + + let mut vars = vec![]; + let mut commands = vec![]; + let mut aliases = vec![]; + let mut modules = vec![]; + + for frame in &engine_state.scope { + for var in &frame.vars { + vars.push(Value::String { + val: String::from_utf8_lossy(var.0).to_string(), + span, + }); + } + + for command in &frame.decls { + commands.push(Value::String { + val: String::from_utf8_lossy(command.0).to_string(), + span, + }); + } + + for alias in &frame.aliases { + aliases.push(Value::String { + val: String::from_utf8_lossy(alias.0).to_string(), + span, + }); + } + + for module in &frame.modules { + modules.push(Value::String { + val: String::from_utf8_lossy(module.0).to_string(), + span, + }); + } + } + + output_cols.push("vars".to_string()); + output_vals.push(Value::List { vals: vars, span }); + + output_cols.push("commands".to_string()); + output_vals.push(Value::List { + vals: commands, + span, + }); + + output_cols.push("aliases".to_string()); + output_vals.push(Value::List { + vals: aliases, + span, + }); + + output_cols.push("modules".to_string()); + output_vals.push(Value::List { + vals: modules, + span, + }); + Ok(Value::Record { cols: output_cols, vals: output_vals, diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 7df54f008e..a49e324841 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1198,7 +1198,17 @@ pub fn parse_variable_expr( } else if contents == b"$nu" { return ( Expression { - expr: Expr::Var(0), + expr: Expr::Var(nu_protocol::NU_VARIABLE_ID), + span, + ty: Type::Unknown, + custom_completion: None, + }, + None, + ); + } else if contents == b"$scope" { + return ( + Expression { + expr: Expr::Var(nu_protocol::SCOPE_VARIABLE_ID), span, ty: Type::Unknown, custom_completion: None, diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 761545e3a1..6e072ddc29 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -6,17 +6,6 @@ use std::{ sync::{atomic::AtomicBool, Arc}, }; -#[derive(Clone)] -pub struct EngineState { - files: im::Vector<(String, usize, usize)>, - file_contents: im::Vector<(Vec, usize, usize)>, - vars: im::Vector, - decls: im::Vector>, - blocks: im::Vector, - pub scope: im::Vector, - pub ctrlc: Option>, -} - // Tells whether a decl etc. is visible or not // TODO: When adding new exportables (env vars, aliases, etc.), parametrize the ID type with generics #[derive(Debug, Clone)] @@ -62,9 +51,9 @@ impl Visibility { pub struct ScopeFrame { pub vars: HashMap, VarId>, predecls: HashMap, DeclId>, // temporary storage for predeclarations - decls: HashMap, DeclId>, - aliases: HashMap, Vec>, - modules: HashMap, BlockId>, + pub decls: HashMap, DeclId>, + pub aliases: HashMap, Vec>, + pub modules: HashMap, BlockId>, visibility: Visibility, } @@ -91,18 +80,26 @@ impl Default for ScopeFrame { } } -impl Default for EngineState { - fn default() -> Self { - Self::new() - } +#[derive(Clone)] +pub struct EngineState { + files: im::Vector<(String, usize, usize)>, + file_contents: im::Vector<(Vec, usize, usize)>, + vars: im::Vector, + decls: im::Vector>, + blocks: im::Vector, + pub scope: im::Vector, + pub ctrlc: Option>, } +pub const NU_VARIABLE_ID: usize = 0; +pub const SCOPE_VARIABLE_ID: usize = 1; + impl EngineState { pub fn new() -> Self { Self { files: im::vector![], file_contents: im::vector![], - vars: im::vector![Type::Unknown], + vars: im::vector![Type::Unknown, Type::Unknown], decls: im::vector![], blocks: im::vector![], scope: im::vector![ScopeFrame::new()], @@ -319,6 +316,12 @@ impl EngineState { } } +impl Default for EngineState { + fn default() -> Self { + Self::new() + } +} + pub struct StateWorkingSet<'a> { pub permanent_state: &'a EngineState, pub delta: StateDelta, diff --git a/crates/nu-protocol/src/lib.rs b/crates/nu-protocol/src/lib.rs index 081a9b0b41..6a7bf45c11 100644 --- a/crates/nu-protocol/src/lib.rs +++ b/crates/nu-protocol/src/lib.rs @@ -11,6 +11,7 @@ mod ty; mod value; pub use value::Value; +pub use engine::{NU_VARIABLE_ID, SCOPE_VARIABLE_ID}; pub use example::*; pub use id::*; pub use pipeline_data::*; diff --git a/src/main.rs b/src/main.rs index aecb0041aa..9dba312575 100644 --- a/src/main.rs +++ b/src/main.rs @@ -225,21 +225,6 @@ fn main() -> Result<()> { Ok(Signal::Success(s)) => { if s.trim() == "exit" { break; - } else if s.trim() == "vars" { - engine_state.print_vars(); - continue; - } else if s.trim() == "decls" { - engine_state.print_decls(); - continue; - } else if s.trim() == "blocks" { - engine_state.print_blocks(); - continue; - } else if s.trim() == "stack" { - stack.print_stack(); - continue; - } else if s.trim() == "contents" { - engine_state.print_contents(); - continue; } eval_source( diff --git a/src/tests.rs b/src/tests.rs index b3852b1c31..dc3251bf79 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -801,3 +801,8 @@ fn long_flag() -> TestResult { fn help_works_with_missing_requirements() -> TestResult { run_test(r#"each --help | lines | length"#, "10") } + +#[test] +fn scope_variable() -> TestResult { + run_test(r"let x = 3; $scope.vars.0", "$x") +}