From 28b6db115aad135a83924a0bd84367f249b7c244 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 17 Oct 2024 19:51:14 -0700 Subject: [PATCH] Revert PRs for 0.99.1 patch (#14119) # Description Temporarily reverts PRs merged after the 0.99.1 bump. --- Cargo.lock | 166 ++++++----- Cargo.toml | 10 +- .../src/completions/operator_completions.rs | 2 - crates/nu-cmd-lang/src/core_commands/try_.rs | 6 +- .../nu-cmd-plugin/src/commands/plugin/add.rs | 2 +- .../nu-cmd-plugin/src/commands/plugin/list.rs | 263 +++--------------- .../nu-cmd-plugin/src/commands/plugin/rm.rs | 2 +- crates/nu-cmd-plugin/src/util.rs | 60 +--- .../nu-command/src/conversions/into/value.rs | 2 +- crates/nu-command/src/debug/info.rs | 6 +- crates/nu-command/src/filters/group_by.rs | 40 +-- crates/nu-command/src/filters/split_by.rs | 21 +- crates/nu-command/src/filters/uniq.rs | 2 +- crates/nu-command/tests/commands/group_by.rs | 52 ++-- crates/nu-command/tests/commands/try_.rs | 17 -- crates/nu-engine/src/eval_ir.rs | 17 +- crates/nu-parser/src/parser.rs | 27 +- crates/nu-plugin/src/plugin/interface/mod.rs | 3 +- crates/nu-protocol/Cargo.toml | 1 - crates/nu-protocol/src/ast/operator.rs | 4 +- .../nu-protocol/src/errors/labeled_error.rs | 17 -- crates/nu-protocol/src/errors/shell_error.rs | 22 +- crates/nu-protocol/src/module.rs | 29 +- crates/nu-std/std/help/mod.nu | 6 +- .../src/dataframe/command/data/mod.rs | 2 - .../src/dataframe/command/data/unnest.rs | 145 ---------- .../src/dataframe/command/data/unpivot.rs | 4 +- rust-toolchain.toml | 2 +- tests/const_/mod.rs | 41 +-- tests/plugin_persistence/mod.rs | 22 +- tests/plugins/registry_file.rs | 53 +--- tests/repl/test_custom_commands.rs | 18 +- tests/repl/test_modules.rs | 5 - 33 files changed, 287 insertions(+), 782 deletions(-) delete mode 100644 crates/nu_plugin_polars/src/dataframe/command/data/unnest.rs diff --git a/Cargo.lock b/Cargo.lock index 424914e606..d6f1e35bd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2611,6 +2611,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "markup5ever" version = "0.12.1" @@ -3016,7 +3025,7 @@ dependencies = [ "percent-encoding", "reedline", "rstest", - "sysinfo 0.32.0", + "sysinfo", "tempfile", "unicode-segmentation", "uuid", @@ -3178,7 +3187,7 @@ dependencies = [ "serde_urlencoded", "serde_yaml", "sha2", - "sysinfo 0.32.0", + "sysinfo", "tabled", "tempfile", "terminal_size", @@ -3201,7 +3210,7 @@ dependencies = [ "v_htmlescape", "wax", "which", - "windows 0.56.0", + "windows 0.54.0", "winreg", ] @@ -3347,7 +3356,7 @@ dependencies = [ "rmp-serde", "serde", "serde_json", - "windows 0.56.0", + "windows 0.54.0", ] [[package]] @@ -3363,7 +3372,7 @@ dependencies = [ "nu-utils", "serde", "typetag", - "windows 0.56.0", + "windows 0.54.0", ] [[package]] @@ -3468,8 +3477,8 @@ dependencies = [ "ntapi", "once_cell", "procfs", - "sysinfo 0.32.0", - "windows 0.56.0", + "sysinfo", + "windows 0.54.0", ] [[package]] @@ -3752,6 +3761,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "objc-sys" version = "0.3.5" @@ -4711,7 +4729,7 @@ dependencies = [ "rayon", "smartstring", "stacker", - "sysinfo 0.30.13", + "sysinfo", "version_check", ] @@ -6097,21 +6115,8 @@ dependencies = [ "libc", "ntapi", "once_cell", - "windows 0.52.0", -] - -[[package]] -name = "sysinfo" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", "rayon", - "windows 0.56.0", + "windows 0.52.0", ] [[package]] @@ -6437,19 +6442,18 @@ dependencies = [ [[package]] name = "trash" -version = "5.1.1" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33caf2a9be1812a263a4bfce74d2de225fcde12ee7b77001361abd2b34ffdcc4" +checksum = "c658458d46d9d5a153a3b5cdd88d8579ad50d4fb85d53961e4526c8fc7c55a57" dependencies = [ "chrono", "libc", "log", - "objc2", - "objc2-foundation", + "objc", "once_cell", "scopeguard", - "urlencoding", - "windows 0.56.0", + "url", + "windows 0.44.0", ] [[package]] @@ -6638,12 +6642,6 @@ dependencies = [ "serde", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" @@ -7085,6 +7083,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows" version = "0.52.0" @@ -7097,11 +7104,11 @@ dependencies = [ [[package]] name = "windows" -version = "0.56.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-core 0.56.0", + "windows-core 0.54.0", "windows-targets 0.52.6", ] @@ -7116,38 +7123,14 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.56.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-implement", - "windows-interface", "windows-result", "windows-targets 0.52.6", ] -[[package]] -name = "windows-implement" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.75", -] - -[[package]] -name = "windows-interface" -version = "0.56.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.75", -] - [[package]] name = "windows-result" version = "0.1.2" @@ -7197,6 +7180,21 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -7228,6 +7226,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -7246,6 +7250,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -7264,6 +7274,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -7288,6 +7304,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -7306,6 +7328,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -7318,6 +7346,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -7336,6 +7370,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" diff --git a/Cargo.toml b/Cargo.toml index f1052e229b..2dabcfd7bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://www.nushell.sh" license = "MIT" name = "nu" repository = "https://github.com/nushell/nushell" -rust-version = "1.80.1" +rust-version = "1.79.0" version = "0.99.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -153,13 +153,13 @@ serde_yaml = "0.9" sha2 = "0.10" strip-ansi-escapes = "0.2.0" syn = "2.0" -sysinfo = "0.32" +sysinfo = "0.30" tabled = { version = "0.16.0", default-features = false } tempfile = "3.13" terminal_size = "0.3" titlecase = "2.0" toml = "0.8" -trash = "5.1" +trash = "3.3" umask = "2.1" unicode-segmentation = "1.12" unicode-width = "0.1" @@ -176,7 +176,7 @@ uuid = "1.10.0" v_htmlescape = "0.15.0" wax = "0.6" which = "6.0.0" -windows = "0.56" +windows = "0.54" windows-sys = "0.48" winreg = "0.52" @@ -320,4 +320,4 @@ bench = false # Run individual benchmarks like `cargo bench -- ` e.g. `cargo bench -- parse` [[bench]] name = "benchmarks" -harness = false +harness = false \ No newline at end of file diff --git a/crates/nu-cli/src/completions/operator_completions.rs b/crates/nu-cli/src/completions/operator_completions.rs index 460e7f590b..e9e95d0799 100644 --- a/crates/nu-cli/src/completions/operator_completions.rs +++ b/crates/nu-cli/src/completions/operator_completions.rs @@ -67,9 +67,7 @@ impl Completer for OperatorCompletion { ], Expr::String(_) => vec![ ("=~", "Contains regex match"), - ("like", "Contains regex match"), ("!~", "Does not contain regex match"), - ("not-like", "Does not contain regex match"), ( "++", "Appends two lists, a list and a value, two strings, or two binary values", diff --git a/crates/nu-cmd-lang/src/core_commands/try_.rs b/crates/nu-cmd-lang/src/core_commands/try_.rs index c7242550a7..ccf0d41f3b 100644 --- a/crates/nu-cmd-lang/src/core_commands/try_.rs +++ b/crates/nu-cmd-lang/src/core_commands/try_.rs @@ -107,11 +107,7 @@ fn run_catch( if let Some(catch) = catch { stack.set_last_error(&error); - let fancy_errors = match engine_state.get_config().error_style { - nu_protocol::ErrorStyle::Fancy => true, - nu_protocol::ErrorStyle::Plain => false, - }; - let error = error.into_value(span, fancy_errors); + let error = error.into_value(span); let block = engine_state.get_block(catch.block_id); // Put the error value in the positional closure var if let Some(var) = block.signature.get_positional(0) { diff --git a/crates/nu-cmd-plugin/src/commands/plugin/add.rs b/crates/nu-cmd-plugin/src/commands/plugin/add.rs index c603ddbb8c..c12f486668 100644 --- a/crates/nu-cmd-plugin/src/commands/plugin/add.rs +++ b/crates/nu-cmd-plugin/src/commands/plugin/add.rs @@ -119,7 +119,7 @@ apparent the next time `nu` is next launched with that plugin registry file. let metadata = interface.get_metadata()?; let commands = interface.get_signature()?; - modify_plugin_file(engine_state, stack, call.head, &custom_path, |contents| { + modify_plugin_file(engine_state, stack, call.head, custom_path, |contents| { // Update the file with the received metadata and signatures let item = PluginRegistryItem::new(plugin.identity(), metadata, commands); contents.upsert_plugin(item); diff --git a/crates/nu-cmd-plugin/src/commands/plugin/list.rs b/crates/nu-cmd-plugin/src/commands/plugin/list.rs index 367a532ef3..3fbf55b23c 100644 --- a/crates/nu-cmd-plugin/src/commands/plugin/list.rs +++ b/crates/nu-cmd-plugin/src/commands/plugin/list.rs @@ -1,8 +1,5 @@ -use itertools::{EitherOrBoth, Itertools}; +use itertools::Itertools; use nu_engine::command_prelude::*; -use nu_protocol::{IntoValue, PluginRegistryItemData}; - -use crate::util::read_plugin_file; #[derive(Clone)] pub struct PluginList; @@ -20,7 +17,7 @@ impl Command for PluginList { [ ("name".into(), Type::String), ("version".into(), Type::String), - ("status".into(), Type::String), + ("is_running".into(), Type::Bool), ("pid".into(), Type::Int), ("filename".into(), Type::String), ("shell".into(), Type::String), @@ -29,54 +26,11 @@ impl Command for PluginList { .into(), ), ) - .named( - "plugin-config", - SyntaxShape::Filepath, - "Use a plugin registry file other than the one set in `$nu.plugin-path`", - None, - ) - .switch( - "engine", - "Show info for plugins that are loaded into the engine only.", - Some('e'), - ) - .switch( - "registry", - "Show info for plugins from the registry file only.", - Some('r'), - ) .category(Category::Plugin) } fn description(&self) -> &str { - "List loaded and installed plugins." - } - - fn extra_description(&self) -> &str { - r#" -The `status` column will contain one of the following values: - -- `added`: The plugin is present in the plugin registry file, but not in - the engine. -- `loaded`: The plugin is present both in the plugin registry file and in - the engine, but is not running. -- `running`: The plugin is currently running, and the `pid` column should - contain its process ID. -- `modified`: The plugin state present in the plugin registry file is different - from the state in the engine. -- `removed`: The plugin is still loaded in the engine, but is not present in - the plugin registry file. -- `invalid`: The data in the plugin registry file couldn't be deserialized, - and the plugin most likely needs to be added again. - -`running` takes priority over any other status. Unless `--registry` is used -or the plugin has not been loaded yet, the values of `version`, `filename`, -`shell`, and `commands` reflect the values in the engine and not the ones in -the plugin registry file. - -See also: `plugin use` -"# - .trim() + "List installed plugins." } fn search_terms(&self) -> Vec<&str> { @@ -91,7 +45,7 @@ See also: `plugin use` result: Some(Value::test_list(vec![Value::test_record(record! { "name" => Value::test_string("inc"), "version" => Value::test_string(env!("CARGO_PKG_VERSION")), - "status" => Value::test_string("running"), + "is_running" => Value::test_bool(true), "pid" => Value::test_int(106480), "filename" => if cfg!(windows) { Value::test_string(r"C:\nu\plugins\nu_plugin_inc.exe") @@ -113,189 +67,58 @@ See also: `plugin use` fn run( &self, engine_state: &EngineState, - stack: &mut Stack, + _stack: &mut Stack, call: &Call, _input: PipelineData, ) -> Result { - let custom_path = call.get_flag(engine_state, stack, "plugin-config")?; - let engine_mode = call.has_flag(engine_state, stack, "engine")?; - let registry_mode = call.has_flag(engine_state, stack, "registry")?; + let head = call.head; - let plugins_info = match (engine_mode, registry_mode) { - // --engine and --registry together is equivalent to the default. - (false, false) | (true, true) => { - if engine_state.plugin_path.is_some() || custom_path.is_some() { - let plugins_in_engine = get_plugins_in_engine(engine_state); - let plugins_in_registry = - get_plugins_in_registry(engine_state, stack, call.head, &custom_path)?; - merge_plugin_info(plugins_in_engine, plugins_in_registry) - } else { - // Don't produce error when running nu --no-config-file - get_plugins_in_engine(engine_state) - } - } - (true, false) => get_plugins_in_engine(engine_state), - (false, true) => get_plugins_in_registry(engine_state, stack, call.head, &custom_path)?, - }; + // Group plugin decls by plugin identity + let decls = engine_state.plugin_decls().into_group_map_by(|decl| { + decl.plugin_identity() + .expect("plugin decl should have identity") + }); - Ok(plugins_info.into_value(call.head).into_pipeline_data()) - } -} - -#[derive(Debug, Clone, IntoValue, PartialOrd, Ord, PartialEq, Eq)] -struct PluginInfo { - name: String, - version: Option, - status: PluginStatus, - pid: Option, - filename: String, - shell: Option, - commands: Vec, -} - -#[derive(Debug, Clone, Copy, IntoValue, PartialOrd, Ord, PartialEq, Eq)] -#[nu_value(rename_all = "snake_case")] -enum PluginStatus { - Added, - Loaded, - Running, - Modified, - Removed, - Invalid, -} - -fn get_plugins_in_engine(engine_state: &EngineState) -> Vec { - // Group plugin decls by plugin identity - let decls = engine_state.plugin_decls().into_group_map_by(|decl| { - decl.plugin_identity() - .expect("plugin decl should have identity") - }); - - // Build plugins list - engine_state - .plugins() - .iter() - .map(|plugin| { + // Build plugins list + let list = engine_state.plugins().iter().map(|plugin| { // Find commands that belong to the plugin - let commands = decls - .get(plugin.identity()) + let commands = decls.get(plugin.identity()) .into_iter() - .flat_map(|decls| decls.iter().map(|decl| decl.name().to_owned())) - .sorted() + .flat_map(|decls| { + decls.iter().map(|decl| Value::string(decl.name(), head)) + }) .collect(); - PluginInfo { - name: plugin.identity().name().into(), - version: plugin.metadata().and_then(|m| m.version), - status: if plugin.pid().is_some() { - PluginStatus::Running - } else { - PluginStatus::Loaded - }, - pid: plugin.pid(), - filename: plugin.identity().filename().to_string_lossy().into_owned(), - shell: plugin - .identity() - .shell() - .map(|path| path.to_string_lossy().into_owned()), - commands, - } - }) - .sorted() - .collect() -} + let pid = plugin + .pid() + .map(|p| Value::int(p as i64, head)) + .unwrap_or(Value::nothing(head)); -fn get_plugins_in_registry( - engine_state: &EngineState, - stack: &mut Stack, - span: Span, - custom_path: &Option>, -) -> Result, ShellError> { - let plugin_file_contents = read_plugin_file(engine_state, stack, span, custom_path)?; + let shell = plugin + .identity() + .shell() + .map(|s| Value::string(s.to_string_lossy(), head)) + .unwrap_or(Value::nothing(head)); - let plugins_info = plugin_file_contents - .plugins - .into_iter() - .map(|plugin| { - let mut info = PluginInfo { - name: plugin.name, - version: None, - status: PluginStatus::Added, - pid: None, - filename: plugin.filename.to_string_lossy().into_owned(), - shell: plugin.shell.map(|path| path.to_string_lossy().into_owned()), - commands: vec![], + let metadata = plugin.metadata(); + let version = metadata + .and_then(|m| m.version) + .map(|s| Value::string(s, head)) + .unwrap_or(Value::nothing(head)); + + let record = record! { + "name" => Value::string(plugin.identity().name(), head), + "version" => version, + "is_running" => Value::bool(plugin.is_running(), head), + "pid" => pid, + "filename" => Value::string(plugin.identity().filename().to_string_lossy(), head), + "shell" => shell, + "commands" => Value::list(commands, head), }; - if let PluginRegistryItemData::Valid { metadata, commands } = plugin.data { - info.version = metadata.version; - info.commands = commands - .into_iter() - .map(|command| command.sig.name) - .sorted() - .collect(); - } else { - info.status = PluginStatus::Invalid; - } - info - }) - .sorted() - .collect(); + Value::record(record, head) + }).collect(); - Ok(plugins_info) -} - -/// If no options are provided, the command loads from both the plugin list in the engine and what's -/// in the registry file. We need to reconcile the two to set the proper states and make sure that -/// new plugins that were added to the plugin registry file show up. -fn merge_plugin_info( - from_engine: Vec, - from_registry: Vec, -) -> Vec { - from_engine - .into_iter() - .merge_join_by(from_registry, |info_a, info_b| { - info_a.name.cmp(&info_b.name) - }) - .map(|either_or_both| match either_or_both { - // Exists in the engine, but not in the registry file - EitherOrBoth::Left(info) => PluginInfo { - status: match info.status { - PluginStatus::Running => info.status, - // The plugin is not in the registry file, so it should be marked as `removed` - _ => PluginStatus::Removed, - }, - ..info - }, - // Exists in the registry file, but not in the engine - EitherOrBoth::Right(info) => info, - // Exists in both - EitherOrBoth::Both(info_engine, info_registry) => PluginInfo { - status: match (info_engine.status, info_registry.status) { - // Above all, `running` should be displayed if the plugin is running - (PluginStatus::Running, _) => PluginStatus::Running, - // `invalid` takes precedence over other states because the user probably wants - // to fix it - (_, PluginStatus::Invalid) => PluginStatus::Invalid, - // Display `modified` if the state in the registry is different somehow - _ if info_engine.is_modified(&info_registry) => PluginStatus::Modified, - // Otherwise, `loaded` (it's not running) - _ => PluginStatus::Loaded, - }, - ..info_engine - }, - }) - .sorted() - .collect() -} - -impl PluginInfo { - /// True if the plugin info shows some kind of change (other than status/pid) relative to the - /// other - fn is_modified(&self, other: &PluginInfo) -> bool { - self.name != other.name - || self.filename != other.filename - || self.shell != other.shell - || self.commands != other.commands + Ok(Value::list(list, head).into_pipeline_data()) } } diff --git a/crates/nu-cmd-plugin/src/commands/plugin/rm.rs b/crates/nu-cmd-plugin/src/commands/plugin/rm.rs index a82b41524a..33557836c0 100644 --- a/crates/nu-cmd-plugin/src/commands/plugin/rm.rs +++ b/crates/nu-cmd-plugin/src/commands/plugin/rm.rs @@ -87,7 +87,7 @@ fixed with `plugin add`. let filename = canonicalize_possible_filename_arg(engine_state, stack, &name.item); - modify_plugin_file(engine_state, stack, call.head, &custom_path, |contents| { + modify_plugin_file(engine_state, stack, call.head, custom_path, |contents| { if let Some(index) = contents .plugins .iter() diff --git a/crates/nu-cmd-plugin/src/util.rs b/crates/nu-cmd-plugin/src/util.rs index 80d1a766b4..6808a74a3c 100644 --- a/crates/nu-cmd-plugin/src/util.rs +++ b/crates/nu-cmd-plugin/src/util.rs @@ -6,17 +6,18 @@ use std::{ path::PathBuf, }; -fn get_plugin_registry_file_path( +pub(crate) fn modify_plugin_file( engine_state: &EngineState, stack: &mut Stack, span: Span, - custom_path: &Option>, -) -> Result { + custom_path: Option>, + operate: impl FnOnce(&mut PluginRegistryFile) -> Result<(), ShellError>, +) -> Result<(), ShellError> { #[allow(deprecated)] let cwd = current_dir(engine_state, stack)?; - if let Some(ref custom_path) = custom_path { - Ok(nu_path::expand_path_with(&custom_path.item, cwd, true)) + let plugin_registry_file_path = if let Some(ref custom_path) = custom_path { + nu_path::expand_path_with(&custom_path.item, cwd, true) } else { engine_state .plugin_path @@ -27,53 +28,8 @@ fn get_plugin_registry_file_path( span: Some(span), help: Some("you may be running `nu` with --no-config-file".into()), inner: vec![], - }) - } -} - -pub(crate) fn read_plugin_file( - engine_state: &EngineState, - stack: &mut Stack, - span: Span, - custom_path: &Option>, -) -> Result { - let plugin_registry_file_path = - get_plugin_registry_file_path(engine_state, stack, span, custom_path)?; - - let file_span = custom_path.as_ref().map(|p| p.span).unwrap_or(span); - - // Try to read the plugin file if it exists - if fs::metadata(&plugin_registry_file_path).is_ok_and(|m| m.len() > 0) { - PluginRegistryFile::read_from( - File::open(&plugin_registry_file_path).map_err(|err| ShellError::IOErrorSpanned { - msg: format!( - "failed to read `{}`: {}", - plugin_registry_file_path.display(), - err - ), - span: file_span, - })?, - Some(file_span), - ) - } else if let Some(path) = custom_path { - Err(ShellError::FileNotFound { - file: path.item.clone(), - span: path.span, - }) - } else { - Ok(PluginRegistryFile::default()) - } -} - -pub(crate) fn modify_plugin_file( - engine_state: &EngineState, - stack: &mut Stack, - span: Span, - custom_path: &Option>, - operate: impl FnOnce(&mut PluginRegistryFile) -> Result<(), ShellError>, -) -> Result<(), ShellError> { - let plugin_registry_file_path = - get_plugin_registry_file_path(engine_state, stack, span, custom_path)?; + })? + }; let file_span = custom_path.as_ref().map(|p| p.span).unwrap_or(span); diff --git a/crates/nu-command/src/conversions/into/value.rs b/crates/nu-command/src/conversions/into/value.rs index 99b1daf4b7..52e5ab339c 100644 --- a/crates/nu-command/src/conversions/into/value.rs +++ b/crates/nu-command/src/conversions/into/value.rs @@ -18,7 +18,7 @@ impl Command for IntoValue { .input_output_types(vec![(Type::table(), Type::table())]) .named( "columns", - SyntaxShape::List(Box::new(SyntaxShape::Any)), + SyntaxShape::Table(vec![]), "list of columns to update", Some('c'), ) diff --git a/crates/nu-command/src/debug/info.rs b/crates/nu-command/src/debug/info.rs index 2a680ae20d..da4689738e 100644 --- a/crates/nu-command/src/debug/info.rs +++ b/crates/nu-command/src/debug/info.rs @@ -101,7 +101,7 @@ fn all_columns(span: Span) -> Value { let environment = { let mut env_rec = Record::new(); for val in p.environ() { - if let Some((key, value)) = val.to_string_lossy().split_once('=') { + if let Some((key, value)) = val.split_once('=') { let is_env_var_a_list = { { #[cfg(target_family = "windows")] @@ -146,8 +146,8 @@ fn all_columns(span: Span) -> Value { "root" => root, "cwd" => cwd, "exe_path" => exe_path, - "command" => Value::string(p.cmd().join(std::ffi::OsStr::new(" ")).to_string_lossy(), span), - "name" => Value::string(p.name().to_string_lossy(), span), + "command" => Value::string(p.cmd().join(" "), span), + "name" => Value::string(p.name(), span), "environment" => environment, }, span, diff --git a/crates/nu-command/src/filters/group_by.rs b/crates/nu-command/src/filters/group_by.rs index 74a19c38e3..78789c606a 100644 --- a/crates/nu-command/src/filters/group_by.rs +++ b/crates/nu-command/src/filters/group_by.rs @@ -38,14 +38,6 @@ impl Command for GroupBy { "Splits a list or table into groups, and returns a record containing those groups." } - fn extra_description(&self) -> &str { - r#"the group-by command makes some assumptions: - - if the input data is not a string, the grouper will convert the key to string but the values will remain in their original format. e.g. with bools, "true" and true would be in the same group (see example). - - datetime is formatted based on your configuration setting. use `format date` to change the format. - - filesize is formatted based on your configuration setting. use `format filesize` to change the format. - - some nushell values are not supported, such as closures."# - } - fn run( &self, engine_state: &EngineState, @@ -122,20 +114,6 @@ impl Command for GroupBy { }), ])), }, - Example { - description: "Group bools, whether they are strings or actual bools", - example: r#"[true "true" false "false"] | group-by"#, - result: Some(Value::test_record(record! { - "true" => Value::test_list(vec![ - Value::test_bool(true), - Value::test_string("true"), - ]), - "false" => Value::test_list(vec![ - Value::test_bool(false), - Value::test_string("false"), - ]), - })), - } ] } } @@ -149,7 +127,6 @@ pub fn group_by( let head = call.head; let grouper: Option = call.opt(engine_state, stack, 0)?; let to_table = call.has_flag(engine_state, stack, "to-table")?; - let config = engine_state.get_config(); let values: Vec = input.into_iter().collect(); if values.is_empty() { @@ -160,7 +137,7 @@ pub fn group_by( Some(grouper) => { let span = grouper.span(); match grouper { - Value::CellPath { val, .. } => group_cell_path(val, values, config)?, + Value::CellPath { val, .. } => group_cell_path(val, values)?, Value::Closure { val, .. } => { group_closure(values, span, *val, engine_state, stack)? } @@ -172,7 +149,7 @@ pub fn group_by( } } } - None => group_no_grouper(values, config)?, + None => group_no_grouper(values)?, }; let value = if to_table { @@ -187,7 +164,6 @@ pub fn group_by( fn group_cell_path( column_name: CellPath, values: Vec, - config: &nu_protocol::Config, ) -> Result>, ShellError> { let mut groups = IndexMap::<_, Vec<_>>::new(); @@ -200,21 +176,18 @@ fn group_cell_path( continue; // likely the result of a failed optional access, ignore this value } - let key = key.to_abbreviated_string(config); + let key = key.coerce_string()?; groups.entry(key).or_default().push(value); } Ok(groups) } -fn group_no_grouper( - values: Vec, - config: &nu_protocol::Config, -) -> Result>, ShellError> { +fn group_no_grouper(values: Vec) -> Result>, ShellError> { let mut groups = IndexMap::<_, Vec<_>>::new(); for value in values.into_iter() { - let key = value.to_abbreviated_string(config); + let key = value.coerce_string()?; groups.entry(key).or_default().push(value); } @@ -230,13 +203,12 @@ fn group_closure( ) -> Result>, ShellError> { let mut groups = IndexMap::<_, Vec<_>>::new(); let mut closure = ClosureEval::new(engine_state, stack, closure); - let config = engine_state.get_config(); for value in values { let key = closure .run_with_value(value.clone())? .into_value(span)? - .to_abbreviated_string(config); + .coerce_into_string()?; groups.entry(key).or_default().push(value); } diff --git a/crates/nu-command/src/filters/split_by.rs b/crates/nu-command/src/filters/split_by.rs index 217918cf91..7a5898e608 100644 --- a/crates/nu-command/src/filters/split_by.rs +++ b/crates/nu-command/src/filters/split_by.rs @@ -84,16 +84,16 @@ pub fn split_by( input: PipelineData, ) -> Result { let name = call.head; - let config = engine_state.get_config(); + let splitter: Option = call.opt(engine_state, stack, 0)?; match splitter { Some(v) => { let splitter = Some(Spanned { - item: v.to_abbreviated_string(config), + item: v.coerce_into_string()?, span: name, }); - Ok(split(splitter.as_ref(), input, name, config)?) + Ok(split(splitter.as_ref(), input, name)?) } // This uses the same format as the 'requires a column name' error in sort_utils.rs None => Err(ShellError::GenericError { @@ -110,7 +110,6 @@ pub fn split( column_name: Option<&Spanned>, values: PipelineData, span: Span, - config: &nu_protocol::Config, ) -> Result { let grouper = if let Some(column_name) = column_name { Grouper::ByColumn(Some(column_name.clone())) @@ -128,7 +127,7 @@ pub fn split( }; match group_key { - Some(group_key) => Ok(group_key.to_abbreviated_string(config)), + Some(group_key) => Ok(group_key.coerce_string()?), None => Err(ShellError::CantFindColumn { col_name: column_name.item.to_string(), span: Some(column_name.span), @@ -137,12 +136,12 @@ pub fn split( } }; - data_split(values, Some(&block), span, config) + data_split(values, Some(&block), span) } Grouper::ByColumn(None) => { - let block = move |_, row: &Value| Ok(row.to_abbreviated_string(config)); + let block = move |_, row: &Value| row.coerce_string(); - data_split(values, Some(&block), span, config) + data_split(values, Some(&block), span) } } } @@ -152,7 +151,6 @@ fn data_group( values: &Value, grouper: Option<&dyn Fn(usize, &Value) -> Result>, span: Span, - config: &nu_protocol::Config, ) -> Result { let mut groups: IndexMap> = IndexMap::new(); @@ -160,7 +158,7 @@ fn data_group( let group_key = if let Some(ref grouper) = grouper { grouper(idx, &value) } else { - Ok(value.to_abbreviated_string(config)) + value.coerce_string() }; let group = groups.entry(group_key?).or_default(); @@ -181,7 +179,6 @@ pub fn data_split( value: PipelineData, splitter: Option<&dyn Fn(usize, &Value) -> Result>, dst_span: Span, - config: &nu_protocol::Config, ) -> Result { let mut splits = indexmap::IndexMap::new(); @@ -191,7 +188,7 @@ pub fn data_split( match v { Value::Record { val: grouped, .. } => { for (outer_key, list) in grouped.into_owned() { - match data_group(&list, splitter, span, config) { + match data_group(&list, splitter, span) { Ok(grouped_vals) => { if let Value::Record { val: sub, .. } = grouped_vals { for (inner_key, subset) in sub.into_owned() { diff --git a/crates/nu-command/src/filters/uniq.rs b/crates/nu-command/src/filters/uniq.rs index 3a82e73aa1..a22d62b89e 100644 --- a/crates/nu-command/src/filters/uniq.rs +++ b/crates/nu-command/src/filters/uniq.rs @@ -46,7 +46,7 @@ impl Command for Uniq { } fn search_terms(&self) -> Vec<&str> { - vec!["distinct", "deduplicate", "count"] + vec!["distinct", "deduplicate"] } fn run( diff --git a/crates/nu-command/tests/commands/group_by.rs b/crates/nu-command/tests/commands/group_by.rs index 232bbcba0f..c6d0903c94 100644 --- a/crates/nu-command/tests/commands/group_by.rs +++ b/crates/nu-command/tests/commands/group_by.rs @@ -23,33 +23,37 @@ fn groups() { #[test] fn errors_if_given_unknown_column_name() { - let sample = r#"{ - "nu": { - "committers": [ - {"name": "Andrés N. Robalino"}, - {"name": "JT Turner"}, - {"name": "Yehuda Katz"} - ], - "releases": [ - {"version": "0.2"} - {"version": "0.8"}, - {"version": "0.9999999"} - ], - "0xATYKARNU": [ - ["Th", "e", " "], - ["BIG", " ", "UnO"], - ["punto", "cero"] - ] - } -} -"#; + let sample = r#" + { + "nu": { + "committers": [ + {"name": "Andrés N. Robalino"}, + {"name": "JT Turner"}, + {"name": "Yehuda Katz"} + ], + "releases": [ + {"version": "0.2"} + {"version": "0.8"}, + {"version": "0.9999999"} + ], + "0xATYKARNU": [ + ["Th", "e", " "], + ["BIG", " ", "UnO"], + ["punto", "cero"] + ] + } + } + "#; let actual = nu!(pipeline(&format!( - r#"'{sample}' - | from json - | group-by {{|| get nu.releases.missing_column }}"# + r#" + '{sample}' + | from json + | group-by {{|| get nu.releases.version }} + "# ))); - assert!(actual.err.contains("cannot find column")); + + assert!(actual.err.contains("can't convert list to string")); } #[test] diff --git a/crates/nu-command/tests/commands/try_.rs b/crates/nu-command/tests/commands/try_.rs index 7e6952d2b9..487fd034b5 100644 --- a/crates/nu-command/tests/commands/try_.rs +++ b/crates/nu-command/tests/commands/try_.rs @@ -126,20 +126,3 @@ fn prints_only_if_last_pipeline() { let actual = nu!("try { ['should not print'] | every 1 }; 'last value'"); assert_eq!(actual.out, "last value"); } - -#[test] -fn get_error_columns() { - let actual = nu!(" try { non_existent_command } catch {|err| $err} | columns | to json -r"); - assert_eq!( - actual.out, - "[\"msg\",\"debug\",\"raw\",\"rendered\",\"json\"]" - ); -} - -#[test] -fn get_json_error() { - let actual = nu!("try { non_existent_command } catch {|err| $err} | get json | from json | update labels.span {{start: 0 end: 0}} | to json -r"); - assert_eq!( - actual.out, "{\"msg\":\"External command failed\",\"labels\":[{\"text\":\"Command `non_existent_command` not found\",\"span\":{\"start\":0,\"end\":0}}],\"code\":\"nu::shell::external_command\",\"url\":null,\"help\":\"`non_existent_command` is neither a Nushell built-in or a known external command\",\"inner\":[]}" - ); -} diff --git a/crates/nu-engine/src/eval_ir.rs b/crates/nu-engine/src/eval_ir.rs index 8d809f182e..233b01c33f 100644 --- a/crates/nu-engine/src/eval_ir.rs +++ b/crates/nu-engine/src/eval_ir.rs @@ -220,17 +220,8 @@ fn eval_ir_block_impl( } Err(err) => { if let Some(error_handler) = ctx.stack.error_handlers.pop(ctx.error_handler_base) { - let fancy_errors = match ctx.engine_state.get_config().error_style { - nu_protocol::ErrorStyle::Fancy => true, - nu_protocol::ErrorStyle::Plain => false, - }; // If an error handler is set, branch there - prepare_error_handler( - ctx, - error_handler, - Some(err.into_spanned(*span)), - fancy_errors, - ); + prepare_error_handler(ctx, error_handler, Some(err.into_spanned(*span))); pc = error_handler.handler_index; } else { // If not, exit the block with the error @@ -255,7 +246,6 @@ fn prepare_error_handler( ctx: &mut EvalContext<'_>, error_handler: ErrorHandler, error: Option>, - fancy_errors: bool, ) { if let Some(reg_id) = error_handler.error_register { if let Some(error) = error { @@ -264,10 +254,7 @@ fn prepare_error_handler( // Create the error value and put it in the register ctx.put_reg( reg_id, - error - .item - .into_value(error.span, fancy_errors) - .into_pipeline_data(), + error.item.into_value(error.span).into_pipeline_data(), ); } else { // Set the register to empty diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index d2ed11188a..232fc50b3d 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1067,27 +1067,30 @@ pub fn parse_internal_call( if let Some(arg_shape) = flag.arg { if let Some(arg) = spans.get(spans_idx + 1) { let arg = parse_value(working_set, *arg, &arg_shape); - let (arg_name, val_expression) = ensure_flag_arg_type( - working_set, - flag.long.clone(), - arg.clone(), - &arg_shape, - spans[spans_idx], - ); if flag.long.is_empty() { if let Some(short) = flag.short { call.add_named(( - arg_name, + Spanned { + item: String::new(), + span: spans[spans_idx], + }, Some(Spanned { item: short.to_string(), span: spans[spans_idx], }), - Some(val_expression), + Some(arg), )); } } else { - call.add_named((arg_name, None, Some(val_expression))); + call.add_named(( + Spanned { + item: flag.long.clone(), + span: spans[spans_idx], + }, + None, + Some(arg), + )); } spans_idx += 1; } else { @@ -5018,8 +5021,8 @@ pub fn parse_operator(working_set: &mut StateWorkingSet, span: Span) -> Expressi b"<=" => Operator::Comparison(Comparison::LessThanOrEqual), b">" => Operator::Comparison(Comparison::GreaterThan), b">=" => Operator::Comparison(Comparison::GreaterThanOrEqual), - b"=~" | b"like" => Operator::Comparison(Comparison::RegexMatch), - b"!~" | b"not-like" => Operator::Comparison(Comparison::NotRegexMatch), + b"=~" => Operator::Comparison(Comparison::RegexMatch), + b"!~" => Operator::Comparison(Comparison::NotRegexMatch), b"+" => Operator::Math(Math::Plus), b"++" => Operator::Math(Math::Append), b"-" => Operator::Math(Math::Minus), diff --git a/crates/nu-plugin/src/plugin/interface/mod.rs b/crates/nu-plugin/src/plugin/interface/mod.rs index be7b2e0dfc..fc40b9c732 100644 --- a/crates/nu-plugin/src/plugin/interface/mod.rs +++ b/crates/nu-plugin/src/plugin/interface/mod.rs @@ -1091,7 +1091,8 @@ fn set_pgrp_from_enter_foreground(pgrp: i64) -> Result<(), ShellError> { fn set_pgrp_from_enter_foreground(_pgrp: i64) -> Result<(), ShellError> { Err(ShellError::NushellFailed { msg: concat!( - "EnterForeground asked plugin to join process group, but this is not supported on non UNIX platforms.", + "EnterForeground asked plugin to join process group, but not supported on ", + cfg!(target_os) ) .into(), }) diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml index e5deba5fa2..5556ce4755 100644 --- a/crates/nu-protocol/Cargo.toml +++ b/crates/nu-protocol/Cargo.toml @@ -35,7 +35,6 @@ miette = { workspace = true, features = ["fancy-no-backtrace"] } num-format = { workspace = true } rmp-serde = { workspace = true, optional = true } serde = { workspace = true } -serde_json = { workspace = true } thiserror = "1.0" typetag = "0.2" os_pipe = { workspace = true, features = ["io_safety"] } diff --git a/crates/nu-protocol/src/ast/operator.rs b/crates/nu-protocol/src/ast/operator.rs index 8c2e59d93a..713c6c0060 100644 --- a/crates/nu-protocol/src/ast/operator.rs +++ b/crates/nu-protocol/src/ast/operator.rs @@ -115,8 +115,8 @@ impl Display for Operator { Operator::Comparison(Comparison::NotEqual) => write!(f, "!="), Operator::Comparison(Comparison::LessThan) => write!(f, "<"), Operator::Comparison(Comparison::GreaterThan) => write!(f, ">"), - Operator::Comparison(Comparison::RegexMatch) => write!(f, "=~ or like"), - Operator::Comparison(Comparison::NotRegexMatch) => write!(f, "!~ or not-like"), + Operator::Comparison(Comparison::RegexMatch) => write!(f, "=~"), + Operator::Comparison(Comparison::NotRegexMatch) => write!(f, "!~"), Operator::Comparison(Comparison::LessThanOrEqual) => write!(f, "<="), Operator::Comparison(Comparison::GreaterThanOrEqual) => write!(f, ">="), Operator::Comparison(Comparison::StartsWith) => write!(f, "starts-with"), diff --git a/crates/nu-protocol/src/errors/labeled_error.rs b/crates/nu-protocol/src/errors/labeled_error.rs index a207178415..c76a6c78dd 100644 --- a/crates/nu-protocol/src/errors/labeled_error.rs +++ b/crates/nu-protocol/src/errors/labeled_error.rs @@ -139,23 +139,6 @@ impl LabeledError { self } - pub fn render_error_to_string(diag: impl miette::Diagnostic, fancy_errors: bool) -> String { - let theme = if fancy_errors { - miette::GraphicalTheme::unicode() - } else { - miette::GraphicalTheme::none() - }; - - let mut out = String::new(); - miette::GraphicalReportHandler::new() - .with_width(80) - .with_theme(theme) - .render_report(&mut out, &diag) - .unwrap_or_default(); - - out - } - /// Create a [`LabeledError`] from a type that implements [`miette::Diagnostic`]. /// /// # Example diff --git a/crates/nu-protocol/src/errors/shell_error.rs b/crates/nu-protocol/src/errors/shell_error.rs index 49ece8323a..0f609061d6 100644 --- a/crates/nu-protocol/src/errors/shell_error.rs +++ b/crates/nu-protocol/src/errors/shell_error.rs @@ -1474,16 +1474,13 @@ impl ShellError { self.external_exit_code().map(|e| e.item).unwrap_or(1) } - pub fn into_value(self, span: Span, fancy_errors: bool) -> Value { + pub fn into_value(self, span: Span) -> Value { let exit_code = self.external_exit_code(); let mut record = record! { "msg" => Value::string(self.to_string(), span), "debug" => Value::string(format!("{self:?}"), span), - "raw" => Value::error(self.clone(), span), - // "labeled_error" => Value::string(LabeledError::from_diagnostic_and_render(self.clone()), span), - "rendered" => Value::string(ShellError::render_error_to_string(self.clone(), fancy_errors), span), - "json" => Value::string(serde_json::to_string(&self).expect("Could not serialize error"), span), + "raw" => Value::error(self, span), }; if let Some(code) = exit_code { @@ -1502,21 +1499,6 @@ impl ShellError { span, ) } - pub fn render_error_to_string(diag: impl miette::Diagnostic, fancy_errors: bool) -> String { - let theme = if fancy_errors { - miette::GraphicalTheme::unicode() - } else { - miette::GraphicalTheme::none() - }; - let mut out = String::new(); - miette::GraphicalReportHandler::new() - .with_width(80) - .with_theme(theme) - .render_report(&mut out, &diag) - .unwrap_or_default(); - - out - } } impl From for ShellError { diff --git a/crates/nu-protocol/src/module.rs b/crates/nu-protocol/src/module.rs index 02bac131dc..6b4aec0c60 100644 --- a/crates/nu-protocol/src/module.rs +++ b/crates/nu-protocol/src/module.rs @@ -161,25 +161,20 @@ impl Module { } let span = self.span.unwrap_or(backup_span); - - // only needs to bring `$module` with a record value if it defines any constants. - let constants = if const_rows.is_empty() { - vec![] - } else { - vec![( - final_name.clone(), - Value::record( - const_rows - .into_iter() - .map(|(name, val)| (String::from_utf8_lossy(&name).to_string(), val)) - .collect(), - span, - ), - )] - }; + let const_record = Value::record( + const_rows + .into_iter() + .map(|(name, val)| (String::from_utf8_lossy(&name).to_string(), val)) + .collect(), + span, + ); return ( - ResolvedImportPattern::new(decls, vec![(final_name.clone(), self_id)], constants), + ResolvedImportPattern::new( + decls, + vec![(final_name.clone(), self_id)], + vec![(final_name, const_record)], + ), errors, ); }; diff --git a/crates/nu-std/std/help/mod.nu b/crates/nu-std/std/help/mod.nu index 089bbff7f8..d608ae8bcb 100644 --- a/crates/nu-std/std/help/mod.nu +++ b/crates/nu-std/std/help/mod.nu @@ -47,8 +47,8 @@ def get-all-operators [] { return [ [Comparison, <=, LessThanOrEqual, "Checks if a value is less than or equal to another.", 80] [Comparison, >, GreaterThan, "Checks if a value is greater than another.", 80] [Comparison, >=, GreaterThanOrEqual, "Checks if a value is greater than or equal to another.", 80] - [Comparison, '=~ or like', RegexMatch, "Checks if a value matches a regular expression.", 80] - [Comparison, '!~ or not-like', NotRegexMatch, "Checks if a value does not match a regular expression.", 80] + [Comparison, =~, RegexMatch, "Checks if a value matches a regular expression.", 80] + [Comparison, !~, NotRegexMatch, "Checks if a value does not match a regular expression.", 80] [Comparison, in, In, "Checks if a value is in a list or string.", 80] [Comparison, not-in, NotIn, "Checks if a value is not in a list or string.", 80] [Comparison, starts-with, StartsWith, "Checks if a string starts with another.", 80] @@ -771,7 +771,7 @@ You can also learn more at (ansi default_italic)(ansi light_cyan_underline)https let modules = (try { modules $target_item --find $find }) if not ($modules | is-empty) { return $modules } - + if ($find | is-not-empty) { print -e $"No help results found mentioning: ($find)" return [] diff --git a/crates/nu_plugin_polars/src/dataframe/command/data/mod.rs b/crates/nu_plugin_polars/src/dataframe/command/data/mod.rs index 0857fff1da..058b277526 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/data/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/data/mod.rs @@ -32,7 +32,6 @@ mod sort_by_expr; pub mod sql_context; pub mod sql_expr; mod take; -mod unnest; mod unpivot; mod with_column; use filter::LazyFilter; @@ -110,6 +109,5 @@ pub(crate) fn data_commands() -> Vec &str { - "polars unnest" - } - - fn description(&self) -> &str { - "Decompose struct columns into separate columns for each of their fields. The new columns will be inserted into the dataframe at the location of the struct column." - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .rest("cols", SyntaxShape::String, "columns to unnest") - .category(Category::Custom("dataframe".into())) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Unnest a dataframe", - example: r#"[[id person]; [1 {name: "Bob", age: 36}] [2 {name: "Betty", age: 63}]] - | polars into-df -s {id: i64, person: {name: str, age: u8}} - | polars unnest person - | polars get id name age - | polars sort-by id"#, - result: Some( - NuDataFrame::from( - df!( - "id" => [1, 2], - "name" => ["Bob", "Betty"], - "age" => [36, 63] - ) - .expect("Should be able to create a simple dataframe"), - ) - .into_value(Span::test_data()), - ), - }, - Example { - description: "Unnest a lazy dataframe", - example: r#"[[id person]; [1 {name: "Bob", age: 36}] [2 {name: "Betty", age: 63}]] - | polars into-df -s {id: i64, person: {name: str, age: u8}} - | polars into-lazy - | polars unnest person - | polars select (polars col id) (polars col name) (polars col age) - | polars collect - | polars sort-by id"#, - result: Some( - NuDataFrame::from( - df!( - "id" => [1, 2], - "name" => ["Bob", "Betty"], - "age" => [36, 63] - ) - .expect("Should be able to create a simple dataframe"), - ) - .into_value(Span::test_data()), - ), - }, - ] - } - - fn run( - &self, - plugin: &Self::Plugin, - engine: &EngineInterface, - call: &EvaluatedCall, - input: PipelineData, - ) -> Result { - match PolarsPluginObject::try_from_pipeline(plugin, input, call.head)? { - PolarsPluginObject::NuDataFrame(df) => command_eager(plugin, engine, call, df), - PolarsPluginObject::NuLazyFrame(lazy) => command_lazy(plugin, engine, call, lazy), - _ => Err(ShellError::GenericError { - error: "Must be a dataframe or lazy dataframe".into(), - msg: "".into(), - span: Some(call.head), - help: None, - inner: vec![], - }), - } - .map_err(LabeledError::from) - } -} - -fn command_eager( - plugin: &PolarsPlugin, - engine: &EngineInterface, - call: &EvaluatedCall, - df: NuDataFrame, -) -> Result { - let cols = call.rest::(0)?; - let polars = df.to_polars(); - let result: NuDataFrame = polars - .unnest(cols) - .map_err(|e| ShellError::GenericError { - error: format!("Error unnesting dataframe: {e}"), - msg: "".into(), - span: Some(call.head), - help: None, - inner: vec![], - })? - .into(); - result.to_pipeline_data(plugin, engine, call.head) -} - -fn command_lazy( - plugin: &PolarsPlugin, - engine: &EngineInterface, - call: &EvaluatedCall, - df: NuLazyFrame, -) -> Result { - let cols = call.rest::(0)?; - - let polars = df.to_polars(); - let result: NuLazyFrame = polars.unnest(cols).into(); - result.to_pipeline_data(plugin, engine, call.head) -} - -#[cfg(test)] -mod test { - use crate::test::test_polars_plugin_command; - - use super::*; - - #[test] - fn test_examples() -> Result<(), ShellError> { - test_polars_plugin_command(&UnnestDF) - } -} diff --git a/crates/nu_plugin_polars/src/dataframe/command/data/unpivot.rs b/crates/nu_plugin_polars/src/dataframe/command/data/unpivot.rs index ffbbd66916..5235305de2 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/data/unpivot.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/data/unpivot.rs @@ -31,13 +31,13 @@ impl PluginCommand for UnpivotDF { Signature::build(self.name()) .required_named( "index", - SyntaxShape::List(Box::new(SyntaxShape::Any)), + SyntaxShape::Table(vec![]), "column names for unpivoting", Some('i'), ) .required_named( "on", - SyntaxShape::List(Box::new(SyntaxShape::Any)), + SyntaxShape::Table(vec![]), "column names used as value columns", Some('o'), ) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 183da649b8..bb2f1fcb35 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -16,4 +16,4 @@ profile = "default" # use in nushell, we may opt to use the bleeding edge stable version of rust. # I believe rust is on a 6 week release cycle and nushell is on a 4 week release cycle. # So, every two nushell releases, this version number should be bumped by one. -channel = "1.80.1" +channel = "1.79.0" diff --git a/tests/const_/mod.rs b/tests/const_/mod.rs index 0c4ff5d77c..f736b785ca 100644 --- a/tests/const_/mod.rs +++ b/tests/const_/mod.rs @@ -238,30 +238,13 @@ fn complex_const_export() { let actual = nu!(&inp.join("; ")); assert_eq!(actual.out, "eats"); - let inp = &[MODULE_SETUP, "use spam", "'none' in $spam.eggs.bacon"]; + let inp = &[ + MODULE_SETUP, + "use spam", + "($spam.eggs.bacon.none | is-empty)", + ]; let actual = nu!(&inp.join("; ")); - assert_eq!(actual.out, "false"); -} - -#[test] -fn only_nested_module_have_const() { - let setup = r#" - module spam { - export module eggs { - export module bacon { - export const viking = 'eats' - export module none {} - } - } - } - "#; - let inp = &[setup, "use spam", "$spam.eggs.bacon.viking"]; - let actual = nu!(&inp.join("; ")); - assert_eq!(actual.out, "eats"); - - let inp = &[setup, "use spam", "'none' in $spam.eggs.bacon"]; - let actual = nu!(&inp.join("; ")); - assert_eq!(actual.out, "false"); + assert_eq!(actual.out, "true"); } #[test] @@ -278,16 +261,20 @@ fn complex_const_glob_export() { let actual = nu!(&inp.join("; ")); assert_eq!(actual.out, "eats"); - let inp = &[MODULE_SETUP, "use spam *", "'none' in $eggs.bacon"]; + let inp = &[MODULE_SETUP, "use spam *", "($eggs.bacon.none | is-empty)"]; let actual = nu!(&inp.join("; ")); - assert_eq!(actual.out, "false"); + assert_eq!(actual.out, "true"); } #[test] fn complex_const_drill_export() { - let inp = &[MODULE_SETUP, "use spam eggs bacon none", "$none"]; + let inp = &[ + MODULE_SETUP, + "use spam eggs bacon none", + "($none | is-empty)", + ]; let actual = nu!(&inp.join("; ")); - assert!(actual.err.contains("variable not found")); + assert_eq!(actual.out, "true"); } #[test] diff --git a/tests/plugin_persistence/mod.rs b/tests/plugin_persistence/mod.rs index 587e4d480f..6729c657c7 100644 --- a/tests/plugin_persistence/mod.rs +++ b/tests/plugin_persistence/mod.rs @@ -12,7 +12,7 @@ fn plugin_list_shows_installed_plugins() { plugins: [("nu_plugin_inc"), ("nu_plugin_custom_values")], r#"(plugin list).name | str join ','"# ); - assert_eq!("custom_values,inc", out.out); + assert_eq!("inc,custom_values", out.out); assert!(out.status.success()); } @@ -34,15 +34,15 @@ fn plugin_keeps_running_after_calling_it() { plugin: ("nu_plugin_inc"), r#" plugin stop inc - (plugin list).0.status == running | print + (plugin list).0.is_running | print print ";" "2.0.0" | inc -m | ignore - (plugin list).0.status == running | print + (plugin list).0.is_running | print "# ); assert_eq!( "false;true", out.out, - "plugin list didn't show status = running" + "plugin list didn't show is_running = true" ); assert!(out.status.success()); } @@ -244,7 +244,7 @@ fn plugin_gc_can_be_configured_to_stop_plugins_immediately() { $env.config.plugin_gc = { default: { stop_after: 0sec } } "2.3.0" | inc -M sleep 100ms - (plugin list | where name == inc).0.status == running + (plugin list | where name == inc).0.is_running "# ); assert!(out.status.success()); @@ -261,7 +261,7 @@ fn plugin_gc_can_be_configured_to_stop_plugins_immediately() { } "2.3.0" | inc -M sleep 100ms - (plugin list | where name == inc).0.status == running + (plugin list | where name == inc).0.is_running "# ); assert!(out.status.success()); @@ -281,7 +281,7 @@ fn plugin_gc_can_be_configured_to_stop_plugins_after_delay() { while $cond { sleep 100ms $cond = ( - (plugin list | where name == inc).0.status == running and + (plugin list | where name == inc).0.is_running and ((date now) - $start) < 5sec ) } @@ -310,7 +310,7 @@ fn plugin_gc_can_be_configured_to_stop_plugins_after_delay() { while $cond { sleep 100ms $cond = ( - (plugin list | where name == inc).0.status == running and + (plugin list | where name == inc).0.is_running and ((date now) - $start) < 5sec ) } @@ -333,7 +333,7 @@ fn plugin_gc_can_be_configured_as_disabled() { r#" $env.config.plugin_gc = { default: { enabled: false, stop_after: 0sec } } "2.3.0" | inc -M - (plugin list | where name == inc).0.status == running + (plugin list | where name == inc).0.is_running "# ); assert!(out.status.success()); @@ -350,7 +350,7 @@ fn plugin_gc_can_be_configured_as_disabled() { } } "2.3.0" | inc -M - (plugin list | where name == inc).0.status == running + (plugin list | where name == inc).0.is_running "# ); assert!(out.status.success()); @@ -367,7 +367,7 @@ fn plugin_gc_can_be_disabled_by_plugin() { $env.config.plugin_gc = { default: { stop_after: 0sec } } example one 1 foo | ignore # ensure we've run the plugin with the new config sleep 100ms - (plugin list | where name == example).0.status == running + (plugin list | where name == example).0.is_running "# ); assert!(out.status.success()); diff --git a/tests/plugins/registry_file.rs b/tests/plugins/registry_file.rs index a2ca8735f0..2cb1473b6f 100644 --- a/tests/plugins/registry_file.rs +++ b/tests/plugins/registry_file.rs @@ -37,7 +37,7 @@ fn plugin_add_then_restart_nu() { --config $nu.config-path --env-config $nu.env-path --plugin-config $nu.plugin-path - --commands 'plugin list --engine | get name | to json --raw' + --commands 'plugin list | get name | to json --raw' ) ", example_plugin_path().display()) ); @@ -69,7 +69,7 @@ fn plugin_add_in_nu_plugin_dirs_const() { --config $nu.config-path --env-config $nu.env-path --plugin-config $nu.plugin-path - --commands 'plugin list --engine | get name | to json --raw' + --commands 'plugin list | get name | to json --raw' ) "#, dirname.display(), @@ -103,7 +103,7 @@ fn plugin_add_in_nu_plugin_dirs_env() { --config $nu.config-path --env-config $nu.env-path --plugin-config $nu.plugin-path - --commands 'plugin list --engine | get name | to json --raw' + --commands 'plugin list | get name | to json --raw' ) "#, dirname.display(), @@ -199,7 +199,7 @@ fn plugin_rm_then_restart_nu() { "--plugin-config", "test-plugin-file.msgpackz", "--commands", - "plugin list --engine | get name | to json --raw", + "plugin list | get name | to json --raw", ]) .assert() .success() @@ -364,7 +364,7 @@ fn warning_on_invalid_plugin_item() { "--plugin-config", "test-plugin-file.msgpackz", "--commands", - "plugin list --engine | get name | to json --raw", + "plugin list | get name | to json --raw", ]) .output() .expect("failed to run nu"); @@ -412,43 +412,6 @@ fn plugin_use_error_not_found() { }) } -#[test] -fn plugin_shows_up_in_default_plugin_list_after_add() { - let example_plugin_path = example_plugin_path(); - let result = nu_with_plugins!( - cwd: ".", - plugins: [], - &format!(r#" - plugin add '{}' - plugin list | get status | to json --raw - "#, example_plugin_path.display()) - ); - assert!(result.status.success()); - assert_eq!(r#"["added"]"#, result.out); -} - -#[test] -fn plugin_shows_removed_after_removing() { - let example_plugin_path = example_plugin_path(); - let result = nu_with_plugins!( - cwd: ".", - plugins: [], - &format!(r#" - plugin add '{}' - plugin list | get status | to json --raw - ( - ^$nu.current-exe - --config $nu.config-path - --env-config $nu.env-path - --plugin-config $nu.plugin-path - --commands 'plugin rm example; plugin list | get status | to json --raw' - ) - "#, example_plugin_path.display()) - ); - assert!(result.status.success()); - assert_eq!(r#"["removed"]"#, result.out); -} - #[test] fn plugin_add_and_then_use() { let example_plugin_path = example_plugin_path(); @@ -462,7 +425,7 @@ fn plugin_add_and_then_use() { --config $nu.config-path --env-config $nu.env-path --plugin-config $nu.plugin-path - --commands 'plugin use example; plugin list --engine | get name | to json --raw' + --commands 'plugin use example; plugin list | get name | to json --raw' ) "#, example_plugin_path.display()) ); @@ -483,7 +446,7 @@ fn plugin_add_and_then_use_by_filename() { --config $nu.config-path --env-config $nu.env-path --plugin-config $nu.plugin-path - --commands 'plugin use '{0}'; plugin list --engine | get name | to json --raw' + --commands 'plugin use '{0}'; plugin list | get name | to json --raw' ) "#, example_plugin_path.display()) ); @@ -508,7 +471,7 @@ fn plugin_add_then_use_with_custom_path() { cwd: dirs.test(), r#" plugin use --plugin-config test-plugin-file.msgpackz example - plugin list --engine | get name | to json --raw + plugin list | get name | to json --raw "# ); diff --git a/tests/repl/test_custom_commands.rs b/tests/repl/test_custom_commands.rs index a93d3fbba8..1710b35913 100644 --- a/tests/repl/test_custom_commands.rs +++ b/tests/repl/test_custom_commands.rs @@ -1,7 +1,6 @@ use crate::repl::tests::{fail_test, run_test, run_test_contains, TestResult}; use nu_test_support::nu; use pretty_assertions::assert_eq; -use rstest::rstest; #[test] fn no_scope_leak1() -> TestResult { @@ -74,21 +73,10 @@ fn custom_switch1() -> TestResult { ) } -#[rstest] -fn custom_flag_with_type_checking( - #[values( - ("int", "\"3\""), - ("int", "null"), - ("record", "{i: \"\"}"), - ("list", "[\"\"]") - )] - type_sig_value: (&str, &str), - #[values("--dry-run", "-d")] flag: &str, -) -> TestResult { - let (type_sig, value) = type_sig_value; - +#[test] +fn custom_flag_with_type_checking() -> TestResult { fail_test( - &format!("def florb [{flag}: {type_sig}] {{}}; let y = {value}; florb {flag} $y"), + r#"def florb [--dry-run: int] { $dry_run }; let y = "3"; florb --dry-run=$y"#, "type_mismatch", ) } diff --git a/tests/repl/test_modules.rs b/tests/repl/test_modules.rs index 289efd291a..dd62c74b77 100644 --- a/tests/repl/test_modules.rs +++ b/tests/repl/test_modules.rs @@ -120,11 +120,6 @@ fn export_consts() -> TestResult { ) } -#[test] -fn dont_export_module_name_as_a_variable() -> TestResult { - fail_test(r#"module spam { }; use spam; $spam"#, "variable not found") -} - #[test] fn func_use_consts() -> TestResult { run_test(