From 356e05177c559e9e02b801ffcdf666784861c6fc Mon Sep 17 00:00:00 2001 From: Michael Angerman <1809991+stormasm@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:46:16 -0700 Subject: [PATCH] nu-cmd-extra crate infrastructure in place with the Bits command as the model for adding other commands (#9327) I wanted to get the infrastructure in place for starters for our *nu-cmd-extra* crate... The plan is to put inside here the following commands... * bits * bytes * math I thought it would be easier to do one at a time as well as get the nu-cmd-extra crate out there on crates.io for this upcoming release... Once this lands the infrastructure will be in place to move over the other noted commands for now... And then add other stuff we do NOT want to be in 1.0. --- Cargo.lock | 13 ++++ Cargo.toml | 6 +- crates/nu-cmd-extra/Cargo.toml | 29 ++++++++ crates/nu-cmd-extra/LICENSE | 21 ++++++ crates/nu-cmd-extra/src/example_test.rs | 74 +++++++++++++++++++ .../src/extra}/bits/and.rs | 0 .../src/extra}/bits/bits_.rs | 0 .../src/extra}/bits/mod.rs | 25 +++++++ .../src/extra}/bits/not.rs | 0 .../src => nu-cmd-extra/src/extra}/bits/or.rs | 0 .../src/extra}/bits/rotate_left.rs | 0 .../src/extra}/bits/rotate_right.rs | 0 .../src/extra}/bits/shift_left.rs | 0 .../src/extra}/bits/shift_right.rs | 0 .../src/extra}/bits/xor.rs | 0 crates/nu-cmd-extra/src/extra/mod.rs | 9 +++ crates/nu-cmd-extra/src/lib.rs | 6 ++ crates/nu-cmd-lang/Cargo.toml | 2 - crates/nu-command/Cargo.toml | 2 + crates/nu-command/src/default_context.rs | 20 ++--- crates/nu-command/src/lib.rs | 2 - src/tests.rs | 1 + 22 files changed, 190 insertions(+), 20 deletions(-) create mode 100644 crates/nu-cmd-extra/Cargo.toml create mode 100644 crates/nu-cmd-extra/LICENSE create mode 100644 crates/nu-cmd-extra/src/example_test.rs rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/and.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/bits_.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/mod.rs (82%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/not.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/or.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/rotate_left.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/rotate_right.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/shift_left.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/shift_right.rs (100%) rename crates/{nu-command/src => nu-cmd-extra/src/extra}/bits/xor.rs (100%) create mode 100644 crates/nu-cmd-extra/src/extra/mod.rs create mode 100644 crates/nu-cmd-extra/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e7ec6435ae..68e0622aa7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2704,6 +2704,18 @@ dependencies = [ "sqlparser 0.33.0", ] +[[package]] +name = "nu-cmd-extra" +version = "0.80.1" +dependencies = [ + "nu-cmd-lang", + "nu-engine", + "nu-parser", + "nu-protocol", + "nu-test-support", + "num-traits", +] + [[package]] name = "nu-cmd-lang" version = "0.80.1" @@ -2774,6 +2786,7 @@ dependencies = [ "notify", "nu-ansi-term", "nu-cmd-dataframe", + "nu-cmd-extra", "nu-cmd-lang", "nu-color-config", "nu-engine", diff --git a/Cargo.toml b/Cargo.toml index b4de279305..3237148d84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ members = [ "crates/nu-engine", "crates/nu-parser", "crates/nu-system", + "crates/nu-cmd-extra", "crates/nu-cmd-lang", "crates/nu-cmd-dataframe", "crates/nu-command", @@ -108,8 +109,6 @@ plugin = [ "nu-protocol/plugin", "nu-engine/plugin", ] -# extra used to be more useful but now it's the same as default. Leaving it in for backcompat with existing build scripts -extra = ["default", "nu-cmd-lang/extra"] default = ["plugin", "which-support", "trash-support", "sqlite"] stable = ["default"] wasi = ["nu-cmd-lang/wasi"] @@ -121,7 +120,8 @@ static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"] which-support = ["nu-command/which-support", "nu-cmd-lang/which-support"] trash-support = ["nu-command/trash-support", "nu-cmd-lang/trash-support"] -# Extra +# Extra feature for nushell +extra = ["nu-command/extra"] # Dataframe feature for nushell dataframe = ["nu-command/dataframe", "nu-cmd-lang/dataframe"] diff --git a/crates/nu-cmd-extra/Cargo.toml b/crates/nu-cmd-extra/Cargo.toml new file mode 100644 index 0000000000..1bfcd6c42e --- /dev/null +++ b/crates/nu-cmd-extra/Cargo.toml @@ -0,0 +1,29 @@ +[package] +authors = ["The Nushell Project Developers"] +description = "Nushell's extra commands that are not part of the 1.0 api standard." +edition = "2021" +license = "MIT" +name = "nu-cmd-extra" +repository = "https://github.com/nushell/nushell/tree/main/crates/nu-cmd-extra" +version = "0.80.1" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +bench = false + +[dependencies] +nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.80.1" } +nu-engine = { path = "../nu-engine", version = "0.80.1" } +nu-parser = { path = "../nu-parser", version = "0.80.1" } +nu-protocol = { path = "../nu-protocol", version = "0.80.1" } + +# Potential dependencies for extras +num-traits = "0.2" + +[features] +extra = ["default"] +default = [] + +[dev-dependencies] +nu-test-support = { path = "../nu-test-support", version = "0.80.1" } diff --git a/crates/nu-cmd-extra/LICENSE b/crates/nu-cmd-extra/LICENSE new file mode 100644 index 0000000000..ae174e8595 --- /dev/null +++ b/crates/nu-cmd-extra/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 - 2023 The Nushell Project Developers + +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. diff --git a/crates/nu-cmd-extra/src/example_test.rs b/crates/nu-cmd-extra/src/example_test.rs new file mode 100644 index 0000000000..7ed7e22f75 --- /dev/null +++ b/crates/nu-cmd-extra/src/example_test.rs @@ -0,0 +1,74 @@ +#[cfg(test)] +use nu_protocol::engine::Command; + +#[cfg(test)] +pub fn test_examples(cmd: impl Command + 'static) { + test_examples::test_examples(cmd); +} + +#[cfg(test)] +mod test_examples { + + use nu_cmd_lang::example_support::{ + check_all_signature_input_output_types_entries_have_examples, + check_example_evaluates_to_expected_output, + check_example_input_and_output_types_match_command_signature, + }; + + use nu_protocol::{ + engine::{Command, EngineState, StateWorkingSet}, + Type, + }; + use std::collections::HashSet; + + pub fn test_examples(cmd: impl Command + 'static) { + let examples = cmd.examples(); + let signature = cmd.signature(); + let mut engine_state = make_engine_state(cmd.clone_box()); + + let cwd = std::env::current_dir().expect("Could not get current working directory."); + + let mut witnessed_type_transformations = HashSet::<(Type, Type)>::new(); + + for example in examples { + if example.result.is_none() { + continue; + } + witnessed_type_transformations.extend( + check_example_input_and_output_types_match_command_signature( + &example, + &cwd, + &mut make_engine_state(cmd.clone_box()), + &signature.input_output_types, + signature.operates_on_cell_paths(), + signature.vectorizes_over_list, + ), + ); + check_example_evaluates_to_expected_output(&example, cwd.as_path(), &mut engine_state); + } + + check_all_signature_input_output_types_entries_have_examples( + signature, + witnessed_type_transformations, + ); + } + + fn make_engine_state(cmd: Box) -> Box { + let mut engine_state = Box::new(EngineState::new()); + + let delta = { + // Base functions that are needed for testing + // Try to keep this working set small to keep tests running as fast as possible + let mut working_set = StateWorkingSet::new(&engine_state); + + // Adding the command that is being tested to the working set + working_set.add_decl(cmd); + working_set.render() + }; + + engine_state + .merge_delta(delta) + .expect("Error merging delta"); + engine_state + } +} diff --git a/crates/nu-command/src/bits/and.rs b/crates/nu-cmd-extra/src/extra/bits/and.rs similarity index 100% rename from crates/nu-command/src/bits/and.rs rename to crates/nu-cmd-extra/src/extra/bits/and.rs diff --git a/crates/nu-command/src/bits/bits_.rs b/crates/nu-cmd-extra/src/extra/bits/bits_.rs similarity index 100% rename from crates/nu-command/src/bits/bits_.rs rename to crates/nu-cmd-extra/src/extra/bits/bits_.rs diff --git a/crates/nu-command/src/bits/mod.rs b/crates/nu-cmd-extra/src/extra/bits/mod.rs similarity index 82% rename from crates/nu-command/src/bits/mod.rs rename to crates/nu-cmd-extra/src/extra/bits/mod.rs index b70bb73b55..9bc6775019 100644 --- a/crates/nu-command/src/bits/mod.rs +++ b/crates/nu-cmd-extra/src/extra/bits/mod.rs @@ -8,6 +8,7 @@ mod shift_left; mod shift_right; mod xor; +use nu_protocol::engine::StateWorkingSet; use nu_protocol::Spanned; pub use and::SubCommand as BitsAnd; @@ -20,6 +21,30 @@ pub use shift_left::SubCommand as BitsShiftLeft; pub use shift_right::SubCommand as BitsShiftRight; pub use xor::SubCommand as BitsXor; +pub fn add_bits_decls(working_set: &mut StateWorkingSet) { + macro_rules! bind_command { + ( $command:expr ) => { + working_set.add_decl(Box::new($command)); + }; + ( $( $command:expr ),* ) => { + $( working_set.add_decl(Box::new($command)); )* + }; + } + + // Dataframe commands + bind_command!( + Bits, + BitsAnd, + BitsNot, + BitsOr, + BitsXor, + BitsRotateLeft, + BitsRotateRight, + BitsShiftLeft, + BitsShiftRight + ); +} + #[derive(Clone, Copy)] enum NumberBytes { One, diff --git a/crates/nu-command/src/bits/not.rs b/crates/nu-cmd-extra/src/extra/bits/not.rs similarity index 100% rename from crates/nu-command/src/bits/not.rs rename to crates/nu-cmd-extra/src/extra/bits/not.rs diff --git a/crates/nu-command/src/bits/or.rs b/crates/nu-cmd-extra/src/extra/bits/or.rs similarity index 100% rename from crates/nu-command/src/bits/or.rs rename to crates/nu-cmd-extra/src/extra/bits/or.rs diff --git a/crates/nu-command/src/bits/rotate_left.rs b/crates/nu-cmd-extra/src/extra/bits/rotate_left.rs similarity index 100% rename from crates/nu-command/src/bits/rotate_left.rs rename to crates/nu-cmd-extra/src/extra/bits/rotate_left.rs diff --git a/crates/nu-command/src/bits/rotate_right.rs b/crates/nu-cmd-extra/src/extra/bits/rotate_right.rs similarity index 100% rename from crates/nu-command/src/bits/rotate_right.rs rename to crates/nu-cmd-extra/src/extra/bits/rotate_right.rs diff --git a/crates/nu-command/src/bits/shift_left.rs b/crates/nu-cmd-extra/src/extra/bits/shift_left.rs similarity index 100% rename from crates/nu-command/src/bits/shift_left.rs rename to crates/nu-cmd-extra/src/extra/bits/shift_left.rs diff --git a/crates/nu-command/src/bits/shift_right.rs b/crates/nu-cmd-extra/src/extra/bits/shift_right.rs similarity index 100% rename from crates/nu-command/src/bits/shift_right.rs rename to crates/nu-cmd-extra/src/extra/bits/shift_right.rs diff --git a/crates/nu-command/src/bits/xor.rs b/crates/nu-cmd-extra/src/extra/bits/xor.rs similarity index 100% rename from crates/nu-command/src/bits/xor.rs rename to crates/nu-cmd-extra/src/extra/bits/xor.rs diff --git a/crates/nu-cmd-extra/src/extra/mod.rs b/crates/nu-cmd-extra/src/extra/mod.rs new file mode 100644 index 0000000000..e63a5b1e14 --- /dev/null +++ b/crates/nu-cmd-extra/src/extra/mod.rs @@ -0,0 +1,9 @@ +mod bits; + +pub use bits::add_bits_decls; + +use nu_protocol::engine::StateWorkingSet; + +pub fn add_extra_decls(working_set: &mut StateWorkingSet) { + add_bits_decls(working_set); +} diff --git a/crates/nu-cmd-extra/src/lib.rs b/crates/nu-cmd-extra/src/lib.rs new file mode 100644 index 0000000000..2a3d70e6cd --- /dev/null +++ b/crates/nu-cmd-extra/src/lib.rs @@ -0,0 +1,6 @@ +mod example_test; +pub mod extra; +pub use extra::*; + +#[cfg(test)] +pub use example_test::test_examples; diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index 1cfeb2b6e6..d63b46a2eb 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -32,6 +32,4 @@ trash-support = [] sqlite = [] dataframe = [] static-link-openssl = [] -extra = [] wasi = [] - diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index e326ca1bc6..d8702b745d 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -15,6 +15,7 @@ bench = false [dependencies] nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.80.1" } nu-cmd-dataframe = { path = "../nu-cmd-dataframe", version = "0.80.1", optional = true } +nu-cmd-extra = { path = "../nu-cmd-extra", version = "0.80.1", optional = true } nu-color-config = { path = "../nu-color-config", version = "0.80.1" } nu-engine = { path = "../nu-engine", version = "0.80.1" } nu-explore = { path = "../nu-explore", version = "0.80.1" } @@ -117,6 +118,7 @@ version = "0.48" [features] dataframe = ["dep:nu-cmd-dataframe"] +extra = ["dep:nu-cmd-extra"] plugin = ["nu-parser/plugin"] sqlite = [ "rusqlite", diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index d7b19afb58..c37adadc21 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -4,6 +4,9 @@ use crate::*; #[cfg(feature = "dataframe")] use nu_cmd_dataframe::*; +#[cfg(feature = "extra")] +use nu_cmd_extra::*; + pub fn create_default_context() -> EngineState { let mut engine_state = nu_cmd_lang::create_default_context(); @@ -20,6 +23,10 @@ pub fn create_default_context() -> EngineState { // they have to be registered before the main declarations. This helps to make // them only accessible if the correct input value category is used with the // declaration + + #[cfg(feature = "extra")] + add_extra_decls(&mut working_set); + #[cfg(feature = "dataframe")] add_dataframe_decls(&mut working_set); @@ -205,19 +212,6 @@ pub fn create_default_context() -> EngineState { StrUpcase }; - // Bits - bind_command! { - Bits, - BitsAnd, - BitsNot, - BitsOr, - BitsXor, - BitsRotateLeft, - BitsRotateRight, - BitsShiftLeft, - BitsShiftRight, - } - // Bytes bind_command! { Bytes, diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index da423ee676..45cbaafd78 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -1,4 +1,3 @@ -mod bits; mod bytes; mod charting; mod conversions; @@ -30,7 +29,6 @@ mod system; pub mod util; mod viewers; -pub use bits::*; pub use bytes::*; pub use charting::*; pub use conversions::*; diff --git a/src/tests.rs b/src/tests.rs index 4e1f984e46..309a8b30c3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "extra")] mod test_bits; mod test_cell_path; mod test_commandline;