From 75ced3e945b8786d89c9996f5fe575cd1569f952 Mon Sep 17 00:00:00 2001 From: Piepmatz Date: Tue, 10 Dec 2024 13:10:28 +0100 Subject: [PATCH 01/26] Fix `table` command when targeting WASM (#14530) # Description In this PR I made the `cwd` parameter in the functions from the `table` command not used when targeting `not(feature = "os)`. As without an OS and therefore without filesystem we don't have any real concept of a current working directory. This allows using the `table` command in the WASM context. # User-Facing Changes None. # Tests + Formatting My tests timed out on the http stuff but I cannot think why this would trigger a test failure. Let's see what the CI finds out. # After Submitting --- crates/nu-command/src/viewers/table.rs | 56 +++++++++++++++++++++----- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 1768590b65..da57198efb 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -125,6 +125,7 @@ impl Command for Table { let val = Value::list(supported_table_modes(), Span::test_data()); return Ok(val.into_pipeline_data()); } + #[cfg(feature = "os")] let cwd = engine_state.cwd(Some(stack))?; let cfg = parse_table_config(call, engine_state, stack)?; let input = CmdInput::new(engine_state, stack, call, input); @@ -135,7 +136,12 @@ impl Command for Table { let _ = nu_utils::enable_vt_processing(); } - handle_table_command(input, cfg, cwd) + handle_table_command( + input, + cfg, + #[cfg(feature = "os")] + cwd, + ) } fn examples(&self) -> Vec { @@ -367,7 +373,7 @@ impl<'a> CmdInput<'a> { fn handle_table_command( mut input: CmdInput<'_>, cfg: TableConfig, - cwd: nu_path::PathBuf, + #[cfg(feature = "os")] cwd: nu_path::PathBuf, ) -> Result { let span = input.data.span().unwrap_or(input.call.head); match input.data { @@ -390,11 +396,25 @@ fn handle_table_command( let stream = ListStream::new(vals.into_iter(), span, signals); input.data = PipelineData::Empty; - handle_row_stream(input, cfg, stream, metadata, cwd) + handle_row_stream( + input, + cfg, + stream, + metadata, + #[cfg(feature = "os")] + cwd, + ) } PipelineData::ListStream(stream, metadata) => { input.data = PipelineData::Empty; - handle_row_stream(input, cfg, stream, metadata, cwd) + handle_row_stream( + input, + cfg, + stream, + metadata, + #[cfg(feature = "os")] + cwd, + ) } PipelineData::Value(Value::Record { val, .. }, ..) => { input.data = PipelineData::Empty; @@ -414,7 +434,14 @@ fn handle_table_command( let stream = ListStream::new(val.into_range_iter(span, Signals::empty()), span, signals); input.data = PipelineData::Empty; - handle_row_stream(input, cfg, stream, metadata, cwd) + handle_row_stream( + input, + cfg, + stream, + metadata, + #[cfg(feature = "os")] + cwd, + ) } x => Ok(x), } @@ -606,7 +633,7 @@ fn handle_row_stream( cfg: TableConfig, stream: ListStream, metadata: Option, - cwd: nu_path::PathBuf, + #[cfg(feature = "os")] cwd: nu_path::PathBuf, ) -> Result { let stream = match metadata.as_ref() { // First, `ls` sources: @@ -636,9 +663,14 @@ fn handle_row_stream( if let Some(value) = record.to_mut().get_mut("name") { let span = value.span(); if let Value::String { val, .. } = value { - if let Some(val) = - render_path_name(val, &config, &ls_colors, cwd.clone(), span) - { + if let Some(val) = render_path_name( + val, + &config, + &ls_colors, + #[cfg(feature = "os")] + cwd.clone(), + span, + ) { *value = val; } } @@ -1031,14 +1063,18 @@ fn render_path_name( path: &str, config: &Config, ls_colors: &LsColors, - cwd: nu_path::PathBuf, + #[cfg(feature = "os")] cwd: nu_path::PathBuf, span: Span, ) -> Option { if !config.ls.use_ls_colors { return None; } + #[cfg(feature = "os")] let fullpath = cwd.join(path); + #[cfg(not(feature = "os"))] + let fullpath = path; + let stripped_path = nu_utils::strip_ansi_unlikely(path); let metadata = std::fs::symlink_metadata(fullpath); let has_metadata = metadata.is_ok(); From fc29d826146afa9b7ac1fdb6807f25129b2d2ef8 Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Tue, 10 Dec 2024 07:14:43 -0500 Subject: [PATCH 02/26] Only run `from_string` conversion on strings (#14509) # Description #14249 loaded `convert_env_values()` several times to force more updates to `ENV_CONVERSION`. This allows the user to treat variables as structured data inside `config.nu` (and others). Unfortunately, `convert_env_values()` did not originally anticipate being called more than once, so it would attempt to re-convert values that had already been converted. This usually leads to an error in the conversion closure. With this PR, values are only converted with `from_string` if they are still strings; otherwise they are skipped and their existing value is used. # User-Facing Changes No user-facing change when compared to 0.100, since closures written for 0.100's `ENV_CONVERSION` now work again without errors. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` - # After Submitting Will remove the "workaround" from the Config doc preview. --- crates/nu-engine/src/env.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/nu-engine/src/env.rs b/crates/nu-engine/src/env.rs index dc6c354fce..bec885173a 100644 --- a/crates/nu-engine/src/env.rs +++ b/crates/nu-engine/src/env.rs @@ -33,14 +33,20 @@ pub fn convert_env_values(engine_state: &mut EngineState, stack: &Stack) -> Resu let env_vars = engine_state.render_env_vars(); for (name, val) in env_vars { - match get_converted_value(engine_state, stack, name, val, "from_string") { - ConversionResult::Ok(v) => { - let _ = new_scope.insert(name.to_string(), v); - } - ConversionResult::ConversionError(e) => error = error.or(Some(e)), - ConversionResult::CellPathError => { - let _ = new_scope.insert(name.to_string(), val.clone()); + if let Value::String { .. } = val { + // Only run from_string on string values + match get_converted_value(engine_state, stack, name, val, "from_string") { + ConversionResult::Ok(v) => { + let _ = new_scope.insert(name.to_string(), v); + } + ConversionResult::ConversionError(e) => error = error.or(Some(e)), + ConversionResult::CellPathError => { + let _ = new_scope.insert(name.to_string(), val.clone()); + } } + } else { + // Skip values that are already converted (not a string) + let _ = new_scope.insert(name.to_string(), val.clone()); } } From cf828146060aa891b66d9f63baad8cc3a59b0a2c Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Tue, 10 Dec 2024 07:36:05 -0500 Subject: [PATCH 03/26] Use const NU_LIB_DIRS in startup (#14549) # Description A slower, gentler alternative to #14531, in that we're just moving one setting *out* of `default_env.nu` in this PR ;-). All this does is transition from using `$env.NU_LIB_DIRS` in the startup config to `const $NU_LIB_DIRS`. Also updates the `sample_env.nu` to reflect the changes. Details: Before: `$env.NU_LIB_DIRS` was unnecessary set both in `main()` and in `default_env.nu` After: `$env.NU_LIB_DIRS` is only set in `main()` Before: `$env.NU_LIB_DIRS` was set to `config-dir/scripts` and `data-dir/completions` After: `$env.NU_LIB_DIRS` is set to an empty list, and `const NU_LIB_DIRS` is set to the directories above Before: Using `--include-path (-I)` would set the `$env.NU_LIB_DIRS` After: Using `--include-path (-I)` sets the constant `$NU_LIB_DIRS` # User-Facing Changes There shouldn't be any breaking changes here. The `$env.NU_LIBS_DIRS` still works for most cases. There are a few areas we need to clean-up to make sure that the const is usable (`nu-check`, et. al.) but they will still work in the meantime with the older `$env` version. # Tests + Formatting * Changed the Type-check on the `$env` version. * Added a type check for the const version. - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` # After Submitting Doc updates --- .../nu-utils/src/default_files/default_env.nu | 5 ---- .../nu-utils/src/default_files/sample_env.nu | 8 +++--- src/main.rs | 28 ++++++++++++++++--- tests/repl/test_env.rs | 12 +++++++- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/crates/nu-utils/src/default_files/default_env.nu b/crates/nu-utils/src/default_files/default_env.nu index cb85e519ba..f4c3f562ff 100644 --- a/crates/nu-utils/src/default_files/default_env.nu +++ b/crates/nu-utils/src/default_files/default_env.nu @@ -47,11 +47,6 @@ $env.ENV_CONVERSIONS = { } } -$env.NU_LIB_DIRS = $env.NU_LIB_DIRS? | default [ - ($nu.default-config-dir | path join 'scripts') # add /scripts - ($nu.data-dir | path join 'completions') # default home for nushell completions -] - $env.NU_PLUGIN_DIRS = $env.NU_PLUGIN_DIRS | default [ ($nu.default-config-dir | path join 'plugins') # add /plugins ] diff --git a/crates/nu-utils/src/default_files/sample_env.nu b/crates/nu-utils/src/default_files/sample_env.nu index 23dc925ccd..f44b8e1986 100644 --- a/crates/nu-utils/src/default_files/sample_env.nu +++ b/crates/nu-utils/src/default_files/sample_env.nu @@ -99,17 +99,17 @@ $env.ENV_CONVERSIONS = $env.ENV_CONVERSIONS | merge { # NU_LIB_DIRS # ----------- -# Directories in this environment variable are searched by the +# Directories in this constant are searched by the # `use` and `source` commands. # # By default, the `scripts` subdirectory of the default configuration # directory is included: -$env.NU_LIB_DIRS = [ +const NU_LIB_DIRS = [ ($nu.default-config-dir | path join 'scripts') # add /scripts ($nu.data-dir | path join 'completions') # default home for nushell completions ] -# You can replace (override) or append to this list: -$env.NU_LIB_DIRS ++= ($nu.default-config-dir | path join 'modules') +# You can replace (override) or append to this list by shadowing the constant +const NU_LIB_DIRS = $NU_LIB_DIRS ++ [($nu.default-config-dir | path join 'modules')] # NU_PLUGIN_DIRS # -------------- diff --git a/src/main.rs b/src/main.rs index bef8d07caf..7898988844 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ use nu_lsp::LanguageServer; use nu_path::canonicalize_with; use nu_protocol::{ engine::EngineState, report_shell_error, ByteStream, Config, IntoValue, PipelineData, - ShellError, Span, Spanned, Value, + ShellError, Span, Spanned, Type, Value, }; use nu_std::load_standard_library; use nu_utils::perf; @@ -147,13 +147,25 @@ fn main() -> Result<()> { let mut default_nu_lib_dirs_path = nushell_config_path.clone(); default_nu_lib_dirs_path.push("scripts"); - engine_state.add_env_var( - "NU_LIB_DIRS".to_string(), + // env.NU_LIB_DIRS to be replaced by constant (below) - Eventual deprecation + // but an empty list for now to allow older code to work + engine_state.add_env_var("NU_LIB_DIRS".to_string(), Value::test_list(vec![])); + + let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state); + let var_id = working_set.add_variable( + b"$NU_LIB_DIRS".into(), + Span::unknown(), + Type::List(Box::new(Type::String)), + false, + ); + working_set.set_variable_const_val( + var_id, Value::test_list(vec![ Value::test_string(default_nu_lib_dirs_path.to_string_lossy()), Value::test_string(default_nushell_completions_path.to_string_lossy()), ]), ); + engine_state.merge_delta(working_set.render())?; let mut default_nu_plugin_dirs_path = nushell_config_path; default_nu_plugin_dirs_path.push("plugins"); @@ -273,7 +285,15 @@ fn main() -> Result<()> { .map(|x| Value::string(x.trim().to_string(), span)) .collect(); - engine_state.add_env_var("NU_LIB_DIRS".into(), Value::list(vals, span)); + let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state); + let var_id = working_set.add_variable( + b"$NU_LIB_DIRS".into(), + span, + Type::List(Box::new(Type::String)), + false, + ); + working_set.set_variable_const_val(var_id, Value::list(vals, span)); + engine_state.merge_delta(working_set.render())?; } perf!("NU_LIB_DIRS setup", start_time, use_color); diff --git a/tests/repl/test_env.rs b/tests/repl/test_env.rs index 7963f7580b..f0a2070c30 100644 --- a/tests/repl/test_env.rs +++ b/tests/repl/test_env.rs @@ -17,8 +17,18 @@ fn shorthand_env_3() -> TestResult { } #[test] -fn default_nu_lib_dirs_type() { +fn default_nu_lib_dirs_env_type() { + // Previously, this was a list + // While we are transitioning to const NU_LIB_DIRS + // the env version will be empty, and thus a + // list let actual = nu!("$env.NU_LIB_DIRS | describe"); + assert_eq!(actual.out, "list"); +} + +#[test] +fn default_nu_lib_dirs_type() { + let actual = nu!("$NU_LIB_DIRS | describe"); assert_eq!(actual.out, "list"); } From 3515e3ee28129c8ec939c31eb4c74b8dae69debe Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Tue, 10 Dec 2024 07:36:27 -0500 Subject: [PATCH 04/26] Remove grid icons deprecation warning (#14526) # Description Noticed this TODO, so I did as it said. # User-Facing Changes N/A (the functionality was already removed) # Tests + Formatting N/A # After Submitting N/A --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> --- crates/nu-protocol/src/config/error.rs | 2 ++ crates/nu-protocol/src/config/mod.rs | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/nu-protocol/src/config/error.rs b/crates/nu-protocol/src/config/error.rs index b13dceeb02..c8fbd3f85a 100644 --- a/crates/nu-protocol/src/config/error.rs +++ b/crates/nu-protocol/src/config/error.rs @@ -65,6 +65,8 @@ impl<'a> ConfigErrors<'a> { }); } + // We'll probably need this again in the future so allow dead code for now + #[allow(dead_code)] pub fn deprecated_option(&mut self, path: &ConfigPath, suggestion: &'static str, span: Span) { self.error(ConfigError::Deprecated { path: path.to_string(), diff --git a/crates/nu-protocol/src/config/mod.rs b/crates/nu-protocol/src/config/mod.rs index c66c41e455..85ae9ce1e3 100644 --- a/crates/nu-protocol/src/config/mod.rs +++ b/crates/nu-protocol/src/config/mod.rs @@ -156,10 +156,6 @@ impl UpdateFromValue for Config { "filesize" => self.filesize.update(val, path, errors), "explore" => self.explore.update(val, path, errors), "color_config" => self.color_config.update(val, path, errors), - "use_grid_icons" => { - // TODO: delete it after 0.99 - errors.deprecated_option(path, "use `grid -i`", val.span()); - } "footer_mode" => self.footer_mode.update(val, path, errors), "float_precision" => self.float_precision.update(val, path, errors), "use_ansi_coloring" => self.use_ansi_coloring.update(val, path, errors), From 7d2e8875e0d9c19d74501cc69bde0103a040dd2e Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Tue, 10 Dec 2024 07:08:53 -0800 Subject: [PATCH 05/26] Make `timeit` take only closures as an argument (#14483) # Description Fixes #14401 where expressions passed to `timeit` will execute twice. This PR removes the expression support for `timeit`, as this behavior is almost exclusive to `timeit` and can hinder migration to the IR evaluator in the future. Additionally, `timeit` used to be able to take a `block` as an argument. Blocks should probably only be allowed for parser keywords, so this PR changes `timeit` to instead only take closures as an argument. This also fixes an issue where environment updates inside the `timeit` block would affect the parent scope and all commands later in the pipeline. ```nu > timeit { $env.FOO = 'bar' }; print $env.FOO bar ``` # User-Facing Changes `timeit` now only takes a closure as the first argument. # After Submitting Update examples in the book/docs if necessary. --- crates/nu-command/src/debug/timeit.rs | 60 ++++++++----------- .../nu-command/tests/commands/debug/timeit.rs | 2 +- crates/nu-engine/src/closure_eval.rs | 39 ++++++++++++ 3 files changed, 65 insertions(+), 36 deletions(-) diff --git a/crates/nu-command/src/debug/timeit.rs b/crates/nu-command/src/debug/timeit.rs index 7bb492769c..182cab87d7 100644 --- a/crates/nu-command/src/debug/timeit.rs +++ b/crates/nu-command/src/debug/timeit.rs @@ -1,4 +1,5 @@ -use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression_with_input}; +use nu_engine::{command_prelude::*, ClosureEvalOnce}; +use nu_protocol::engine::Closure; use std::time::Instant; #[derive(Clone)] @@ -10,16 +11,18 @@ impl Command for TimeIt { } fn description(&self) -> &str { - "Time the running time of a block." + "Time how long it takes a closure to run." + } + + fn extra_description(&self) -> &str { + "Any pipeline input given to this command is passed to the closure. Note that streaming inputs may affect timing results, and it is recommended to add a `collect` command before this if the input is a stream. + +This command will bubble up any errors encountered when running the closure. The return pipeline of the closure is collected into a value and then discarded." } fn signature(&self) -> nu_protocol::Signature { Signature::build("timeit") - .required( - "command", - SyntaxShape::OneOf(vec![SyntaxShape::Block, SyntaxShape::Expression]), - "The command or block to run.", - ) + .required("command", SyntaxShape::Closure(None), "The closure to run.") .input_output_types(vec![ (Type::Any, Type::Duration), (Type::Nothing, Type::Duration), @@ -46,51 +49,38 @@ impl Command for TimeIt { // reset outdest, so the command can write to stdout and stderr. let stack = &mut stack.push_redirection(None, None); - let command_to_run = call.positional_nth(stack, 0); + let closure: Closure = call.req(engine_state, stack, 0)?; + let closure = ClosureEvalOnce::new_preserve_out_dest(engine_state, stack, closure); // Get the start time after all other computation has been done. let start_time = Instant::now(); + closure.run_with_input(input)?.into_value(call.head)?; + let time = start_time.elapsed(); - if let Some(command_to_run) = command_to_run { - if let Some(block_id) = command_to_run.as_block() { - let eval_block = get_eval_block(engine_state); - let block = engine_state.get_block(block_id); - eval_block(engine_state, stack, block, input)? - } else { - let eval_expression_with_input = get_eval_expression_with_input(engine_state); - let expression = &command_to_run.clone(); - eval_expression_with_input(engine_state, stack, expression, input)? - } - } else { - PipelineData::empty() - } - .into_value(call.head)?; - - let end_time = Instant::now(); - - let output = Value::duration( - end_time.saturating_duration_since(start_time).as_nanos() as i64, - call.head, - ); - + let output = Value::duration(time.as_nanos() as i64, call.head); Ok(output.into_pipeline_data()) } fn examples(&self) -> Vec { vec![ Example { - description: "Times a command within a closure", + description: "Time a closure containing one command", example: "timeit { sleep 500ms }", result: None, }, Example { - description: "Times a command using an existing input", - example: "http get https://www.nushell.sh/book/ | timeit { split chars }", + description: "Time a closure with an input value", + example: "'A really long string' | timeit { split chars }", result: None, }, Example { - description: "Times a command invocation", - example: "timeit ls -la", + description: "Time a closure with an input stream", + example: "open some_file.txt | collect | timeit { split chars }", + result: None, + }, + Example { + description: "Time a closure containing a pipeline", + example: "timeit { open some_file.txt | split chars }", result: None, }, ] diff --git a/crates/nu-command/tests/commands/debug/timeit.rs b/crates/nu-command/tests/commands/debug/timeit.rs index a59f67d26a..509f5bc4e7 100644 --- a/crates/nu-command/tests/commands/debug/timeit.rs +++ b/crates/nu-command/tests/commands/debug/timeit.rs @@ -2,7 +2,7 @@ use nu_test_support::nu; #[test] fn timeit_show_stdout() { - let actual = nu!("let t = timeit nu --testbin cococo abcdefg"); + let actual = nu!("let t = timeit { nu --testbin cococo abcdefg }"); assert_eq!(actual.out, "abcdefg"); } diff --git a/crates/nu-engine/src/closure_eval.rs b/crates/nu-engine/src/closure_eval.rs index b271d90cbe..66c6287cca 100644 --- a/crates/nu-engine/src/closure_eval.rs +++ b/crates/nu-engine/src/closure_eval.rs @@ -88,6 +88,29 @@ impl ClosureEval { } } + pub fn new_preserve_out_dest( + engine_state: &EngineState, + stack: &Stack, + closure: Closure, + ) -> Self { + let engine_state = engine_state.clone(); + let stack = stack.captures_to_stack_preserve_out_dest(closure.captures); + let block = engine_state.get_block(closure.block_id).clone(); + let env_vars = stack.env_vars.clone(); + let env_hidden = stack.env_hidden.clone(); + let eval = get_eval_block_with_early_return(&engine_state); + + Self { + engine_state, + stack, + block, + arg_index: 0, + env_vars, + env_hidden, + eval, + } + } + /// Sets whether to enable debugging when evaluating the closure. /// /// By default, this is controlled by the [`EngineState`] used to create this [`ClosureEval`]. @@ -189,6 +212,22 @@ impl<'a> ClosureEvalOnce<'a> { } } + pub fn new_preserve_out_dest( + engine_state: &'a EngineState, + stack: &Stack, + closure: Closure, + ) -> Self { + let block = engine_state.get_block(closure.block_id); + let eval = get_eval_block_with_early_return(engine_state); + Self { + engine_state, + stack: stack.captures_to_stack_preserve_out_dest(closure.captures), + block, + arg_index: 0, + eval, + } + } + /// Sets whether to enable debugging when evaluating the closure. /// /// By default, this is controlled by the [`EngineState`] used to create this [`ClosureEvalOnce`]. From 8f9aa1a250029cf7352152703cbe34c27e05e6f2 Mon Sep 17 00:00:00 2001 From: 132ikl <132@ikl.sh> Date: Tue, 10 Dec 2024 10:27:30 -0500 Subject: [PATCH 06/26] Change `help commands` to use name from scope instead of the name from the declaration (#14490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Before this PR, `help commands` uses the name from a command's declaration rather than the name in the scope. This is problematic when trying to view the help page for the `main` command of a module. For example, `std bench`: ```nushell use std/bench help bench # => Error: nu::parser::not_found # => # => × Not found. # => ╭─[entry #10:1:6] # => 1 │ help bench # => · ──┬── # => · ╰── did not find anything under this name # => ╰──── ``` This can also cause confusion when importing specific commands from modules. Furthermore, if there are multiple commands with the same name from different modules, the help text for _both_ will appear when querying their help text (this is especially problematic for `main` commands, see #14033): ```nushell use std/iter help iter find # => Error: nu::parser::not_found # => # => × Not found. # => ╭─[entry #3:1:6] # => 1│ help iter find # => · ────┬──── # => · ╰── did not find anything under this name # => ╰──── help find # => Searches terms in the input. # => # => Search terms: filter, regex, search, condition # => # => Usage: # => > find {flags} ...(rest) # [...] # => Returns the first element of the list that matches the # => closure predicate, `null` otherwise # [...] # (full text omitted for brevity) ``` This PR changes `help commands` to use the name as it is in scope, so prefixing any command in scope with `help` will show the correct help text. ```nushell use std/bench help bench # [help text for std bench] use std/iter help iter find # [help text for std iter find] use std help std bench # [help text for std bench] help std iter find # [help text for std iter find] ``` Additionally, the IR code generation for commands called with the `--help` text has been updated to reflect this change. This does have one side effect: when a module has a `main` command defined, running `help ` (which checks `help aliases`, then `help commands`, then `help modules`) will show the help text for the `main` command rather than the module. The help text for the module is still accessible with `help modules `. Fixes #10499, #10311, #11609, #13470, #14033, and #14402. Partially fixes #10707. Does **not** fix #11447. # User-Facing Changes * Help text for commands can be obtained by running `help `, where the command name is the same thing you would type in order to execute the command. Previously, it was the name of the function as written in the source file. * For example, for the following module `spam` with command `meow`: ```nushell module spam { # help text export def meow [] {} } ``` * Before this PR: * Regardless of how `meow` is `use`d, the help text is viewable by running `help meow`. * After this PR: * When imported with `use spam`: The `meow` command is executed by running `spam meow` and the `help` text is viewable by running `help spam meow`. * When imported with `use spam foo`: The `meow` command is executed by running `meow` and the `help` text is viewable by running `meow`. * When a module has a `main` command defined, `help ` will return help for the main command, rather than the module. To access the help for the module, use `help modules `. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` # After Submitting N/A --- crates/nu-command/src/help/help_commands.rs | 19 ++------ crates/nu-command/src/help/help_externs.rs | 19 ++------ crates/nu-engine/src/compile/call.rs | 11 +++-- .../src/engine/state_working_set.rs | 45 +++++++++++++++---- 4 files changed, 49 insertions(+), 45 deletions(-) diff --git a/crates/nu-command/src/help/help_commands.rs b/crates/nu-command/src/help/help_commands.rs index f0f8df9c02..9d3ab9c924 100644 --- a/crates/nu-command/src/help/help_commands.rs +++ b/crates/nu-command/src/help/help_commands.rs @@ -87,21 +87,10 @@ pub fn help_commands( name.push_str(&r.item); } - let output = engine_state - .get_decls_sorted(false) - .into_iter() - .filter_map(|(_, decl_id)| { - let decl = engine_state.get_decl(decl_id); - (decl.name() == name).then_some(decl) - }) - .map(|cmd| get_full_help(cmd, engine_state, stack)) - .collect::>(); - - if !output.is_empty() { - Ok( - Value::string(output.join("======================\n\n"), call.head) - .into_pipeline_data(), - ) + if let Some(decl) = engine_state.find_decl(name.as_bytes(), &[]) { + let cmd = engine_state.get_decl(decl); + let help_text = get_full_help(cmd, engine_state, stack); + Ok(Value::string(help_text, call.head).into_pipeline_data()) } else { Err(ShellError::CommandNotFound { span: Span::merge_many(rest.iter().map(|s| s.span)), diff --git a/crates/nu-command/src/help/help_externs.rs b/crates/nu-command/src/help/help_externs.rs index af07835af4..27775b416e 100644 --- a/crates/nu-command/src/help/help_externs.rs +++ b/crates/nu-command/src/help/help_externs.rs @@ -107,21 +107,10 @@ pub fn help_externs( name.push_str(&r.item); } - let output = engine_state - .get_decls_sorted(false) - .into_iter() - .filter_map(|(_, decl_id)| { - let decl = engine_state.get_decl(decl_id); - (decl.name() == name).then_some(decl) - }) - .map(|cmd| get_full_help(cmd, engine_state, stack)) - .collect::>(); - - if !output.is_empty() { - Ok( - Value::string(output.join("======================\n\n"), call.head) - .into_pipeline_data(), - ) + if let Some(decl) = engine_state.find_decl(name.as_bytes(), &[]) { + let cmd = engine_state.get_decl(decl); + let help_text = get_full_help(cmd, engine_state, stack); + Ok(Value::string(help_text, call.head).into_pipeline_data()) } else { Err(ShellError::CommandNotFound { span: Span::merge_many(rest.iter().map(|s| s.span)), diff --git a/crates/nu-engine/src/compile/call.rs b/crates/nu-engine/src/compile/call.rs index 4112e889b1..e58a7b3efe 100644 --- a/crates/nu-engine/src/compile/call.rs +++ b/crates/nu-engine/src/compile/call.rs @@ -20,12 +20,11 @@ pub(crate) fn compile_call( // Check if this call has --help - if so, just redirect to `help` if call.named_iter().any(|(name, _, _)| name.item == "help") { - return compile_help( - working_set, - builder, - decl.name().into_spanned(call.head), - io_reg, - ); + let name = working_set + .find_decl_name(call.decl_id) // check for name in scope + .and_then(|name| std::str::from_utf8(name).ok()) + .unwrap_or(decl.name()); // fall back to decl's name + return compile_help(working_set, builder, name.into_spanned(call.head), io_reg); } // Try to figure out if this is a keyword call like `if`, and handle those specially diff --git a/crates/nu-protocol/src/engine/state_working_set.rs b/crates/nu-protocol/src/engine/state_working_set.rs index 0d59068dbf..5cbc959f63 100644 --- a/crates/nu-protocol/src/engine/state_working_set.rs +++ b/crates/nu-protocol/src/engine/state_working_set.rs @@ -459,21 +459,48 @@ impl<'a> StateWorkingSet<'a> { } // check overlay in perma - for overlay_frame in self - .permanent_state - .active_overlays(&removed_overlays) - .rev() - { - visibility.append(&overlay_frame.visibility); + self.permanent_state.find_decl(name, &removed_overlays) + } + + pub fn find_decl_name(&self, decl_id: DeclId) -> Option<&[u8]> { + let mut removed_overlays = vec![]; + + let mut visibility: Visibility = Visibility::new(); + + for scope_frame in self.delta.scope.iter().rev() { + if self.search_predecls { + for (name, id) in scope_frame.predecls.iter() { + if id == &decl_id { + return Some(name); + } + } + } + + // check overlay in delta + for overlay_frame in scope_frame.active_overlays(&mut removed_overlays).rev() { + visibility.append(&overlay_frame.visibility); + + if self.search_predecls { + for (name, id) in overlay_frame.predecls.iter() { + if id == &decl_id { + return Some(name); + } + } + } - if let Some(decl_id) = overlay_frame.get_decl(name) { if visibility.is_decl_id_visible(&decl_id) { - return Some(decl_id); + for (name, id) in overlay_frame.decls.iter() { + if id == &decl_id { + return Some(name); + } + } } } } - None + // check overlay in perma + self.permanent_state + .find_decl_name(decl_id, &removed_overlays) } pub fn find_module(&self, name: &[u8]) -> Option { From dff6268d664f1511088394c32d424a12959c8747 Mon Sep 17 00:00:00 2001 From: Wind Date: Wed, 11 Dec 2024 01:22:56 +0800 Subject: [PATCH 07/26] du: add `-l/--long` flag, remove `-a/--all` flag (#14407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Closes: #14387 ~To make it happen, just need to added `-l` flag to `du`, and pass it to `DirBuilder`, `DirInfo`, `FileInfo` Then tweak `impl From for Value` and `impl From for Value` impl.~ --- Edit: this PR is going to: 1. Exclude directories and files columns by default 2. Added `-l/--long` flag to output directories and files columns 3. When running `du`, it will output the files as well. Previously it doesn't output the size of file. To make it happen, just need to added `-r` flag to `du`, and pass it to `DirBuilder`, `DirInfo`, `FileInfo` Then tweak `impl From for Value` and `impl From for Value` impl. And rename some variables. # User-Facing Changes `du` is no longer output `directories` and `file` columns by default, added `-r` flag will show `directories` column, `-f` flag will show `files` column. ```nushell > du nushell ╭───┬────────────────────────────────────┬──────────┬──────────╮ │ # │ path │ apparent │ physical │ ├───┼────────────────────────────────────┼──────────┼──────────┤ │ 0 │ /home/windsoilder/projects/nushell │ 34.6 GiB │ 34.7 GiB │ ├───┼────────────────────────────────────┼──────────┼──────────┤ │ # │ path │ apparent │ physical │ ╰───┴────────────────────────────────────┴──────────┴──────────╯ > du nushell --recursive --files # It outputs two more columns, `directories` and `files`, but the output is too long to paste here. ``` # Tests + Formatting Added 1 test # After Submitting NaN --- crates/nu-command/src/filesystem/du.rs | 29 ++++---- crates/nu-command/src/platform/dir_info.rs | 83 +++++++++++++++------- crates/nu-command/tests/commands/du.rs | 14 ++++ 3 files changed, 84 insertions(+), 42 deletions(-) diff --git a/crates/nu-command/src/filesystem/du.rs b/crates/nu-command/src/filesystem/du.rs index 0981d2c0ee..15dc0d78d6 100644 --- a/crates/nu-command/src/filesystem/du.rs +++ b/crates/nu-command/src/filesystem/du.rs @@ -12,8 +12,8 @@ pub struct Du; #[derive(Deserialize, Clone, Debug)] pub struct DuArgs { path: Option>, - all: bool, deref: bool, + long: bool, exclude: Option>, #[serde(rename = "max-depth")] max_depth: Option>, @@ -49,6 +49,11 @@ impl Command for Du { "Dereference symlinks to their targets for size", Some('r'), ) + .switch( + "long", + "Get underlying directories and files for each entry", + Some('l'), + ) .named( "exclude", SyntaxShape::GlobPattern, @@ -94,8 +99,8 @@ impl Command for Du { }); } } - let all = call.has_flag(engine_state, stack, "all")?; let deref = call.has_flag(engine_state, stack, "deref")?; + let long = call.has_flag(engine_state, stack, "long")?; let exclude = call.get_flag(engine_state, stack, "exclude")?; #[allow(deprecated)] let current_dir = current_dir(engine_state, stack)?; @@ -111,8 +116,8 @@ impl Command for Du { None => { let args = DuArgs { path: None, - all, deref, + long, exclude, max_depth, min_size, @@ -127,8 +132,8 @@ impl Command for Du { for p in paths { let args = DuArgs { path: Some(p), - all, deref, + long, exclude: exclude.clone(), max_depth, min_size, @@ -174,7 +179,6 @@ fn du_for_one_pattern( }) })?; - let include_files = args.all; let mut paths = match args.path { Some(p) => nu_engine::glob_from(&p, current_dir, span, None), // The * pattern should never fail. @@ -188,17 +192,10 @@ fn du_for_one_pattern( None, ), } - .map(|f| f.1)? - .filter(move |p| { - if include_files { - true - } else { - matches!(p, Ok(f) if f.is_dir()) - } - }); + .map(|f| f.1)?; - let all = args.all; let deref = args.deref; + let long = args.long; let max_depth = args.max_depth.map(|f| f.item as u64); let min_size = args.min_size.map(|f| f.item as u64); @@ -207,7 +204,7 @@ fn du_for_one_pattern( min: min_size, deref, exclude, - all, + long, }; let mut output: Vec = vec![]; @@ -216,7 +213,7 @@ fn du_for_one_pattern( Ok(a) => { if a.is_dir() { output.push(DirInfo::new(a, ¶ms, max_depth, span, signals)?.into()); - } else if let Ok(v) = FileInfo::new(a, deref, span) { + } else if let Ok(v) = FileInfo::new(a, deref, span, params.long) { output.push(v.into()); } } diff --git a/crates/nu-command/src/platform/dir_info.rs b/crates/nu-command/src/platform/dir_info.rs index 10ce4f5420..9b8ea1929e 100644 --- a/crates/nu-command/src/platform/dir_info.rs +++ b/crates/nu-command/src/platform/dir_info.rs @@ -9,7 +9,7 @@ pub struct DirBuilder { pub min: Option, pub deref: bool, pub exclude: Option, - pub all: bool, + pub long: bool, } impl DirBuilder { @@ -18,14 +18,14 @@ impl DirBuilder { min: Option, deref: bool, exclude: Option, - all: bool, + long: bool, ) -> DirBuilder { DirBuilder { tag, min, deref, exclude, - all, + long, } } } @@ -39,6 +39,7 @@ pub struct DirInfo { blocks: u64, path: PathBuf, tag: Span, + long: bool, } #[derive(Debug, Clone)] @@ -47,10 +48,16 @@ pub struct FileInfo { size: u64, blocks: Option, tag: Span, + long: bool, } impl FileInfo { - pub fn new(path: impl Into, deref: bool, tag: Span) -> Result { + pub fn new( + path: impl Into, + deref: bool, + tag: Span, + long: bool, + ) -> Result { let path = path.into(); let m = if deref { std::fs::metadata(&path) @@ -67,6 +74,7 @@ impl FileInfo { blocks: block_size, size: d.len(), tag, + long, }) } Err(e) => Err(e.into()), @@ -92,6 +100,7 @@ impl DirInfo { blocks: 0, tag: params.tag, path, + long: params.long, }; match std::fs::metadata(&s.path) { @@ -154,13 +163,13 @@ impl DirInfo { .as_ref() .map_or(true, |x| !x.matches_path(&f)); if include { - match FileInfo::new(f, params.deref, self.tag) { + match FileInfo::new(f, params.deref, self.tag, self.long) { Ok(file) => { let inc = params.min.map_or(true, |s| file.size >= s); if inc { self.size += file.size; self.blocks += file.blocks.unwrap_or(0); - if params.all { + if params.long { self.files.push(file); } } @@ -197,16 +206,27 @@ impl From for Value { // }) // } - Value::record( - record! { - "path" => Value::string(d.path.display().to_string(), d.tag), - "apparent" => Value::filesize(d.size as i64, d.tag), - "physical" => Value::filesize(d.blocks as i64, d.tag), - "directories" => value_from_vec(d.dirs, d.tag), - "files" => value_from_vec(d.files, d.tag) - }, - d.tag, - ) + if d.long { + Value::record( + record! { + "path" => Value::string(d.path.display().to_string(), d.tag), + "apparent" => Value::filesize(d.size as i64, d.tag), + "physical" => Value::filesize(d.blocks as i64, d.tag), + "directories" => value_from_vec(d.dirs, d.tag), + "files" => value_from_vec(d.files, d.tag) + }, + d.tag, + ) + } else { + Value::record( + record! { + "path" => Value::string(d.path.display().to_string(), d.tag), + "apparent" => Value::filesize(d.size as i64, d.tag), + "physical" => Value::filesize(d.blocks as i64, d.tag), + }, + d.tag, + ) + } } } @@ -215,16 +235,27 @@ impl From for Value { // cols.push("errors".into()); // vals.push(Value::nothing(Span::unknown())); - Value::record( - record! { - "path" => Value::string(f.path.display().to_string(), f.tag), - "apparent" => Value::filesize(f.size as i64, f.tag), - "physical" => Value::filesize(f.blocks.unwrap_or(0) as i64, f.tag), - "directories" => Value::nothing(Span::unknown()), - "files" => Value::nothing(Span::unknown()), - }, - f.tag, - ) + if f.long { + Value::record( + record! { + "path" => Value::string(f.path.display().to_string(), f.tag), + "apparent" => Value::filesize(f.size as i64, f.tag), + "physical" => Value::filesize(f.blocks.unwrap_or(0) as i64, f.tag), + "directories" => Value::nothing(Span::unknown()), + "files" => Value::nothing(Span::unknown()), + }, + f.tag, + ) + } else { + Value::record( + record! { + "path" => Value::string(f.path.display().to_string(), f.tag), + "apparent" => Value::filesize(f.size as i64, f.tag), + "physical" => Value::filesize(f.blocks.unwrap_or(0) as i64, f.tag), + }, + f.tag, + ) + } } } diff --git a/crates/nu-command/tests/commands/du.rs b/crates/nu-command/tests/commands/du.rs index 1e22d54f2f..c88eb546be 100644 --- a/crates/nu-command/tests/commands/du.rs +++ b/crates/nu-command/tests/commands/du.rs @@ -100,3 +100,17 @@ fn du_with_multiple_path() { let actual = nu!(cwd: "tests/fixtures", "du ...[] | length"); assert_eq!(actual.out, "0"); } + +#[test] +fn test_du_output_columns() { + let actual = nu!( + cwd: "tests/fixtures/formats", + "du -m 1 | columns | str join ','" + ); + assert_eq!(actual.out, "path,apparent,physical"); + let actual = nu!( + cwd: "tests/fixtures/formats", + "du -m 1 -l | columns | str join ','" + ); + assert_eq!(actual.out, "path,apparent,physical,directories,files"); +} From e4bb248142b99ce384d6dda06f27aba7654fa568 Mon Sep 17 00:00:00 2001 From: RobbingDaHood <16130319+RobbingDaHood@users.noreply.github.com> Date: Wed, 11 Dec 2024 02:39:36 +0100 Subject: [PATCH 08/26] =?UTF-8?q?For=20`#`=20to=20start=20a=20comment,=20t?= =?UTF-8?q?hen=20it=20either=20need=20to=20be=20the=20first=20chara?= =?UTF-8?q?=E2=80=A6=20(#14548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR should close 1. #10327 1. #13667 1. #13810 1. #14129 # Description For `#` to start a comment, then it either need to be the first character of the token or prefixed with ` ` (space). So now you can do this: ``` ~/Projects/nushell> 1..10 | each {echo test#testing } 12/05/2024 05:37:19 PM ╭───┬──────────────╮ │ 0 │ test#testing │ │ 1 │ test#testing │ │ 2 │ test#testing │ │ 3 │ test#testing │ │ 4 │ test#testing │ │ 5 │ test#testing │ │ 6 │ test#testing │ │ 7 │ test#testing │ │ 8 │ test#testing │ │ 9 │ test#testing │ ╰───┴──────────────╯ ``` # User-Facing Changes It is a breaking change if anyone expected comments to start in the middle of a string without any prefixing ` ` (space). # Tests + Formatting Did all: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library # After Submitting I cant see that I need to update anything in [the documentation](https://github.com/nushell/nushell.github.io) but please point me in the direction if there is anything. --------- Co-authored-by: Wind --- crates/nu-parser/src/lex.rs | 7 +++++-- crates/nu-parser/tests/test_lex.rs | 23 +++++++++++++++++++++++ tests/repl/test_parser.rs | 23 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index f0802fcd7a..04c3922154 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -51,7 +51,7 @@ impl BlockKind { } // A baseline token is terminated if it's not nested inside of a paired -// delimiter and the next character is one of: `|`, `;`, `#` or any +// delimiter and the next character is one of: `|`, `;` or any // whitespace. fn is_item_terminator( block_level: &[BlockKind], @@ -115,6 +115,7 @@ pub fn lex_item( // character (whitespace, `|`, `;` or `#`) is encountered, the baseline // token is done. // - Otherwise, accumulate the character into the current baseline token. + let mut previous_char = None; while let Some(c) = input.get(*curr_offset) { let c = *c; @@ -151,7 +152,8 @@ pub fn lex_item( if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { break; } - in_comment = true; + // To start a comment, It either need to be the first character of the token or prefixed with space. + in_comment = previous_char.map(|pc| pc == b' ').unwrap_or(true); } else if c == b'\n' || c == b'\r' { in_comment = false; if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { @@ -254,6 +256,7 @@ pub fn lex_item( } *curr_offset += 1; + previous_char = Some(c); } let span = Span::new(span_offset + token_start, span_offset + *curr_offset); diff --git a/crates/nu-parser/tests/test_lex.rs b/crates/nu-parser/tests/test_lex.rs index a14843f3f0..54ff674bb9 100644 --- a/crates/nu-parser/tests/test_lex.rs +++ b/crates/nu-parser/tests/test_lex.rs @@ -159,6 +159,29 @@ fn lex_comment() { ); } +#[test] +fn lex_not_comment_needs_space_in_front_of_hashtag() { + let file = b"1..10 | each {echo test#testing }"; + + let output = lex(file, 0, &[], &[], false); + + assert!(output.1.is_none()); +} + +#[test] +fn lex_comment_with_space_in_front_of_hashtag() { + let file = b"1..10 | each {echo test #testing }"; + + let output = lex(file, 0, &[], &[], false); + + assert!(output.1.is_some()); + assert!(matches!( + output.1.unwrap(), + ParseError::UnexpectedEof(missing_token, span) if missing_token == "}" + && span == Span::new(33, 34) + )); +} + #[test] fn lex_is_incomplete() { let file = b"let x = 300 | ;"; diff --git a/tests/repl/test_parser.rs b/tests/repl/test_parser.rs index f77d431110..05a7c512cb 100644 --- a/tests/repl/test_parser.rs +++ b/tests/repl/test_parser.rs @@ -169,6 +169,24 @@ fn comment_skipping_in_pipeline_3() -> TestResult { ) } +#[test] +fn still_string_if_hashtag_is_middle_of_string() -> TestResult { + run_test(r#"echo test#testing"#, "test#testing") +} + +#[test] +fn still_string_if_hashtag_is_middle_of_string_inside_each() -> TestResult { + run_test( + r#"1..1 | each {echo test#testing } | get 0"#, + "test#testing", + ) +} + +#[test] +fn still_string_if_hashtag_is_middle_of_string_inside_each_also_with_dot() -> TestResult { + run_test(r#"1..1 | each {echo '.#testing' } | get 0"#, ".#testing") +} + #[test] fn bad_var_name() -> TestResult { fail_test(r#"let $"foo bar" = 4"#, "can't contain") @@ -282,6 +300,11 @@ fn raw_string_with_equals() -> TestResult { ) } +#[test] +fn raw_string_with_hashtag() -> TestResult { + run_test(r#"r##' one # two '##"#, "one # two") +} + #[test] fn list_quotes_with_equals() -> TestResult { run_test( From 4f20c370f90a935fc6a999f732a92dc0e928c6c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 09:40:09 +0800 Subject: [PATCH 09/26] Bump scraper from 0.21.0 to 0.22.0 (#14557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [scraper](https://github.com/causal-agent/scraper) from 0.21.0 to 0.22.0.
Release notes

Sourced from scraper's releases.

v0.22.0

What's Changed

Full Changelog: https://github.com/rust-scraper/scraper/compare/v0.21.0...v0.22.0

Commits
  • dcf5e0c Version 0.22.0
  • 932ed03 Merge pull request #222 from rust-scraper/bump-ego-tree
  • 483ecab Bump ego-tree to version 0.10.0
  • 26f04ed Merge pull request #221 from rust-scraper/sorted-vec-instead-of-hash-table
  • ee66ee8 Drop hash table for per-element attributes for more compact sorted vector.
  • 8d3e74b Merge pull request #220 from rust-scraper/make-clippy-happy
  • 47cc9de Make current nightly version of Clippy happy.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=scraper&package-manager=cargo&previous-version=0.21.0&new-version=0.22.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 9 ++++----- crates/nu_plugin_query/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a50d71724..fac1ad9ff1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,9 +1418,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ego-tree" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6ba7d4eec39eaa9ab24d44a0e73a7949a1095a8b3f3abb11eddf27dbb56a53" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" [[package]] name = "either" @@ -6085,11 +6085,10 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scraper" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0e749d29b2064585327af5038a5a8eb73aeebad4a3472e83531a436563f7208" +checksum = "cc3d051b884f40e309de6c149734eab57aa8cc1347992710dc80bcc1c2194c15" dependencies = [ - "ahash 0.8.11", "cssparser", "ego-tree", "html5ever 0.29.0", diff --git a/crates/nu_plugin_query/Cargo.toml b/crates/nu_plugin_query/Cargo.toml index 431b728f62..260b909c90 100644 --- a/crates/nu_plugin_query/Cargo.toml +++ b/crates/nu_plugin_query/Cargo.toml @@ -20,7 +20,7 @@ nu-plugin = { path = "../nu-plugin", version = "0.100.1" } nu-protocol = { path = "../nu-protocol", version = "0.100.1" } gjson = "0.8" -scraper = { default-features = false, version = "0.21" } +scraper = { default-features = false, version = "0.22" } sxd-document = "0.3" sxd-xpath = "0.4" webpage = { version = "2.0.1", features = ["serde"] } From 1a573d17c016be109357d91bb3bb7ab057aecc2e Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Wed, 11 Dec 2024 07:08:15 -0600 Subject: [PATCH 10/26] =?UTF-8?q?Revert=20"For=20`#`=20to=20start=20a=20co?= =?UTF-8?q?mment,=20then=20it=20either=20need=20to=20be=20the=20first=20ch?= =?UTF-8?q?ara=E2=80=A6"=20(#14560)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts nushell/nushell#14548 I'm finding may oddities --- crates/nu-parser/src/lex.rs | 7 ++----- crates/nu-parser/tests/test_lex.rs | 23 ----------------------- tests/repl/test_parser.rs | 23 ----------------------- 3 files changed, 2 insertions(+), 51 deletions(-) diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index 04c3922154..f0802fcd7a 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -51,7 +51,7 @@ impl BlockKind { } // A baseline token is terminated if it's not nested inside of a paired -// delimiter and the next character is one of: `|`, `;` or any +// delimiter and the next character is one of: `|`, `;`, `#` or any // whitespace. fn is_item_terminator( block_level: &[BlockKind], @@ -115,7 +115,6 @@ pub fn lex_item( // character (whitespace, `|`, `;` or `#`) is encountered, the baseline // token is done. // - Otherwise, accumulate the character into the current baseline token. - let mut previous_char = None; while let Some(c) = input.get(*curr_offset) { let c = *c; @@ -152,8 +151,7 @@ pub fn lex_item( if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { break; } - // To start a comment, It either need to be the first character of the token or prefixed with space. - in_comment = previous_char.map(|pc| pc == b' ').unwrap_or(true); + in_comment = true; } else if c == b'\n' || c == b'\r' { in_comment = false; if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { @@ -256,7 +254,6 @@ pub fn lex_item( } *curr_offset += 1; - previous_char = Some(c); } let span = Span::new(span_offset + token_start, span_offset + *curr_offset); diff --git a/crates/nu-parser/tests/test_lex.rs b/crates/nu-parser/tests/test_lex.rs index 54ff674bb9..a14843f3f0 100644 --- a/crates/nu-parser/tests/test_lex.rs +++ b/crates/nu-parser/tests/test_lex.rs @@ -159,29 +159,6 @@ fn lex_comment() { ); } -#[test] -fn lex_not_comment_needs_space_in_front_of_hashtag() { - let file = b"1..10 | each {echo test#testing }"; - - let output = lex(file, 0, &[], &[], false); - - assert!(output.1.is_none()); -} - -#[test] -fn lex_comment_with_space_in_front_of_hashtag() { - let file = b"1..10 | each {echo test #testing }"; - - let output = lex(file, 0, &[], &[], false); - - assert!(output.1.is_some()); - assert!(matches!( - output.1.unwrap(), - ParseError::UnexpectedEof(missing_token, span) if missing_token == "}" - && span == Span::new(33, 34) - )); -} - #[test] fn lex_is_incomplete() { let file = b"let x = 300 | ;"; diff --git a/tests/repl/test_parser.rs b/tests/repl/test_parser.rs index 05a7c512cb..f77d431110 100644 --- a/tests/repl/test_parser.rs +++ b/tests/repl/test_parser.rs @@ -169,24 +169,6 @@ fn comment_skipping_in_pipeline_3() -> TestResult { ) } -#[test] -fn still_string_if_hashtag_is_middle_of_string() -> TestResult { - run_test(r#"echo test#testing"#, "test#testing") -} - -#[test] -fn still_string_if_hashtag_is_middle_of_string_inside_each() -> TestResult { - run_test( - r#"1..1 | each {echo test#testing } | get 0"#, - "test#testing", - ) -} - -#[test] -fn still_string_if_hashtag_is_middle_of_string_inside_each_also_with_dot() -> TestResult { - run_test(r#"1..1 | each {echo '.#testing' } | get 0"#, ".#testing") -} - #[test] fn bad_var_name() -> TestResult { fail_test(r#"let $"foo bar" = 4"#, "can't contain") @@ -300,11 +282,6 @@ fn raw_string_with_equals() -> TestResult { ) } -#[test] -fn raw_string_with_hashtag() -> TestResult { - run_test(r#"r##' one # two '##"#, "one # two") -} - #[test] fn list_quotes_with_equals() -> TestResult { run_test( From 0872e9c3ae4876db433002a17d4742978dd0fcd9 Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:41:06 -0500 Subject: [PATCH 11/26] Allow both NU_PLUGIN_DIRS const and env at the same time (#14553) # Description Fix #14544 and is also the reciprocal of #14549. Before: If both a const and env `NU_PLUGIN_DIRS` were defined at the same time, the env paths would not be used. After: The directories from `const NU_PLUGIN_DIRS` are searched for a matching filename, and if not found, `$env.NU_PLUGIN_DIRS` directories will be searched. Before: `$env.NU_PLUGIN_DIRS` was unnecessary set both in main() and in default_env.nu After: `$env.NU_PLUGIN_DIRS` is only set in main() Before: `$env.NU_PLUGIN_DIRS` was set to `plugins` in the config directory After: `$env.NU_PLUGIN_DIRS` is set to an empty list and `const NU_PLUGIN_DIRS` is set to the directory above. Also updates `sample_env.nu` to use the `const` # User-Facing Changes Most scenarios should work just fine as there continues to be an `$env.NU_PLUGIN_DIRS` to append to or override. However, there is a small chance of a breaking change if someone was *querying* the old default `$env.NU_PLUGIN_DIRS`. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` Also updated the `env` tests and added one for the `const`. # After Submitting Config doc updates --- crates/nu-cmd-plugin/src/util.rs | 22 ++++++++++++------- .../nu-utils/src/default_files/default_env.nu | 4 ---- .../nu-utils/src/default_files/sample_env.nu | 6 +++-- src/main.rs | 13 +++++++++-- tests/repl/test_env.rs | 12 +++++++++- 5 files changed, 40 insertions(+), 17 deletions(-) diff --git a/crates/nu-cmd-plugin/src/util.rs b/crates/nu-cmd-plugin/src/util.rs index 80d1a766b4..57de225ace 100644 --- a/crates/nu-cmd-plugin/src/util.rs +++ b/crates/nu-cmd-plugin/src/util.rs @@ -135,18 +135,24 @@ pub(crate) fn get_plugin_dirs( engine_state: &EngineState, stack: &Stack, ) -> impl Iterator { - // Get the NU_PLUGIN_DIRS constant or env var + // Get the NU_PLUGIN_DIRS from the constant and/or env var let working_set = StateWorkingSet::new(engine_state); - let value = working_set + let dirs_from_const = working_set .find_variable(b"$NU_PLUGIN_DIRS") .and_then(|var_id| working_set.get_constant(var_id).ok()) - .or_else(|| stack.get_env_var(engine_state, "NU_PLUGIN_DIRS")) - .cloned(); // TODO: avoid this clone - - // Get all of the strings in the list, if possible - value + .cloned() // TODO: avoid this clone .into_iter() .flat_map(|value| value.into_list().ok()) .flatten() - .flat_map(|list_item| list_item.coerce_into_string().ok()) + .flat_map(|list_item| list_item.coerce_into_string().ok()); + + let dirs_from_env = stack + .get_env_var(engine_state, "NU_PLUGIN_DIRS") + .cloned() // TODO: avoid this clone + .into_iter() + .flat_map(|value| value.into_list().ok()) + .flatten() + .flat_map(|list_item| list_item.coerce_into_string().ok()); + + dirs_from_const.chain(dirs_from_env) } diff --git a/crates/nu-utils/src/default_files/default_env.nu b/crates/nu-utils/src/default_files/default_env.nu index f4c3f562ff..2e2d66f0bc 100644 --- a/crates/nu-utils/src/default_files/default_env.nu +++ b/crates/nu-utils/src/default_files/default_env.nu @@ -46,7 +46,3 @@ $env.ENV_CONVERSIONS = { to_string: { |v| $v | path expand --no-symlink | str join (char esep) } } } - -$env.NU_PLUGIN_DIRS = $env.NU_PLUGIN_DIRS | default [ - ($nu.default-config-dir | path join 'plugins') # add /plugins -] diff --git a/crates/nu-utils/src/default_files/sample_env.nu b/crates/nu-utils/src/default_files/sample_env.nu index f44b8e1986..ea323c6c22 100644 --- a/crates/nu-utils/src/default_files/sample_env.nu +++ b/crates/nu-utils/src/default_files/sample_env.nu @@ -113,13 +113,15 @@ const NU_LIB_DIRS = $NU_LIB_DIRS ++ [($nu.default-config-dir | path join 'module # NU_PLUGIN_DIRS # -------------- -# Directories to search for plugin binaries when calling register. +# Directories to search for plugin binaries when calling add. # By default, the `plugins` subdirectory of the default configuration # directory is included: -$env.NU_PLUGIN_DIRS = [ +const NU_PLUGIN_DIRS = [ ($nu.default-config-dir | path join 'plugins') # add /plugins ] +# You can replace (override) or append to this list by shadowing the constant +const NU_PLUGIN_DIRS = $NU_PLUGIN_DIRS ++ [($nu.default-config-dir | path join 'plugins')] # Appending to the OS path is a common configuration task. # Because of the previous ENV_CONVERSIONS (performed internally diff --git a/src/main.rs b/src/main.rs index 7898988844..1c82e58851 100644 --- a/src/main.rs +++ b/src/main.rs @@ -169,12 +169,21 @@ fn main() -> Result<()> { let mut default_nu_plugin_dirs_path = nushell_config_path; default_nu_plugin_dirs_path.push("plugins"); - engine_state.add_env_var( - "NU_PLUGIN_DIRS".to_string(), + engine_state.add_env_var("NU_PLUGIN_DIRS".to_string(), Value::test_list(vec![])); + let mut working_set = nu_protocol::engine::StateWorkingSet::new(&engine_state); + let var_id = working_set.add_variable( + b"$NU_PLUGIN_DIRS".into(), + Span::unknown(), + Type::List(Box::new(Type::String)), + false, + ); + working_set.set_variable_const_val( + var_id, Value::test_list(vec![Value::test_string( default_nu_plugin_dirs_path.to_string_lossy(), )]), ); + engine_state.merge_delta(working_set.render())?; // End: Default NU_LIB_DIRS, NU_PLUGIN_DIRS // This is the real secret sauce to having an in-memory sqlite db. You must diff --git a/tests/repl/test_env.rs b/tests/repl/test_env.rs index f0a2070c30..d540ce2fd4 100644 --- a/tests/repl/test_env.rs +++ b/tests/repl/test_env.rs @@ -33,7 +33,17 @@ fn default_nu_lib_dirs_type() { } #[test] -fn default_nu_plugin_dirs_type() { +fn default_nu_plugin_dirs_env_type() { + // Previously, this was a list + // While we are transitioning to const NU_PLUGIN_DIRS + // the env version will be empty, and thus a + // list let actual = nu!("$env.NU_PLUGIN_DIRS | describe"); + assert_eq!(actual.out, "list"); +} + +#[test] +fn default_nu_plugin_dirs_type() { + let actual = nu!("$NU_PLUGIN_DIRS | describe"); assert_eq!(actual.out, "list"); } From 035b882db1e719e8f5e77ff8516eb977c2e290bf Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:43:20 -0500 Subject: [PATCH 12/26] Update sample and scaffold files (#14568) # Description Tidying up some of the wording of the sample and scaffold files to align with our current recommendations: * Continue to generate a commented-only `env.nu` and `config.nu` on first launch. * The generated `env.nu` mentions that most configuration can be done in `config.nu` * The `sample_env.nu` mentions the same. I might try getting rid of `config env --sample` entirely (it's new since 0.100 anyway). * All configuration is now documented "in-shell" in `sample_config.nu`, which can be viewed using `config nu --sample` - This means that environment variables that used to be in `sample_env.nu` have been moved to `sample_config.new`. # User-Facing Changes Doc-only # Tests + Formatting Doc-only changes, but: - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` # After Submitting Need to work on updates to Config chapter --- .../src/default_files/sample_config.nu | 142 +++++++++++++++++ .../nu-utils/src/default_files/sample_env.nu | 145 +----------------- .../src/default_files/scaffold_env.nu | 19 +-- 3 files changed, 158 insertions(+), 148 deletions(-) diff --git a/crates/nu-utils/src/default_files/sample_config.nu b/crates/nu-utils/src/default_files/sample_config.nu index 143e56aae4..ceb65835cd 100644 --- a/crates/nu-utils/src/default_files/sample_config.nu +++ b/crates/nu-utils/src/default_files/sample_config.nu @@ -785,3 +785,145 @@ $env.config.explore = { }, selected_cell: { bg: light_blue }, } + +# --------------------------------------------------------------------------------------- +# Environment Variables +# --------------------------------------------------------------------------------------- + +# In addition to the $env.config record, a number of other environment variables +# also affect Nushell's behavior: + +# PROMPT_* +# -------- +# Prompt configuration +# PROMPT_ variables accept either a string or a closure that returns a string + +# PROMPT_COMMAND +# -------------- +# Defines the primary prompt. Note that the PROMPT_INDICATOR (below) is appended to this value. +# Simple example - Static string: +$env.PROMPT_COMMAND = "Nushell" +# Simple example - Dynamic closure displaying the path: +$env.PROMPT_COMMAND = {|| pwd} + +# PROMPT_COMMAND_RIGHT +# -------------------- +# Defines a prompt which will appear right-aligned in the terminal +$env.PROMPT_COMMAND_RIGHT = {|| date now | format date "%d-%a %r" } + +# PROMPT_INDICATOR* +# ----------------- +# The prompt indicators are environmental variables that represent +# the state of the prompt. The specified character(s) will appear +# immediately following the PROMPT_COMMAND + +# When in Emacs mode (default): +$env.PROMPT_INDICATOR = "> " + +# When in normal vi mode: +$env.PROMPT_INDICATOR_VI_NORMAL = "> " +# When in vi insert-mode: +$env.PROMPT_INDICATOR_VI_INSERT = ": " + +# When a commandline extends across multiple lines: +$env.PROMPT_MULTILINE_INDICATOR = "::: " + +# TRANSIENT_PROMPT_* +# ------------------ +# Allows a different prompt to be shown after a command has been executed. This +# can be useful if you have a 2-line prompt. Instead of each previously-entered +# command taking up at least 2 lines, the transient prompt can condense it to a +# shorter version. The following example shows a rocket emoji before each +# previously-entered command: +$env.TRANSIENT_PROMPT_COMMAND = "🚀 " +$env.TRANSIENT_PROMPT_INDICATOR = "" +$env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = "" +$env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = "" +# Tip: Removing the transient multiline indicator and right-prompt can simplify +# copying from the terminal +$env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = "" +$env.TRANSIENT_PROMPT_COMMAND_RIGHT = "" + +# ENV_CONVERSIONS +# --------------- +# Certain variables, such as those containing multiple paths, are often stored as a +# colon-separated string in other shells. Nushell can convert these automatically to a +# more convenient Nushell list. The ENV_CONVERSIONS variable specifies how environment +# variables are: +# - converted from a string to a value on Nushell startup (from_string) +# - converted from a value back to a string when running external commands (to_string) +# +# Note: The OS Path variable is automatically converted before env.nu loads, so it can +# be treated a list in this file. +# +# Note: Environment variables are not case-sensitive, so the following will work +# for both Windows and Unix-like platforms. +# +# By default, the internal conversion looks something like the following, so there +# is no need to add this in your actual env.nu: +$env.ENV_CONVERSIONS = { + "Path": { + from_string: { |s| $s | split row (char esep) | path expand --no-symlink } + to_string: { |v| $v | path expand --no-symlink | str join (char esep) } + } +} + +# Here's an example converts the XDG_DATA_DIRS variable to and from a list: +$env.ENV_CONVERSIONS = $env.ENV_CONVERSIONS | merge { + "XDG_DATA_DIRS": { + from_string: { |s| $s | split row (char esep) | path expand --no-symlink } + to_string: { |v| $v | path expand --no-symlink | str join (char esep) } + } +} +# +# Other common directory-lists for conversion: TERMINFO_DIRS. +# Note that other variable conversions take place after `config.nu` is loaded. + +# NU_LIB_DIRS +# ----------- +# Directories in this constant are searched by the +# `use` and `source` commands. +# +# By default, the `scripts` subdirectory of the default configuration +# directory is included: +const NU_LIB_DIRS = [ + ($nu.default-config-dir | path join 'scripts') # add /scripts + ($nu.data-dir | path join 'completions') # default home for nushell completions +] +# You can replace (override) or append to this list by shadowing the constant +const NU_LIB_DIRS = $NU_LIB_DIRS ++ [($nu.default-config-dir | path join 'modules')] + +# An environment variable version of this also exists. It is searched after the constant. +$env.NU_LIB_DIRS ++= [ ($nu.data-dir | path join "nu_scripts") ] + +# NU_PLUGIN_DIRS +# -------------- +# Directories to search for plugin binaries when calling add. + +# By default, the `plugins` subdirectory of the default configuration +# directory is included: +const NU_PLUGIN_DIRS = [ + ($nu.default-config-dir | path join 'plugins') # add /plugins +] +# You can replace (override) or append to this list by shadowing the constant +const NU_PLUGIN_DIRS = $NU_PLUGIN_DIRS ++ [($nu.default-config-dir | path join 'plugins')] + +# As with NU_LIB_DIRS, an $env.NU_PLUGIN_DIRS is searched after the constant version + +# Appending to the OS path is a common configuration task. +# Because of the previous ENV_CONVERSIONS (performed internally +# before your config.nu loads), the path variable is a list that can +# be appended to using, for example: +$env.path ++= "~/.local/bin" + +# Or prepend using +$env.path = "~/.local/bin" ++ $env.path + +# The `path add` function from the Standard Library also provides +# a convenience method for prepending to the path: +use std/util "path add" +path add "~/.local/bin" +path add ($env.CARGO_HOME | path join "bin") + +# You can remove duplicate directories from the path using: +$env.PATH = ($env.PATH | uniq) diff --git a/crates/nu-utils/src/default_files/sample_env.nu b/crates/nu-utils/src/default_files/sample_env.nu index ea323c6c22..c081c87609 100644 --- a/crates/nu-utils/src/default_files/sample_env.nu +++ b/crates/nu-utils/src/default_files/sample_env.nu @@ -1,142 +1,9 @@ # Sample Nushell Environment Config File # -# Environment variables are usually configured in `env.nu`. Nushell -# sets sensible defaults for many environment variables, so the user's -# `env.nu` only needs to override these defaults if desired. -# -# This file serves as simple "in-shell" documentation for these -# settings, or you can view a more complete discussion online at: -# https://nushell.sh/book/configuration -# -# You can pretty-print and page this file using: -# config env --sample | nu-highlight | less -R +# Previously, environment variables were typically configured in `env.nu`. +# In general, most configuration can and should be performed in `config.nu` +# or one of the autoload directories. -# PROMPT_* -# -------- -# Prompt configuration -# PROMPT_ variables accept either a string or a closure that returns a string - -# PROMPT_COMMAND -# -------------- -# Defines the primary prompt. Note that the PROMPT_INDICATOR (below) is appended to this value. -# Simple example - Static string: -$env.PROMPT_COMMAND = "Nushell" -# Simple example - Dynamic closure displaying the path: -$env.PROMPT_COMMAND = {|| pwd} - -# PROMPT_COMMAND_RIGHT -# -------------------- -# Defines a prompt which will appear right-aligned in the terminal -$env.PROMPT_COMMAND_RIGHT = {|| date now | format date "%d-%a %r" } - -# PROMPT_INDICATOR* -# ----------------- -# The prompt indicators are environmental variables that represent -# the state of the prompt. The specified character(s) will appear -# immediately following the PROMPT_COMMAND - -# When in Emacs mode (default): -$env.PROMPT_INDICATOR = "> " - -# When in normal vi mode: -$env.PROMPT_INDICATOR_VI_NORMAL = "> " -# When in vi insert-mode: -$env.PROMPT_INDICATOR_VI_INSERT = ": " - -# When a commandline extends across multiple lines: -$env.PROMPT_MULTILINE_INDICATOR = "::: " - -# TRANSIENT_PROMPT_* -# ------------------ -# Allows a different prompt to be shown after a command has been executed. This -# can be useful if you have a 2-line prompt. Instead of each previously-entered -# command taking up at least 2 lines, the transient prompt can condense it to a -# shorter version. The following example shows a rocket emoji before each -# previously-entered command: -$env.TRANSIENT_PROMPT_COMMAND = "🚀 " -$env.TRANSIENT_PROMPT_INDICATOR = "" -$env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = "" -$env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = "" -# Tip: Removing the transient multiline indicator and right-prompt can simplify -# copying from the terminal -$env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = "" -$env.TRANSIENT_PROMPT_COMMAND_RIGHT = "" - -# ENV_CONVERSIONS -# --------------- -# Certain variables, such as those containing multiple paths, are often stored as a -# colon-separated string in other shells. Nushell can convert these automatically to a -# more convenient Nushell list. The ENV_CONVERSIONS variable specifies how environment -# variables are: -# - converted from a string to a value on Nushell startup (from_string) -# - converted from a value back to a string when running external commands (to_string) -# -# Note: The OS Path variable is automatically converted before env.nu loads, so it can -# be treated a list in this file. -# -# Note: Environment variables are not case-sensitive, so the following will work -# for both Windows and Unix-like platforms. -# -# By default, the internal conversion looks something like the following, so there -# is no need to add this in your actual env.nu: -$env.ENV_CONVERSIONS = { - "Path": { - from_string: { |s| $s | split row (char esep) | path expand --no-symlink } - to_string: { |v| $v | path expand --no-symlink | str join (char esep) } - } -} - -# Here's an example converts the XDG_DATA_DIRS variable to and from a list: -$env.ENV_CONVERSIONS = $env.ENV_CONVERSIONS | merge { - "XDG_DATA_DIRS": { - from_string: { |s| $s | split row (char esep) | path expand --no-symlink } - to_string: { |v| $v | path expand --no-symlink | str join (char esep) } - } -} -# -# Other common directory-lists for conversion: TERMINFO_DIRS. -# Note that other variable conversions take place after `config.nu` is loaded. - -# NU_LIB_DIRS -# ----------- -# Directories in this constant are searched by the -# `use` and `source` commands. -# -# By default, the `scripts` subdirectory of the default configuration -# directory is included: -const NU_LIB_DIRS = [ - ($nu.default-config-dir | path join 'scripts') # add /scripts - ($nu.data-dir | path join 'completions') # default home for nushell completions -] -# You can replace (override) or append to this list by shadowing the constant -const NU_LIB_DIRS = $NU_LIB_DIRS ++ [($nu.default-config-dir | path join 'modules')] - -# NU_PLUGIN_DIRS -# -------------- -# Directories to search for plugin binaries when calling add. - -# By default, the `plugins` subdirectory of the default configuration -# directory is included: -const NU_PLUGIN_DIRS = [ - ($nu.default-config-dir | path join 'plugins') # add /plugins -] -# You can replace (override) or append to this list by shadowing the constant -const NU_PLUGIN_DIRS = $NU_PLUGIN_DIRS ++ [($nu.default-config-dir | path join 'plugins')] - -# Appending to the OS path is a common configuration task. -# Because of the previous ENV_CONVERSIONS (performed internally -# before your env.nu loads), the path variable is a list that can -# be appended to using, for example: -$env.path ++= "~/.local/bin" - -# Or prepend using -$env.path = "~/.local/bin" ++ $env.path - -# The `path add` function from the Standard Library also provides -# a convenience method for prepending to the path: -use std/util "path add" -path add "~/.local/bin" -path add ($env.CARGO_HOME | path join "bin") - -# You can remove duplicate directories from the path using: -$env.PATH = ($env.PATH | uniq) +# To pretty-print the in-shell documentation for Nushell's various configuration +# settings, you can run: +config nu --sample | nu-highlight | less -R \ No newline at end of file diff --git a/crates/nu-utils/src/default_files/scaffold_env.nu b/crates/nu-utils/src/default_files/scaffold_env.nu index a3ce3cab07..7071b9fb3d 100644 --- a/crates/nu-utils/src/default_files/scaffold_env.nu +++ b/crates/nu-utils/src/default_files/scaffold_env.nu @@ -1,17 +1,18 @@ # env.nu # -# This file is typically used to add or override environment variables. +# Previously, environment variables were typically configured in `env.nu`. +# In general, most configuration can and should be performed in `config.nu` +# or one of the autoload directories. +# +# This file is generated for backwards compatibility for now. +# It is loaded before config.nu and login.nu +# # See https://www.nushell.sh/book/configuration.html # -# This file is loaded before config.nu and login.nu +# To pretty-print a sample of the configuration settings, run: +# config nu --sample | nu-highlight | less -R # -# You can open this file in your default editor using: -# config env -# -# To pretty-print a sample env.nu with documentation, run: -# config env --sample | nu-highlight | less -R -# -# To pretty-print the default environment values, run: +# To pretty-print the default env.nu, run: # config env --default | nu-highlight | less -R # # You can remove these comments if you want or leave From 7aacad3270c89fdc89e4cbcbf61b1769ea69bd13 Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:50:28 -0500 Subject: [PATCH 13/26] Set empty `ENV_CONVERSIONS` record by default (#14566) # Description With Windows Path case-insensitivity in place, we no longer need an `ENV_CONVERSIONS` for `PATH`, as the `nu_engine::env::convert_env_values()` handles it automatically. This PR: * Removes the default `ENV_CONVERSIONS` for path from `default_env.nu` * Sets `ENV_CONVERSIONS` to an empty record (so it can be `merge`'d) in `main()` instead # User-Facing Changes No behavioral changes - Users will now have an empty `ENV_CONVERSIONS` at startup by default, but the behavior should not change. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` # After Submitting --- crates/nu-utils/src/default_files/default_env.nu | 7 ------- src/main.rs | 7 ++++++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/nu-utils/src/default_files/default_env.nu b/crates/nu-utils/src/default_files/default_env.nu index 2e2d66f0bc..66b442ce7a 100644 --- a/crates/nu-utils/src/default_files/default_env.nu +++ b/crates/nu-utils/src/default_files/default_env.nu @@ -39,10 +39,3 @@ $env.PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT? | default {|| ([$last_exit_code, (char space), $time_segment] | str join) } - -$env.ENV_CONVERSIONS = { - "PATH": { - from_string: { |s| $s | split row (char esep) | path expand --no-symlink } - to_string: { |v| $v | path expand --no-symlink | str join (char esep) } - } -} diff --git a/src/main.rs b/src/main.rs index 1c82e58851..7d39aef02b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ use nu_cli::gather_parent_env_vars; use nu_lsp::LanguageServer; use nu_path::canonicalize_with; use nu_protocol::{ - engine::EngineState, report_shell_error, ByteStream, Config, IntoValue, PipelineData, + engine::EngineState, record, report_shell_error, ByteStream, Config, IntoValue, PipelineData, ShellError, Span, Spanned, Type, Value, }; use nu_std::load_standard_library; @@ -285,6 +285,11 @@ fn main() -> Result<()> { ); perf!("$env.config setup", start_time, use_color); + engine_state.add_env_var( + "ENV_CONVERSIONS".to_string(), + Value::test_record(record! {}), + ); + start_time = std::time::Instant::now(); if let Some(include_path) = &parsed_nu_cli_args.include_path { let span = include_path.span; From ebce62629e9f6fa3d68ba13f27d5d672997f7850 Mon Sep 17 00:00:00 2001 From: Rikuki IX <52599939+rikukiix@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:19:03 +0800 Subject: [PATCH 14/26] fix: make exec command decrement SHLVL correctly (#14570) # Description fixes #14567 Now NuShell's `exec` command will decrement `SHLVL` env value before passing it to target executable. It only works in interactive session, the same as `SHLVL` initialization. In addition, this PR also make a simple change to `SHLVL` initialization (only remove an unnecessary type conversion). # User-Facing Changes None. # Tests + Formatting Formatted. With interactively tested with several shells (bash, zsh, fish) and cross-exec-ing them, it works well this time. # After Submitting --- crates/nu-command/src/system/exec.rs | 10 ++++++++++ src/main.rs | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/nu-command/src/system/exec.rs b/crates/nu-command/src/system/exec.rs index 8a2b24a113..e9f49b86c1 100644 --- a/crates/nu-command/src/system/exec.rs +++ b/crates/nu-command/src/system/exec.rs @@ -61,6 +61,16 @@ On Windows based systems, Nushell will wait for the command to finish and then e let envs = env_to_strings(engine_state, stack)?; command.env_clear(); command.envs(envs); + // Decrement SHLVL as removing the current shell from the stack + // (only works in interactive mode, same as initialization) + if engine_state.is_interactive { + if let Some(shlvl) = engine_state.get_env_var("SHLVL") { + let shlvl = shlvl.as_int().unwrap_or(1) - 1; + command.env("SHLVL", shlvl.to_string()); + } else { + command.env("SHLVL", "0"); + } + } // Configure args. let args = crate::eval_arguments_from_call(engine_state, stack, call)?; diff --git a/src/main.rs b/src/main.rs index 7d39aef02b..db55db3ff2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -325,7 +325,7 @@ fn main() -> Result<()> { if engine_state.is_interactive { let mut shlvl = engine_state .get_env_var("SHLVL") - .map(|x| x.as_str().unwrap_or("0").parse::().unwrap_or(0)) + .map(|x| x.as_int().unwrap_or(0)) .unwrap_or(0); shlvl += 1; engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown())); From 0b9696215770f966455707560df927b394b76aaa Mon Sep 17 00:00:00 2001 From: Wind Date: Fri, 13 Dec 2024 13:40:03 +0800 Subject: [PATCH 15/26] run `cargo update` manually to update dependencies (#14569) #14556 Seems strange to me, because it downgrade `windows-target` version. So In this pr I tried to update it by hand, and also run `cargo update` manually to see how it goes --- Cargo.lock | 555 +++++++++++++++++++++++------------------------------ 1 file changed, 244 insertions(+), 311 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fac1ad9ff1..d37c10a46f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alphanumeric-sort" @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -284,7 +284,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -295,7 +295,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -384,7 +384,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -480,7 +480,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -512,9 +512,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" dependencies = [ "memchr", "regex-automata", @@ -568,9 +568,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" dependencies = [ "bytemuck_derive", ] @@ -583,7 +583,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -637,9 +637,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -696,9 +696,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -812,9 +812,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -822,9 +822,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -842,14 +842,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -877,11 +877,11 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colorz" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2a5df6ee18d52a36920c93a7736761c6fcffa72b9d960fd9133dd8d57c5184" +checksum = "6ceb37c5798821e37369cb546f430f19da2f585e0364c9615ae340a9f2e6067b" dependencies = [ - "supports-color 2.1.0", + "supports-color", ] [[package]] @@ -959,18 +959,18 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ "proc-macro2", "quote", @@ -1011,9 +1011,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1109,7 +1109,7 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags 2.6.0", "crossterm_winapi", - "mio 1.0.2", + "mio 1.0.3", "parking_lot", "rustix", "serde", @@ -1163,7 +1163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1250,7 +1250,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1261,7 +1261,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1272,7 +1272,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1338,7 +1338,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1465,7 +1465,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1519,12 +1519,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1570,9 +1570,9 @@ checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" @@ -1773,7 +1773,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1909,9 +1909,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -1978,9 +1978,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -2020,18 +2020,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - [[package]] name = "hex" version = "0.4.3" @@ -2058,7 +2046,7 @@ dependencies = [ "markup5ever 0.12.1", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2072,14 +2060,14 @@ dependencies = [ "markup5ever 0.14.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -2141,9 +2129,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", @@ -2344,7 +2332,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2375,7 +2363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -2420,9 +2408,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f4e4a06d42fab3e85ab1b419ad32b09eab58b901d40c57935ff92db3287a13" +checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" dependencies = [ "doctest-file", "libc", @@ -2452,17 +2440,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "is-terminal" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" -dependencies = [ - "hermit-abi 0.4.0", - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "is-wsl" version = "0.4.0" @@ -2529,9 +2506,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "itoap" @@ -2550,10 +2527,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2596,9 +2574,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libflate" @@ -2636,9 +2614,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -2736,9 +2714,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -2768,7 +2746,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2924,7 +2902,7 @@ dependencies = [ "cfg-if", "miette-derive", "owo-colors", - "supports-color 3.0.1", + "supports-color", "supports-hyperlinks", "supports-unicode", "terminal_size", @@ -2941,7 +2919,7 @@ checksum = "23c9b935fbe1d6cbd1dac857b54a688145e2d93f48db36010514d0f612d0ad67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2998,11 +2976,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "log", "wasi", @@ -3257,7 +3234,7 @@ dependencies = [ "percent-encoding", "reedline", "rstest", - "sysinfo 0.32.0", + "sysinfo 0.32.1", "tempfile", "unicode-segmentation", "uuid", @@ -3404,7 +3381,7 @@ dependencies = [ "pretty_assertions", "print-positions", "procfs", - "quick-xml 0.37.0", + "quick-xml 0.37.1", "quickcheck", "quickcheck_macros", "rand", @@ -3421,11 +3398,11 @@ dependencies = [ "serde_urlencoded", "serde_yaml", "sha2", - "sysinfo 0.32.0", + "sysinfo 0.32.1", "tabled", "tempfile", "titlecase", - "toml 0.8.19", + "toml", "trash", "umask", "unicode-segmentation", @@ -3456,7 +3433,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3574,7 +3551,7 @@ dependencies = [ "nu-protocol", "nu-utils", "serde", - "thiserror 2.0.3", + "thiserror 2.0.6", "typetag", ] @@ -3680,7 +3657,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", - "thiserror 2.0.3", + "thiserror 2.0.6", "typetag", "windows-sys 0.48.0", ] @@ -3709,7 +3686,7 @@ dependencies = [ "nix 0.29.0", "ntapi", "procfs", - "sysinfo 0.32.0", + "sysinfo 0.32.1", "windows 0.56.0", ] @@ -4189,7 +4166,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4200,9 +4177,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.4.0+3.4.0" +version = "300.4.1+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" dependencies = [ "cc", ] @@ -4325,9 +4302,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" @@ -4343,20 +4320,20 @@ checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 1.0.69", + "thiserror 2.0.6", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ "pest", "pest_generator", @@ -4364,22 +4341,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" dependencies = [ "once_cell", "pest", @@ -4446,7 +4423,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4561,7 +4538,7 @@ dependencies = [ "ethnum", "fast-float", "getrandom", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "itoa", "itoap", "lz4", @@ -4622,7 +4599,7 @@ dependencies = [ "comfy-table", "either", "hashbrown 0.14.5", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "indexmap", "num-traits", "once_cell", @@ -4666,7 +4643,7 @@ checksum = "ea1b431ed816cba1120cff200f06b962748001bbb2e615ce53cfbbdf701cc136" dependencies = [ "ahash 0.8.11", "bitflags 2.6.0", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "num-traits", "once_cell", "polars-arrow", @@ -4699,7 +4676,7 @@ dependencies = [ "fs4", "futures", "glob", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "home", "itoa", "memchr", @@ -4740,7 +4717,7 @@ dependencies = [ "ahash 0.8.11", "chrono", "fallible-streaming-iterator", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "indexmap", "itoa", "num-traits", @@ -4814,7 +4791,7 @@ dependencies = [ "chrono", "chrono-tz 0.8.6", "either", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "hex", "indexmap", "jsonpath_lib_polars_vendor", @@ -4853,7 +4830,7 @@ dependencies = [ "ethnum", "flate2", "futures", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "lz4", "num-traits", "polars-arrow", @@ -4888,7 +4865,7 @@ dependencies = [ "crossbeam-queue", "enum_dispatch", "futures", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "num-traits", "polars-arrow", "polars-compute", @@ -4919,7 +4896,7 @@ dependencies = [ "ciborium", "either", "futures", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "memmap2", "num-traits", "once_cell", @@ -5049,7 +5026,7 @@ dependencies = [ "bytemuck", "bytes", "compact_str 0.8.0", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "indexmap", "libc", "memmap2", @@ -5076,9 +5053,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "powerfmt" @@ -5153,7 +5130,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -5181,9 +5158,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -5305,7 +5282,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5318,7 +5295,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5364,9 +5341,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.37.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbfb3ddf5364c9cfcd65549a1e7b801d0e8d1b14c1a1590a6408aa93cfbfa84" +checksum = "f22f29bdff3987b4d8632ef95fd6424ec7e4e0a57e2f4fc63e489e75357f6a03" dependencies = [ "memchr", ] @@ -5403,10 +5380,10 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls", "socket2", - "thiserror 2.0.3", + "thiserror 2.0.6", "tokio", "tracing", ] @@ -5421,11 +5398,11 @@ dependencies = [ "getrandom", "rand", "ring", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror 2.0.6", "tinyvec", "tracing", "web-time", @@ -5433,9 +5410,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ "cfg_aliases 0.2.1", "libc", @@ -5572,7 +5549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5583,9 +5560,9 @@ checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -5640,7 +5617,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5743,7 +5720,7 @@ dependencies = [ "chumsky", "memchr", "quoted_printable", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -5857,7 +5834,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.87", + "syn 2.0.90", "unicode-ident", ] @@ -5896,7 +5873,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.87", + "syn 2.0.90", "walkdir", ] @@ -5951,9 +5928,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -5966,22 +5943,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.19" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring", @@ -6064,9 +6041,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -6114,7 +6091,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6192,29 +6169,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "indexmap", "itoa", @@ -6231,7 +6208,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6290,7 +6267,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6354,7 +6331,7 @@ checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio 0.8.11", - "mio 1.0.2", + "mio 1.0.3", "signal-hook", ] @@ -6473,9 +6450,9 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6503,7 +6480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6618,7 +6595,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6629,28 +6606,18 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "supports-color" -version = "2.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" -dependencies = [ - "is-terminal", - "is_ci", -] - -[[package]] -name = "supports-color" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" dependencies = [ "is_ci", ] [[package]] name = "supports-hyperlinks" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" [[package]] name = "supports-unicode" @@ -6692,9 +6659,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -6718,7 +6685,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6745,9 +6712,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791" +checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" dependencies = [ "core-foundation-sys", "libc", @@ -6877,11 +6844,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.6", ] [[package]] @@ -6892,18 +6859,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6918,9 +6885,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -6941,9 +6908,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -6994,14 +6961,14 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.2", + "mio 1.0.3", "parking_lot", "pin-project-lite", "socket2", @@ -7017,25 +6984,24 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -7044,18 +7010,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", -] - [[package]] name = "toml" version = "0.8.19" @@ -7066,7 +7020,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -7078,19 +7032,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" @@ -7101,7 +7042,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.20", + "winnow", ] [[package]] @@ -7112,9 +7053,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -7129,23 +7070,23 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "trash" -version = "5.2.0" +version = "5.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defe1fdd4232e407b312377885a2c5396764972bddad87baf304753374a1bfc8" +checksum = "a8e5ca62c20366b4685e3e41fba17bc7c9bbdcb82e65a89d6fda2ceea5fffd2f" dependencies = [ "chrono", "libc", @@ -7153,6 +7094,7 @@ dependencies = [ "objc2", "objc2-foundation", "once_cell", + "percent-encoding", "scopeguard", "urlencoding", "windows 0.56.0", @@ -7222,7 +7164,7 @@ checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7248,9 +7190,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-linebreak" @@ -7322,9 +7264,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3193f92e105038f98ae68af40c008e3c94f2f046926e0f95e6c835dc6459bac8" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64", "encoding_rs", @@ -7339,9 +7281,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -7496,9 +7438,9 @@ dependencies = [ [[package]] name = "uucore_procs" -version = "0.0.27" +version = "0.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d588f57acb2ba416e072a6fa652f2e11cf727267c697d2e2d65175f3b10c41" +checksum = "d91d598cf92275d9373e1eb0b9dcf85b730bde48186ed7db3bde713803090511" dependencies = [ "proc-macro2", "quote", @@ -7507,9 +7449,9 @@ dependencies = [ [[package]] name = "uuhelp_parser" -version = "0.0.27" +version = "0.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96f26868814bf1ca9deec910a08007c93eb1d8e407ce36451999d4c1c1ea6767" +checksum = "86b4d8c991cc252d4b4ea2958d0d842e36af0d1ca7f1fdc4fdce8fd0a2ff6e9c" [[package]] name = "uuid" @@ -7618,9 +7560,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -7629,36 +7571,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7666,22 +7608,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" @@ -7786,9 +7728,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -7937,7 +7879,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7948,7 +7890,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7959,7 +7901,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7970,7 +7912,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -8160,15 +8102,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.20" @@ -8190,11 +8123,11 @@ dependencies = [ [[package]] name = "winresource" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e2aaaf8cfa92078c0c0375423d631f82f2f57979c2884fdd5f604a11e45329" +checksum = "7276691b353ad4547af8c3268488d1311f4be791ffdc0c65b8cfa8f41eed693b" dependencies = [ - "toml 0.7.8", + "toml", "version_check", ] @@ -8298,9 +8231,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -8310,13 +8243,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -8338,27 +8271,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -8387,14 +8320,14 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "zip" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352" dependencies = [ "arbitrary", "crc32fast", @@ -8403,7 +8336,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror 1.0.69", + "thiserror 2.0.6", "zopfli", ] From 49f377688a88387010aea0a2781bbb6a69bf67d3 Mon Sep 17 00:00:00 2001 From: Solomon Date: Fri, 13 Dec 2024 05:55:57 -0700 Subject: [PATCH 16/26] support raw strings in match patterns (#14573) Fixes #14554 # User-Facing Changes Raw strings are now supported in match patterns: ```diff match "foo" { r#'foo'# => true, _ => false } -false +true ``` --- crates/nu-command/tests/commands/match_.rs | 9 +++++++++ crates/nu-protocol/src/engine/pattern_match.rs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/nu-command/tests/commands/match_.rs b/crates/nu-command/tests/commands/match_.rs index 23e4450d2b..5d41b3291a 100644 --- a/crates/nu-command/tests/commands/match_.rs +++ b/crates/nu-command/tests/commands/match_.rs @@ -140,6 +140,15 @@ fn match_constant_7() { assert_eq!(actual.out, "success"); } +#[test] +fn match_constant_8() { + let actual = + nu!(r#"match "foo" { r#'foo'# => { print "success" }, _ => { print "failure" } }"#); + // Make sure we don't see any of these values in the output + // As we do not auto-print loops anymore + assert_eq!(actual.out, "success"); +} + #[test] fn match_null() { let actual = nu!(r#"match null { null => { print "success"}, _ => { print "failure" }}"#); diff --git a/crates/nu-protocol/src/engine/pattern_match.rs b/crates/nu-protocol/src/engine/pattern_match.rs index 3284527cc6..32c34d22d3 100644 --- a/crates/nu-protocol/src/engine/pattern_match.rs +++ b/crates/nu-protocol/src/engine/pattern_match.rs @@ -128,7 +128,7 @@ impl Matcher for Pattern { false } } - Expr::String(x) => { + Expr::String(x) | Expr::RawString(x) => { if let Value::String { val, .. } = &value { x == val } else { From a7fa6d00c1a72f63ce953c3a6131d046aa4e3fee Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 13 Dec 2024 07:00:53 -0600 Subject: [PATCH 17/26] fix 64-bit hex number parsing (#14571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Closes #14521 This PR tweaks the way 64-bit hex numbers are parsed. ### Before ```nushell ❯ 0xffffffffffffffef Error: nu::shell::external_command × External command failed ╭─[entry #1:1:1] 1 │ 0xffffffffffffffef · ─────────┬──────── · ╰── Command `0xffffffffffffffef` not found ╰──── help: `0xffffffffffffffef` is neither a Nushell built-in or a known external command ``` ### After ```nushell ❯ 0xffffffffffffffef -17 ``` # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-parser/src/parser.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 07ab35dc36..d71ef77182 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1532,7 +1532,9 @@ pub fn parse_int(working_set: &mut StateWorkingSet, span: Span) -> Expression { span: Span, radix: u32, ) -> Expression { - if let Ok(num) = i64::from_str_radix(token, radix) { + // Parse as a u64, then cast to i64, otherwise, for numbers like "0xffffffffffffffef", + // you'll get `Error parsing hex string: number too large to fit in target type`. + if let Ok(num) = u64::from_str_radix(token, radix).map(|val| val as i64) { Expression::new(working_set, Expr::Int(num), span, Type::Int) } else { working_set.error(ParseError::InvalidLiteral( From cbf5fa6684a741598f6ba4e55835d0b89ddecdbc Mon Sep 17 00:00:00 2001 From: RobbingDaHood <16130319+RobbingDaHood@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:02:07 +0100 Subject: [PATCH 18/26] =?UTF-8?q?For=20`#`=20to=20start=20a=20comment,=20t?= =?UTF-8?q?hen=20it=20either=20need=20to=20be=20the=20first=20chara?= =?UTF-8?q?=E2=80=A6=20(#14562)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR should close 1. #10327 1. #13667 1. #13810 1. #14129 # Description For `#` to start a comment, then it either need to be the first character of the token or prefixed with ` ` (space). So now you can do this: ``` ~/Projects/nushell> 1..10 | each {echo test#testing } 12/05/2024 05:37:19 PM ╭───┬──────────────╮ │ 0 │ test#testing │ │ 1 │ test#testing │ │ 2 │ test#testing │ │ 3 │ test#testing │ │ 4 │ test#testing │ │ 5 │ test#testing │ │ 6 │ test#testing │ │ 7 │ test#testing │ │ 8 │ test#testing │ │ 9 │ test#testing │ ╰───┴──────────────╯ ``` # User-Facing Changes It is a breaking change if anyone expected comments to start in the middle of a string without any prefixing ` ` (space). # Tests + Formatting Did all: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library # After Submitting I cant see that I need to update anything in [the documentation](https://github.com/nushell/nushell.github.io) but please point me in the direction if there is anything. --- crates/nu-parser/src/lex.rs | 12 ++++----- crates/nu-parser/tests/test_lex.rs | 23 +++++++++++++++++ tests/repl/test_parser.rs | 40 ++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index f0802fcd7a..6d1adf28ef 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -51,7 +51,7 @@ impl BlockKind { } // A baseline token is terminated if it's not nested inside of a paired -// delimiter and the next character is one of: `|`, `;`, `#` or any +// delimiter and the next character is one of: `|`, `;` or any // whitespace. fn is_item_terminator( block_level: &[BlockKind], @@ -115,6 +115,7 @@ pub fn lex_item( // character (whitespace, `|`, `;` or `#`) is encountered, the baseline // token is done. // - Otherwise, accumulate the character into the current baseline token. + let mut previous_char = None; while let Some(c) = input.get(*curr_offset) { let c = *c; @@ -147,11 +148,9 @@ pub fn lex_item( // Also need to check to make sure we aren't escaped quote_start = None; } - } else if c == b'#' { - if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { - break; - } - in_comment = true; + } else if c == b'#' && !in_comment { + // To start a comment, It either need to be the first character of the token or prefixed with space. + in_comment = previous_char.map(|pc| pc == b' ').unwrap_or(true); } else if c == b'\n' || c == b'\r' { in_comment = false; if is_item_terminator(&block_level, c, additional_whitespace, special_tokens) { @@ -254,6 +253,7 @@ pub fn lex_item( } *curr_offset += 1; + previous_char = Some(c); } let span = Span::new(span_offset + token_start, span_offset + *curr_offset); diff --git a/crates/nu-parser/tests/test_lex.rs b/crates/nu-parser/tests/test_lex.rs index a14843f3f0..54ff674bb9 100644 --- a/crates/nu-parser/tests/test_lex.rs +++ b/crates/nu-parser/tests/test_lex.rs @@ -159,6 +159,29 @@ fn lex_comment() { ); } +#[test] +fn lex_not_comment_needs_space_in_front_of_hashtag() { + let file = b"1..10 | each {echo test#testing }"; + + let output = lex(file, 0, &[], &[], false); + + assert!(output.1.is_none()); +} + +#[test] +fn lex_comment_with_space_in_front_of_hashtag() { + let file = b"1..10 | each {echo test #testing }"; + + let output = lex(file, 0, &[], &[], false); + + assert!(output.1.is_some()); + assert!(matches!( + output.1.unwrap(), + ParseError::UnexpectedEof(missing_token, span) if missing_token == "}" + && span == Span::new(33, 34) + )); +} + #[test] fn lex_is_incomplete() { let file = b"let x = 300 | ;"; diff --git a/tests/repl/test_parser.rs b/tests/repl/test_parser.rs index f77d431110..ddc790324a 100644 --- a/tests/repl/test_parser.rs +++ b/tests/repl/test_parser.rs @@ -169,6 +169,41 @@ fn comment_skipping_in_pipeline_3() -> TestResult { ) } +#[test] +fn still_string_if_hashtag_is_middle_of_string() -> TestResult { + run_test(r#"echo test#testing"#, "test#testing") +} + +#[test] +fn non_comment_hashtag_in_comment_does_not_stop_comment() -> TestResult { + run_test(r#"# command_bar_text: { fg: '#C4C9C6' },"#, "") +} + +#[test] +fn non_comment_hashtag_in_comment_does_not_stop_comment_in_block() -> TestResult { + run_test( + r#"{ + explore: { + # command_bar_text: { fg: '#C4C9C6' }, + } + } | get explore | is-empty"#, + "true", + ) +} + +#[test] +fn still_string_if_hashtag_is_middle_of_string_inside_each() -> TestResult { + run_test( + r#"1..1 | each {echo test#testing } | get 0"#, + "test#testing", + ) +} + +#[test] +fn still_string_if_hashtag_is_middle_of_string_inside_each_also_with_dot() -> TestResult { + run_test(r#"1..1 | each {echo '.#testing' } | get 0"#, ".#testing") +} + #[test] fn bad_var_name() -> TestResult { fail_test(r#"let $"foo bar" = 4"#, "can't contain") @@ -282,6 +317,11 @@ fn raw_string_with_equals() -> TestResult { ) } +#[test] +fn raw_string_with_hashtag() -> TestResult { + run_test(r#"r##' one # two '##"#, "one # two") +} + #[test] fn list_quotes_with_equals() -> TestResult { run_test( From cc0616b753f0f6f290a7108a1202970387c91690 Mon Sep 17 00:00:00 2001 From: Solomon Date: Fri, 13 Dec 2024 15:23:17 -0700 Subject: [PATCH 19/26] return const values from `scope variables` (#14577) Fixes #14542 # User-Facing Changes Constant values are no longer missing from `scope variables` output when the IR evaluator is enabled: ```diff const foo = 1 scope variables | where name == "$foo" | get value.0 | to nuon -null +int ``` --- crates/nu-engine/src/scope.rs | 11 ++++++----- tests/repl/test_engine.rs | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/crates/nu-engine/src/scope.rs b/crates/nu-engine/src/scope.rs index 45f6f983fc..8774a8996b 100644 --- a/crates/nu-engine/src/scope.rs +++ b/crates/nu-engine/src/scope.rs @@ -56,11 +56,12 @@ impl<'e, 's> ScopeData<'e, 's> { let var_type = Value::string(var.ty.to_string(), span); let is_const = Value::bool(var.const_val.is_some(), span); - let var_value = if let Ok(val) = self.stack.get_var(**var_id, span) { - val - } else { - Value::nothing(span) - }; + let var_value = self + .stack + .get_var(**var_id, span) + .ok() + .or(var.const_val.clone()) + .unwrap_or(Value::nothing(span)); let var_id_val = Value::int(var_id.get() as i64, span); diff --git a/tests/repl/test_engine.rs b/tests/repl/test_engine.rs index 90dd1e86b0..5c2fb8e533 100644 --- a/tests/repl/test_engine.rs +++ b/tests/repl/test_engine.rs @@ -90,12 +90,19 @@ fn help_works_with_missing_requirements() -> TestResult { run_test(r#"each --help | lines | length"#, "72") } -#[test] -fn scope_variable() -> TestResult { - run_test( - r#"let x = 3; scope variables | where name == "$x" | get type.0"#, - "int", - ) +#[rstest] +#[case("let x = 3", "$x", "int", "3")] +#[case("const x = 3", "$x", "int", "3")] +fn scope_variable( + #[case] var_decl: &str, + #[case] exp_name: &str, + #[case] exp_type: &str, + #[case] exp_value: &str, +) -> TestResult { + let get_var_info = + format!(r#"{var_decl}; scope variables | where name == "{exp_name}" | first"#); + run_test(&format!(r#"{get_var_info} | get type"#), exp_type)?; + run_test(&format!(r#"{get_var_info} | get value"#), exp_value) } #[rstest] From 05ee7ea9c78cb9ead9dbf380a1c3322d4cf226e5 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:34:33 -0600 Subject: [PATCH 20/26] Revert "fix: make exec command decrement SHLVL correctly" (#14580) Reverts nushell/nushell#14570 --- crates/nu-command/src/system/exec.rs | 10 ---------- src/main.rs | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/crates/nu-command/src/system/exec.rs b/crates/nu-command/src/system/exec.rs index e9f49b86c1..8a2b24a113 100644 --- a/crates/nu-command/src/system/exec.rs +++ b/crates/nu-command/src/system/exec.rs @@ -61,16 +61,6 @@ On Windows based systems, Nushell will wait for the command to finish and then e let envs = env_to_strings(engine_state, stack)?; command.env_clear(); command.envs(envs); - // Decrement SHLVL as removing the current shell from the stack - // (only works in interactive mode, same as initialization) - if engine_state.is_interactive { - if let Some(shlvl) = engine_state.get_env_var("SHLVL") { - let shlvl = shlvl.as_int().unwrap_or(1) - 1; - command.env("SHLVL", shlvl.to_string()); - } else { - command.env("SHLVL", "0"); - } - } // Configure args. let args = crate::eval_arguments_from_call(engine_state, stack, call)?; diff --git a/src/main.rs b/src/main.rs index db55db3ff2..7d39aef02b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -325,7 +325,7 @@ fn main() -> Result<()> { if engine_state.is_interactive { let mut shlvl = engine_state .get_env_var("SHLVL") - .map(|x| x.as_int().unwrap_or(0)) + .map(|x| x.as_str().unwrap_or("0").parse::().unwrap_or(0)) .unwrap_or(0); shlvl += 1; engine_state.add_env_var("SHLVL".to_string(), Value::int(shlvl, Span::unknown())); From 219b44a04f0d22adfd0c733158a8228571723f5a Mon Sep 17 00:00:00 2001 From: Jack Wright <56345+ayax79@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:36:01 -0800 Subject: [PATCH 21/26] Improve handling of columns with null values (#14588) Addresses some null handling issues in #6882 # Description This changes the implementation of guessing a column type when a schema is not specified. New behavior: 1. Use the first non-Value::Nothing value type for the columns data type 2. If the value type changes (ignoring Value::Nothing) in subsequent values, the datatype will be changed to DataType::Object("Value", None) 3. If a column type does not have a value type, DataType::Object("Value", None) will be assumed. --- .../values/nu_dataframe/conversion.rs | 547 ++++++++---------- 1 file changed, 256 insertions(+), 291 deletions(-) diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs index 7d5a4ace3f..d196ed8ba6 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs @@ -223,57 +223,30 @@ pub fn insert_value( inner: vec![], }) } - } - // Checking that the type for the value is the same - // for the previous value in the column - else if col_val.values.is_empty() { - if let Some(schema) = maybe_schema { - if let Some(field) = schema.schema.get_field(&key) { - col_val.column_type = Some(field.dtype().clone()); - } - } - + } else { + let current_data_type = value_to_data_type(&value); if col_val.column_type.is_none() { - col_val.column_type = Some(value_to_data_type(&value)); + col_val.column_type = value_to_data_type(&value); + } else if let Some(current_data_type) = current_data_type { + if col_val.column_type.as_ref() != Some(¤t_data_type) { + col_val.column_type = Some(DataType::Object("Value", None)); + } } col_val.values.push(value); Ok(()) - } else { - let prev_value = &col_val.values[col_val.values.len() - 1]; - - match (&prev_value, &value) { - (Value::Int { .. }, Value::Int { .. }) - | (Value::Float { .. }, Value::Float { .. }) - | (Value::String { .. }, Value::String { .. }) - | (Value::Bool { .. }, Value::Bool { .. }) - | (Value::Date { .. }, Value::Date { .. }) - | (Value::Filesize { .. }, Value::Filesize { .. }) - | (Value::Binary { .. }, Value::Binary { .. }) - | (Value::Duration { .. }, Value::Duration { .. }) => col_val.values.push(value), - (_, Value::Nothing { .. }) => col_val.values.push(value), - (Value::List { .. }, _) => { - col_val.column_type = Some(value_to_data_type(&value)); - col_val.values.push(value); - } - _ => { - col_val.column_type = Some(DataType::Object("Value", None)); - col_val.values.push(value); - } - } - Ok(()) } } -fn value_to_data_type(value: &Value) -> DataType { +fn value_to_data_type(value: &Value) -> Option { match &value { - Value::Int { .. } => DataType::Int64, - Value::Float { .. } => DataType::Float64, - Value::String { .. } => DataType::String, - Value::Bool { .. } => DataType::Boolean, - Value::Date { .. } => DataType::Date, - Value::Duration { .. } => DataType::Duration(TimeUnit::Nanoseconds), - Value::Filesize { .. } => DataType::Int64, - Value::Binary { .. } => DataType::Binary, + Value::Int { .. } => Some(DataType::Int64), + Value::Float { .. } => Some(DataType::Float64), + Value::String { .. } => Some(DataType::String), + Value::Bool { .. } => Some(DataType::Boolean), + Value::Date { .. } => Some(DataType::Date), + Value::Duration { .. } => Some(DataType::Duration(TimeUnit::Nanoseconds)), + Value::Filesize { .. } => Some(DataType::Int64), + Value::Binary { .. } => Some(DataType::Binary), Value::List { vals, .. } => { // We need to determined the type inside of the list. // Since Value::List does not have any kind of @@ -286,243 +259,247 @@ fn value_to_data_type(value: &Value) -> DataType { .filter(|v| !matches!(v, Value::Nothing { .. })) .map(value_to_data_type) .nth(1) + .flatten() .unwrap_or(DataType::Object("Value", None)); - DataType::List(Box::new(list_type)) + Some(DataType::List(Box::new(list_type))) } - _ => DataType::Object("Value", None), + _ => None, } } fn typed_column_to_series(name: PlSmallStr, column: TypedColumn) -> Result { - if let Some(column_type) = &column.column_type { - match column_type { - DataType::Float32 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| { - value_to_option(v, |v| match v { - Value::Float { val, .. } => Ok(*val as f32), - Value::Int { val, .. } => Ok(*val as f32), - x => Err(ShellError::GenericError { - error: "Error converting to f32".into(), - msg: "".into(), - span: None, - help: Some(format!("Unexpected type: {x:?}")), - inner: vec![], - }), - }) + let column_type = &column + .column_type + .clone() + .unwrap_or(DataType::Object("Value", None)); + match column_type { + DataType::Float32 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| { + value_to_option(v, |v| match v { + Value::Float { val, .. } => Ok(*val as f32), + Value::Int { val, .. } => Ok(*val as f32), + x => Err(ShellError::GenericError { + error: "Error converting to f32".into(), + msg: "".into(), + span: None, + help: Some(format!("Unexpected type: {x:?}")), + inner: vec![], + }), }) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Float64 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| { - value_to_option(v, |v| match v { - Value::Float { val, .. } => Ok(*val), - Value::Int { val, .. } => Ok(*val as f64), - x => Err(ShellError::GenericError { - error: "Error converting to f64".into(), - msg: "".into(), - span: None, - help: Some(format!("Unexpected type: {x:?}")), - inner: vec![], - }), - }) + }) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Float64 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| { + value_to_option(v, |v| match v { + Value::Float { val, .. } => Ok(*val), + Value::Int { val, .. } => Ok(*val as f64), + x => Err(ShellError::GenericError { + error: "Error converting to f64".into(), + msg: "".into(), + span: None, + help: Some(format!("Unexpected type: {x:?}")), + inner: vec![], + }), }) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::UInt8 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u8))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::UInt16 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u16))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::UInt32 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u32))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::UInt64 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u64))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Int8 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i8))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Int16 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i16))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Int32 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i32))) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Int64 => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, value_to_int)) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Boolean => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| v.as_bool())) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::String => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| value_to_option(v, |v| v.coerce_string())) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Binary | DataType::BinaryOffset => { - let series_values: Result, _> = - column.values.iter().map(|v| v.coerce_binary()).collect(); - Ok(Series::new(name, series_values?)) - } - DataType::Object(_, _) => value_to_series(name, &column.values), - DataType::Duration(time_unit) => { - let series_values: Result, _> = column - .values - .iter() - .map(|v| { - value_to_option(v, |v| { - v.as_duration().map(|v| nanos_from_timeunit(v, *time_unit)) - }) + }) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::UInt8 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u8))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::UInt16 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u16))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::UInt32 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u32))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::UInt64 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as u64))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Int8 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i8))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Int16 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i16))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Int32 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| value_to_int(v).map(|v| v as i32))) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Int64 => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, value_to_int)) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Boolean => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| v.as_bool())) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::String => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| value_to_option(v, |v| v.coerce_string())) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Binary | DataType::BinaryOffset => { + let series_values: Result, _> = + column.values.iter().map(|v| v.coerce_binary()).collect(); + Ok(Series::new(name, series_values?)) + } + DataType::Object(_, _) => value_to_series(name, &column.values), + DataType::Duration(time_unit) => { + let series_values: Result, _> = column + .values + .iter() + .map(|v| { + value_to_option(v, |v| { + v.as_duration().map(|v| nanos_from_timeunit(v, *time_unit)) }) - .collect(); - Ok(Series::new(name, series_values?)) - } - DataType::List(list_type) => { - match input_type_list_to_series(&name, list_type.as_ref(), &column.values) { - Ok(series) => Ok(series), - Err(_) => { - // An error case will occur when there are lists of mixed types. - // If this happens, fallback to object list - input_type_list_to_series( - &name, - &DataType::Object("unknown", None), - &column.values, - ) - } + }) + .collect(); + Ok(Series::new(name, series_values?)) + } + DataType::List(list_type) => { + match input_type_list_to_series(&name, list_type.as_ref(), &column.values) { + Ok(series) => Ok(series), + Err(_) => { + // An error case will occur when there are lists of mixed types. + // If this happens, fallback to object list + input_type_list_to_series( + &name, + &DataType::Object("unknown", None), + &column.values, + ) } } - DataType::Date => { - let it = column.values.iter().map(|v| { + } + DataType::Date => { + let it = column.values.iter().map(|v| { + if let Value::Date { val, .. } = &v { + Some(val.timestamp_nanos_opt().unwrap_or_default()) + } else { + None + } + }); + + let res: DatetimeChunked = ChunkedArray::::from_iter_options(name, it) + .into_datetime(TimeUnit::Nanoseconds, None); + + Ok(res.into_series()) + } + DataType::Datetime(tu, maybe_tz) => { + let dates = column + .values + .iter() + .map(|v| { if let Value::Date { val, .. } = &v { - Some(val.timestamp_nanos_opt().unwrap_or_default()) - } else { - None - } - }); - - let res: DatetimeChunked = ChunkedArray::::from_iter_options(name, it) - .into_datetime(TimeUnit::Nanoseconds, None); - - Ok(res.into_series()) - } - DataType::Datetime(tu, maybe_tz) => { - let dates = column - .values - .iter() - .map(|v| { - if let Value::Date { val, .. } = &v { - // If there is a timezone specified, make sure - // the value is converted to it - Ok(maybe_tz - .as_ref() - .map(|tz| tz.parse::().map(|tz| val.with_timezone(&tz))) - .transpose() - .map_err(|e| ShellError::GenericError { - error: "Error parsing timezone".into(), - msg: "".into(), - span: None, - help: Some(e.to_string()), - inner: vec![], - })? - .and_then(|dt| dt.timestamp_nanos_opt()) - .map(|nanos| nanos_from_timeunit(nanos, *tu))) - } else { - Ok(None) - } - }) - .collect::>, ShellError>>()?; - - let res: DatetimeChunked = - ChunkedArray::::from_iter_options(name, dates.into_iter()) - .into_datetime(*tu, maybe_tz.clone()); - - Ok(res.into_series()) - } - DataType::Struct(fields) => { - let schema = Some(NuSchema::new(Schema::from_iter(fields.clone()))); - // let mut structs: Vec = Vec::new(); - let mut structs: HashMap = HashMap::new(); - - for v in column.values.iter() { - let mut column_values: ColumnMap = IndexMap::new(); - let record = v.as_record()?; - insert_record(&mut column_values, record.clone(), &schema)?; - let df = from_parsed_columns(column_values)?; - for name in df.df.get_column_names() { - let series = df - .df - .column(name) + // If there is a timezone specified, make sure + // the value is converted to it + Ok(maybe_tz + .as_ref() + .map(|tz| tz.parse::().map(|tz| val.with_timezone(&tz))) + .transpose() .map_err(|e| ShellError::GenericError { - error: format!( - "Error creating struct, could not get column name {name}: {e}" - ), + error: "Error parsing timezone".into(), msg: "".into(), span: None, - help: None, + help: Some(e.to_string()), inner: vec![], })? - .as_materialized_series(); + .and_then(|dt| dt.timestamp_nanos_opt()) + .map(|nanos| nanos_from_timeunit(nanos, *tu))) + } else { + Ok(None) + } + }) + .collect::>, ShellError>>()?; - if let Some(v) = structs.get_mut(name) { - let _ = v.append(series) + let res: DatetimeChunked = + ChunkedArray::::from_iter_options(name, dates.into_iter()) + .into_datetime(*tu, maybe_tz.clone()); + + Ok(res.into_series()) + } + DataType::Struct(fields) => { + let schema = Some(NuSchema::new(Schema::from_iter(fields.clone()))); + // let mut structs: Vec = Vec::new(); + let mut structs: HashMap = HashMap::new(); + + for v in column.values.iter() { + let mut column_values: ColumnMap = IndexMap::new(); + let record = v.as_record()?; + insert_record(&mut column_values, record.clone(), &schema)?; + let df = from_parsed_columns(column_values)?; + for name in df.df.get_column_names() { + let series = df + .df + .column(name) + .map_err(|e| ShellError::GenericError { + error: format!( + "Error creating struct, could not get column name {name}: {e}" + ), + msg: "".into(), + span: None, + help: None, + inner: vec![], + })? + .as_materialized_series(); + + if let Some(v) = structs.get_mut(name) { + let _ = v.append(series) .map_err(|e| ShellError::GenericError { error: format!("Error creating struct, could not append to series for col {name}: {e}"), msg: "".into(), @@ -530,44 +507,32 @@ fn typed_column_to_series(name: PlSmallStr, column: TypedColumn) -> Result = structs.into_values().collect(); - - let chunked = StructChunked::from_series( - column.name().to_owned(), - structs.len(), - structs.iter(), - ) - .map_err(|e| ShellError::GenericError { - error: format!("Error creating struct: {e}"), - msg: "".into(), - span: None, - help: None, - inner: vec![], - })?; - Ok(chunked.into_series()) } - _ => Err(ShellError::GenericError { - error: format!("Error creating dataframe: Unsupported type: {column_type:?}"), - msg: "".into(), - span: None, - help: None, - inner: vec![], - }), + + let structs: Vec = structs.into_values().collect(); + + let chunked = + StructChunked::from_series(column.name().to_owned(), structs.len(), structs.iter()) + .map_err(|e| ShellError::GenericError { + error: format!("Error creating struct: {e}"), + msg: "".into(), + span: None, + help: None, + inner: vec![], + })?; + Ok(chunked.into_series()) } - } else { - Err(ShellError::GenericError { - error: "Passed a type column with no type".into(), + _ => Err(ShellError::GenericError { + error: format!("Error creating dataframe: Unsupported type: {column_type:?}"), msg: "".into(), span: None, help: None, inner: vec![], - }) + }), } } From baf86dfb0ed57aefb75962ea6cfc1552cb44c2c4 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Sat, 14 Dec 2024 21:58:47 -0600 Subject: [PATCH 22/26] tweak polars join for better cross joins (#14586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description closes #14585 This PR tries to make `polars join --cross` work better. Example taken from https://docs.pola.rs/user-guide/transformations/joins/#cartesian-product ### Before ```nushell ❯ let tokens = [[monopoly_token]; [hat] [shoe] [boat]] | polars into-df ❯ let players = [[name, cash]; [Alice, 78] [Bob, 135]] | polars into-df ❯ $players | polars into-lazy | polars select (polars col name) | polars join --cross $tokens | polars collect Error: nu::parser::missing_positional × Missing required positional argument. ╭─[entry #3:1:92] 1 │ $players | polars into-lazy | polars select (polars col name) | polars join --cross $tokens ╰──── help: Usage: polars join {flags} . Use `--help` for more information. ``` ### After ```nushell ❯ let players = [[name, cash]; [Alice, 78] [Bob, 135]] | polars into-df ❯ let tokens = [[monopoly_token]; [hat] [shoe] [boat]] | polars into-df ❯ $players | polars into-lazy | polars select (polars col name) | polars join --cross $tokens | polars collect ╭─#─┬─name──┬─monopoly_token─╮ │ 0 │ Alice │ hat │ │ 1 │ Alice │ shoe │ │ 2 │ Alice │ boat │ │ 3 │ Bob │ hat │ │ 4 │ Bob │ shoe │ │ 5 │ Bob │ boat │ ╰─#─┴─name──┴─monopoly_token─╯ ``` Other examples ```nushell ❯ 1..3 | polars into-df | polars join --cross (4..6 | polars into-df) ╭─#─┬─0─┬─0_x─╮ │ 0 │ 1 │ 4 │ │ 1 │ 1 │ 5 │ │ 2 │ 1 │ 6 │ │ 3 │ 2 │ 4 │ │ 4 │ 2 │ 5 │ │ 5 │ 2 │ 6 │ │ 6 │ 3 │ 4 │ │ 7 │ 3 │ 5 │ │ 8 │ 3 │ 6 │ ╰─#─┴─0─┴─0_x─╯ ❯ 1..3 | each {|x| {x: $x}} | polars into-df | polars join --cross (4..6 | each {|y| {y: $y}} | polars into-df) x y ╭─#─┬─x─┬─y─╮ │ 0 │ 1 │ 4 │ │ 1 │ 1 │ 5 │ │ 2 │ 1 │ 6 │ │ 3 │ 2 │ 4 │ │ 4 │ 2 │ 5 │ │ 5 │ 2 │ 6 │ │ 6 │ 3 │ 4 │ │ 7 │ 3 │ 5 │ │ 8 │ 3 │ 6 │ ╰─#─┴─x─┴─y─╯ ``` /cc @ayax79 # User-Facing Changes # Tests + Formatting # After Submitting --- .../src/dataframe/command/data/join.rs | 96 +++++++++++++++---- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/crates/nu_plugin_polars/src/dataframe/command/data/join.rs b/crates/nu_plugin_polars/src/dataframe/command/data/join.rs index ee18e17567..b1c13fef00 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/data/join.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/data/join.rs @@ -27,8 +27,8 @@ impl PluginCommand for LazyJoin { fn signature(&self) -> Signature { Signature::build(self.name()) .required("other", SyntaxShape::Any, "LazyFrame to join with") - .required("left_on", SyntaxShape::Any, "Left column(s) to join on") - .required("right_on", SyntaxShape::Any, "Right column(s) to join on") + .optional("left_on", SyntaxShape::Any, "Left column(s) to join on") + .optional("right_on", SyntaxShape::Any, "Right column(s) to join on") .switch( "inner", "inner joining between lazyframes (default)", @@ -54,8 +54,8 @@ impl PluginCommand for LazyJoin { vec![ Example { description: "Join two lazy dataframes", - example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-lazy); - let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy); + example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-lazy) + let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy) $df_a | polars join $df_b a foo | polars collect"#, result: Some( NuDataFrame::try_from_columns( @@ -114,8 +114,8 @@ impl PluginCommand for LazyJoin { }, Example { description: "Join one eager dataframe with a lazy dataframe", - example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-df); - let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy); + example: r#"let df_a = ([[a b c];[1 "a" 0] [2 "b" 1] [1 "c" 2] [1 "c" 3]] | polars into-df) + let df_b = ([["foo" "bar" "ham"];[1 "a" "let"] [2 "c" "var"] [3 "c" "const"]] | polars into-lazy) $df_a | polars join $df_b a foo"#, result: Some( NuDataFrame::try_from_columns( @@ -172,6 +172,43 @@ impl PluginCommand for LazyJoin { .into_value(Span::test_data()), ), }, + Example { + description: "Join one eager dataframe with another using a cross join", + example: r#"let tokens = [[monopoly_token]; [hat] [shoe] [boat]] | polars into-df + let players = [[name, cash]; [Alice, 78] [Bob, 135]] | polars into-df + $players | polars select (polars col name) | polars join --cross $tokens | polars collect"#, + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new( + "name".to_string(), + vec![ + Value::test_string("Alice"), + Value::test_string("Alice"), + Value::test_string("Alice"), + Value::test_string("Bob"), + Value::test_string("Bob"), + Value::test_string("Bob"), + ], + ), + Column::new( + "monopoly_token".to_string(), + vec![ + Value::test_string("hat"), + Value::test_string("shoe"), + Value::test_string("boat"), + Value::test_string("hat"), + Value::test_string("shoe"), + Value::test_string("boat"), + ], + ), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, ] } @@ -200,11 +237,21 @@ impl PluginCommand for LazyJoin { let other = NuLazyFrame::try_from_value_coerce(plugin, &other)?; let other = other.to_polars(); - let left_on: Value = call.req(1)?; - let left_on = NuExpression::extract_exprs(plugin, left_on)?; + let left_on_opt: Option = call.opt(1)?; + let left_on = match left_on_opt { + Some(left_on_value) if left || left_on_opt.is_some() => { + NuExpression::extract_exprs(plugin, left_on_value)? + } + _ => vec![], + }; - let right_on: Value = call.req(2)?; - let right_on = NuExpression::extract_exprs(plugin, right_on)?; + let right_on_opt: Option = call.opt(2)?; + let right_on = match right_on_opt { + Some(right_on_value) if full || right_on_opt.is_some() => { + NuExpression::extract_exprs(plugin, right_on_value)? + } + _ => vec![], + }; if left_on.len() != right_on.len() { let right_on: Value = call.req(2)?; @@ -232,16 +279,25 @@ impl PluginCommand for LazyJoin { let lazy = NuLazyFrame::try_from_value_coerce(plugin, &value)?; let from_eager = lazy.from_eager; let lazy = lazy.to_polars(); - - let lazy = lazy - .join_builder() - .with(other) - .left_on(left_on) - .right_on(right_on) - .how(how) - .force_parallel(true) - .suffix(suffix) - .finish(); + let lazy = if cross { + lazy.join_builder() + .with(other) + .left_on(vec![]) + .right_on(vec![]) + .how(how) + .force_parallel(true) + .suffix(suffix) + .finish() + } else { + lazy.join_builder() + .with(other) + .left_on(left_on) + .right_on(right_on) + .how(how) + .force_parallel(true) + .suffix(suffix) + .finish() + }; let lazy = NuLazyFrame::new(from_eager, lazy); lazy.to_pipeline_data(plugin, engine, call.head) From 3c632e96f9ec02095cc0e1485115df0a5abf123b Mon Sep 17 00:00:00 2001 From: Bahex Date: Mon, 16 Dec 2024 00:26:14 +0300 Subject: [PATCH 23/26] docs(reduce): add example demonstrating accumulator as pipeline input (#14593) # Description Add an example to `reduce` that shows accumulator can also be accessed pipeline input. # User-Facing Changes N/A # Tests + Formatting - :green_circle: toolkit fmt - :green_circle: toolkit clippy - :green_circle: toolkit test - :green_circle: toolkit test stdlib # After Submitting N/A --- crates/nu-command/src/filters/reduce.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/filters/reduce.rs b/crates/nu-command/src/filters/reduce.rs index ed3c61ec32..8aa77719b9 100644 --- a/crates/nu-command/src/filters/reduce.rs +++ b/crates/nu-command/src/filters/reduce.rs @@ -88,6 +88,15 @@ impl Command for Reduce { "Concatenate a string with itself, using a range to determine the number of times.", result: Some(Value::test_string("StrStrStr")), }, + Example { + example: r#"[{a: 1} {b: 2} {c: 3}] | reduce {|it| merge $it}"#, + description: "Merge multiple records together, making use of the fact that the accumulated value is also supplied as pipeline input to the closure.", + result: Some(Value::test_record(record!( + "a" => Value::test_int(1), + "b" => Value::test_int(2), + "c" => Value::test_int(3), + ))), + } ] } @@ -135,8 +144,8 @@ mod test { #[test] fn test_examples() { - use crate::test_examples; + use crate::{test_examples_with_commands, Merge}; - test_examples(Reduce {}) + test_examples_with_commands(Reduce {}, &[&Merge]) } } From 3760910f0bbf58e25787ee685046cd2837924882 Mon Sep 17 00:00:00 2001 From: Bahex Date: Mon, 16 Dec 2024 00:27:13 +0300 Subject: [PATCH 24/26] remove the deprecated index argument from filter commands' closure signature (#14594) # Description A lot of filter commands that have a closure argument (`each`, `filter`, etc), have a wrong signature for the closure, indicating an extra int argument for the closure. I think they are a left over from before `enumerate` was added, used to access iteration index. None of the commands changed in this PR actually supply this int argument. # User-Facing Changes N/A # Tests + Formatting - :green_circle: toolkit fmt - :green_circle: toolkit clippy - :green_circle: toolkit test - :green_circle: toolkit test stdlib # After Submitting N/A --- crates/nu-cmd-extra/src/extra/filters/each_while.rs | 2 +- crates/nu-command/src/filters/all.rs | 2 +- crates/nu-command/src/filters/any.rs | 2 +- crates/nu-command/src/filters/filter.rs | 2 +- crates/nu-command/src/filters/par_each.rs | 2 +- crates/nu-command/src/filters/reduce.rs | 6 +----- crates/nu-command/src/filters/skip/skip_until.rs | 2 +- crates/nu-command/src/filters/skip/skip_while.rs | 2 +- crates/nu-command/src/filters/take/take_until.rs | 2 +- crates/nu-command/src/filters/take/take_while.rs | 2 +- 10 files changed, 10 insertions(+), 14 deletions(-) diff --git a/crates/nu-cmd-extra/src/extra/filters/each_while.rs b/crates/nu-cmd-extra/src/extra/filters/each_while.rs index 67f0cc9482..cc5c066185 100644 --- a/crates/nu-cmd-extra/src/extra/filters/each_while.rs +++ b/crates/nu-cmd-extra/src/extra/filters/each_while.rs @@ -25,7 +25,7 @@ impl Command for EachWhile { )]) .required( "closure", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "the closure to run", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/all.rs b/crates/nu-command/src/filters/all.rs index e4ffdf2c87..aa36118273 100644 --- a/crates/nu-command/src/filters/all.rs +++ b/crates/nu-command/src/filters/all.rs @@ -14,7 +14,7 @@ impl Command for All { .input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Bool)]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "A closure that must evaluate to a boolean.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/any.rs b/crates/nu-command/src/filters/any.rs index cd8a6b65e4..230a96ebe7 100644 --- a/crates/nu-command/src/filters/any.rs +++ b/crates/nu-command/src/filters/any.rs @@ -14,7 +14,7 @@ impl Command for Any { .input_output_types(vec![(Type::List(Box::new(Type::Any)), Type::Bool)]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "A closure that must evaluate to a boolean.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/filter.rs b/crates/nu-command/src/filters/filter.rs index 93fe5a6e6d..ea7960c4d3 100644 --- a/crates/nu-command/src/filters/filter.rs +++ b/crates/nu-command/src/filters/filter.rs @@ -30,7 +30,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."# ]) .required( "closure", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "Predicate closure.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/par_each.rs b/crates/nu-command/src/filters/par_each.rs index fc0da7d3d3..4e4d526657 100644 --- a/crates/nu-command/src/filters/par_each.rs +++ b/crates/nu-command/src/filters/par_each.rs @@ -38,7 +38,7 @@ impl Command for ParEach { ) .required( "closure", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "The closure to run.", ) .allow_variants_without_examples(true) diff --git a/crates/nu-command/src/filters/reduce.rs b/crates/nu-command/src/filters/reduce.rs index 8aa77719b9..9d17339d0e 100644 --- a/crates/nu-command/src/filters/reduce.rs +++ b/crates/nu-command/src/filters/reduce.rs @@ -24,11 +24,7 @@ impl Command for Reduce { ) .required( "closure", - SyntaxShape::Closure(Some(vec![ - SyntaxShape::Any, - SyntaxShape::Any, - SyntaxShape::Int, - ])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Any])), "Reducing function.", ) .allow_variants_without_examples(true) diff --git a/crates/nu-command/src/filters/skip/skip_until.rs b/crates/nu-command/src/filters/skip/skip_until.rs index b73c817e9b..6f9ada280c 100644 --- a/crates/nu-command/src/filters/skip/skip_until.rs +++ b/crates/nu-command/src/filters/skip/skip_until.rs @@ -20,7 +20,7 @@ impl Command for SkipUntil { ]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "The predicate that skipped element must not match.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/skip/skip_while.rs b/crates/nu-command/src/filters/skip/skip_while.rs index 9423915242..494cf91558 100644 --- a/crates/nu-command/src/filters/skip/skip_while.rs +++ b/crates/nu-command/src/filters/skip/skip_while.rs @@ -20,7 +20,7 @@ impl Command for SkipWhile { ]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "The predicate that skipped element must match.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/take/take_until.rs b/crates/nu-command/src/filters/take/take_until.rs index e1dcd6ceda..4e8f38a3d2 100644 --- a/crates/nu-command/src/filters/take/take_until.rs +++ b/crates/nu-command/src/filters/take/take_until.rs @@ -17,7 +17,7 @@ impl Command for TakeUntil { )]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "The predicate that element(s) must not match.", ) .category(Category::Filters) diff --git a/crates/nu-command/src/filters/take/take_while.rs b/crates/nu-command/src/filters/take/take_while.rs index 54e9384cba..c9e218f543 100644 --- a/crates/nu-command/src/filters/take/take_while.rs +++ b/crates/nu-command/src/filters/take/take_while.rs @@ -20,7 +20,7 @@ impl Command for TakeWhile { ]) .required( "predicate", - SyntaxShape::Closure(Some(vec![SyntaxShape::Any, SyntaxShape::Int])), + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), "The predicate that element(s) must match.", ) .category(Category::Filters) From cfdb4bbf255ade8ee618d722f3291082c59e66bb Mon Sep 17 00:00:00 2001 From: Bahex Date: Mon, 16 Dec 2024 15:13:51 +0300 Subject: [PATCH 25/26] `std/iter scan`: change closure signature to be consistent with `reduce` (#14596) # Description I noticed that `std/iter scan`'s closure has the order of parameters reversed compared to `reduce`, so changed it to be consistent. Also it didn't have `$acc` as `$in` like `reduce`, so fixed that as well. # User-Facing Changes > [!WARNING] > This is a breaking change for all operations where order of `$it` and `$acc` matter. - This is still fine. ```nushell [1 2 3] | iter scan 0 {|x, y| $x + $y} ``` - This is broken ```nushell [a b c d] | iter scan "" {|x, y| [$x, $y] | str join} -n ``` and should be changed to either one of these - ```nushell [a b c d] | iter scan "" {|it, acc| [$acc, $it] | str join} -n ``` - ```nushell [a b c d] | iter scan "" {|it| append $it | str join} -n ``` # Tests + Formatting Only change is in the std and its tests - :green_circle: toolkit test stdlib # After Submitting Mention in release notes --- crates/nu-std/std/iter/mod.nu | 8 +++++--- crates/nu-std/tests/test_iter.nu | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/nu-std/std/iter/mod.nu b/crates/nu-std/std/iter/mod.nu index 8c25269690..daa62d2dba 100644 --- a/crates/nu-std/std/iter/mod.nu +++ b/crates/nu-std/std/iter/mod.nu @@ -101,8 +101,9 @@ export def intersperse [ # -> list # Returns a list of intermediate steps performed by `reduce` # (`fold`). It takes two arguments, an initial value to seed the # initial state and a closure that takes two arguments, the first -# being the internal state and the second the list element in the -# current iteration. +# being the list element in the current iteration and the second +# the internal state. +# The internal state is also provided as pipeline input. # # # Example # ``` @@ -123,7 +124,8 @@ export def scan [ # -> list --noinit(-n) # remove the initial value from the result ] { reduce --fold [$init] {|it, acc| - $acc ++ [(do $fn ($acc | last) $it)] + let acc_last = $acc | last + $acc ++ [($acc_last | do $fn $it $acc_last)] } | if $noinit { $in | skip diff --git a/crates/nu-std/tests/test_iter.nu b/crates/nu-std/tests/test_iter.nu index 2b768c3d9d..3ace342788 100644 --- a/crates/nu-std/tests/test_iter.nu +++ b/crates/nu-std/tests/test_iter.nu @@ -49,7 +49,10 @@ def iter_scan [] { let scanned = ([1 2 3] | iter scan 0 {|x, y| $x + $y}) assert equal $scanned [0, 1, 3, 6] - let scanned = ([a b c d] | iter scan "" {|x, y| [$x, $y] | str join} -n) + let scanned = ([a b c d] | iter scan "" {|it, acc| [$acc, $it] | str join} -n) + assert equal $scanned ["a" "ab" "abc" "abcd"] + + let scanned = ([a b c d] | iter scan "" {|it, acc| append $it | str join} -n) assert equal $scanned ["a" "ab" "abc" "abcd"] } From 39770d41975a0dae3cdc89802215416a4c6671e4 Mon Sep 17 00:00:00 2001 From: Douglas <32344964+NotTheDr01ds@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:18:47 -0500 Subject: [PATCH 26/26] Moves additional env vars out of default_env and updates some transient prompt vars (#14579) # Description With `NU_LIB_DIRS`, `NU_PLUGIN_DIRS`, and `ENV_CONVERSIONS` now moved out of `default_env.nu`, we're down to just a few left. This moves all non-closure `PROMPT` variables out as well (and into Rust `main()`. It also: * Implements #14565 and sets the default `TRANSIENT_PROMPT_COMMAND_RIGHT` and `TRANSIENT_MULTILINE_INDICATOR` to an empty string so that they are removed for easier copying from the terminal. * Reverses portions of #14249 where I was overzealous in some of the variables that were imported * Fixes #12096 * Will be the final fix in place, I believe, to close #13670 # User-Facing Changes Transient prompt will now remove the right-prompt and multiline-indicator once a commandline has been entered. # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` - # After Submitting Release notes addition --- .../nu-utils/src/default_files/default_env.nu | 5 ----- src/main.rs | 22 ++++++++++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/crates/nu-utils/src/default_files/default_env.nu b/crates/nu-utils/src/default_files/default_env.nu index 66b442ce7a..ae2f1ae719 100644 --- a/crates/nu-utils/src/default_files/default_env.nu +++ b/crates/nu-utils/src/default_files/default_env.nu @@ -17,11 +17,6 @@ $env.PROMPT_COMMAND = $env.PROMPT_COMMAND? | default {|| $path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)" } -$env.PROMPT_INDICATOR = $env.PROMPT_INDICATOR? | default "> " -$env.PROMPT_INDICATOR_VI_NORMAL = $env.PROMPT_INDICATOR_VI_NORMAL? | default "> " -$env.PROMPT_INDICATOR_VI_INSERT = $env.PROMPT_INDICATOR_VI_INSERT? | default ": " -$env.PROMPT_MULTILINE_INDICATOR = $env.PROMPT_MULTILINE_INDICATOR? | default "::: " - $env.PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT? | default {|| # create a right prompt in magenta with green separators and am/pm underlined let time_segment = ([ diff --git a/src/main.rs b/src/main.rs index 7d39aef02b..4ebc215531 100644 --- a/src/main.rs +++ b/src/main.rs @@ -320,9 +320,29 @@ fn main() -> Result<()> { "NU_VERSION".to_string(), Value::string(env!("CARGO_PKG_VERSION"), Span::unknown()), ); - // Add SHLVL if interactive if engine_state.is_interactive { + engine_state.add_env_var("PROMPT_INDICATOR".to_string(), Value::test_string("> ")); + engine_state.add_env_var( + "PROMPT_INDICATOR_VI_NORMAL".to_string(), + Value::test_string("> "), + ); + engine_state.add_env_var( + "PROMPT_INDICATOR_VI_INSERT".to_string(), + Value::test_string(": "), + ); + engine_state.add_env_var( + "PROMPT_MULTILINE_INDICATOR".to_string(), + Value::test_string("::: "), + ); + engine_state.add_env_var( + "TRANSIENT_PROMPT_MULTILINE_INDICATOR".to_string(), + Value::test_string(""), + ); + engine_state.add_env_var( + "TRANSIENT_PROMPT_COMMAND_RIGHT".to_string(), + Value::test_string(""), + ); let mut shlvl = engine_state .get_env_var("SHLVL") .map(|x| x.as_str().unwrap_or("0").parse::().unwrap_or(0))