nushell/crates/nu-parser/src/parse_keywords.rs

3927 lines
141 KiB
Rust
Raw Normal View History

Custom command input/output types (#9690) # Description This adds input/output types to custom commands. These are input/output pairs that related an input type to an output type. For example (a single int-to-int input/output pair): ``` def foo []: int -> int { ... } ``` You can also have multiple input/output pairs: ``` def bar []: [int -> string, string -> list<string>] { ... } ``` These types are checked during definition time in the parser. If the block does not match the type, the user will get a parser error. This `:` to begin the input/output signatures should immediately follow the argument signature as shown above. The PR also improves type parsing by re-using the shape parser. The shape parser is now the canonical way to parse types/shapes in user code. This PR also splits `extern` into `extern`/`extern-wrapped` because of the parser limitation that a multi-span argument (which Signature now is) can't precede an optional argument. `extern-wrapped` now takes the required block that was previously optional. # User-Facing Changes The change to `extern` to split into `extern` and `extern-wrapped` is a breaking change. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-14 21:51:28 +00:00
use crate::{
parse_block,
parser_path::ParserPath,
type_check::{check_block_input_output, type_compatible},
};
use itertools::Itertools;
use log::trace;
use nu_path::canonicalize_with;
2021-09-26 18:39:19 +00:00
use nu_protocol::{
ast::{
Argument, Block, Call, Expr, Expression, ImportPattern, ImportPatternHead,
ImportPatternMember, Pipeline, PipelineElement,
},
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
engine::{StateWorkingSet, DEFAULT_OVERLAY_NAME},
eval_const::eval_constant,
span, Alias, BlockId, DeclId, Exportable, Module, ModuleId, ParseError, PositionalArg,
ResolvedImportPattern, Span, Spanned, SyntaxShape, Type, VarId,
2021-09-26 18:39:19 +00:00
};
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
pub const LIB_DIRS_VAR: &str = "NU_LIB_DIRS";
#[cfg(feature = "plugin")]
pub const PLUGIN_DIRS_VAR: &str = "NU_PLUGIN_DIRS";
2021-09-26 18:39:19 +00:00
use crate::{
is_math_expression_like,
known_external::KnownExternal,
lex,
2022-12-22 11:41:44 +00:00
lite_parser::{lite_parse, LiteCommand, LiteElement},
2021-09-26 18:39:19 +00:00
parser::{
check_call, check_name, garbage, garbage_pipeline, parse, parse_call, parse_expression,
parse_full_signature, parse_import_pattern, parse_internal_call, parse_multispan_value,
parse_string, parse_value, parse_var_with_opt_type, trim_quotes, ParsedInternalCall,
2021-09-26 18:39:19 +00:00
},
unescape_unquote_string, Token, TokenContents,
2021-09-26 18:39:19 +00:00
};
2023-03-10 21:20:31 +00:00
/// These parser keywords can be aliased
pub const ALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[b"overlay hide", b"overlay new", b"overlay use"];
pub const RESERVED_VARIABLE_NAMES: [&str; 3] = ["in", "nu", "env"];
2023-03-10 21:20:31 +00:00
/// These parser keywords cannot be aliased (either not possible, or support not yet added)
pub const UNALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[
b"export",
b"def",
b"export def",
b"for",
b"extern",
b"export extern",
b"alias",
b"export alias",
b"export-env",
b"module",
b"use",
b"export use",
b"hide",
// b"overlay",
// b"overlay hide",
// b"overlay new",
// b"overlay use",
b"let",
b"const",
b"mut",
b"source",
b"where",
b"register",
];
/// Check whether spans start with a parser keyword that can be aliased
pub fn is_unaliasable_parser_keyword(working_set: &StateWorkingSet, spans: &[Span]) -> bool {
// try two words
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
if let (Some(span1), Some(span2)) = (spans.first(), spans.get(1)) {
2023-03-10 21:20:31 +00:00
let cmd_name = working_set.get_span_contents(span(&[*span1, *span2]));
return UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name);
}
// try one word
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
if let Some(span1) = spans.first() {
2023-03-10 21:20:31 +00:00
let cmd_name = working_set.get_span_contents(*span1);
UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name)
} else {
false
}
}
/// This is a new more compact method of calling parse_xxx() functions without repeating the
/// parse_call() in each function. Remaining keywords can be moved here.
pub fn parse_keyword(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
is_subexpression: bool,
) -> Pipeline {
let call_expr = parse_call(
2023-03-10 21:20:31 +00:00
working_set,
&lite_command.parts,
lite_command.parts[0],
is_subexpression,
);
// if err.is_some() {
// return (Pipeline::from_vec(vec![call_expr]), err);
// }
2023-03-10 21:20:31 +00:00
if let Expression {
expr: Expr::Call(call),
..
} = call_expr.clone()
{
// Apply parse keyword side effects
let cmd = working_set.get_decl(call.decl_id);
// check help flag first.
if call.named_iter().any(|(flag, _, _)| flag.item == "help") {
let call_span = call.span();
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]);
}
2023-03-10 21:20:31 +00:00
match cmd.name() {
"overlay hide" => parse_overlay_hide(working_set, call),
"overlay new" => parse_overlay_new(working_set, call),
"overlay use" => parse_overlay_use(working_set, call),
_ => Pipeline::from_vec(vec![call_expr]),
2023-03-10 21:20:31 +00:00
}
} else {
Pipeline::from_vec(vec![call_expr])
2023-03-10 21:20:31 +00:00
}
}
pub fn parse_def_predecl(working_set: &mut StateWorkingSet, spans: &[Span]) {
let mut pos = 0;
2021-09-26 18:39:19 +00:00
let def_type_name = if spans.len() >= 3 {
// definition can't have only two spans, minimum is 3, e.g., 'extern spam []'
let first_word = working_set.get_span_contents(spans[0]);
if first_word == b"export" {
pos += 2;
} else {
pos += 1;
}
working_set.get_span_contents(spans[pos - 1]).to_vec()
2021-09-28 17:29:38 +00:00
} else {
return;
2021-09-28 17:29:38 +00:00
};
if def_type_name != b"def" && def_type_name != b"extern" {
return;
}
// Now, pos should point at the next span after the def-like call.
// Skip all potential flags, like --env, --wrapped or --help:
while pos < spans.len()
&& working_set
.get_span_contents(spans[pos])
.starts_with(&[b'-'])
{
pos += 1;
}
if pos >= spans.len() {
// This can happen if the call ends with a flag, e.g., 'def --help'
return;
}
// Now, pos should point at the command name.
let name_pos = pos;
let Some(name) = parse_string(working_set, spans[name_pos]).as_string() else {
return;
};
if name.contains('#')
|| name.contains('^')
|| name.parse::<bytesize::ByteSize>().is_ok()
|| name.parse::<f64>().is_ok()
{
working_set.error(ParseError::CommandDefNotValid(spans[name_pos]));
return;
}
// Find signature
let mut signature_pos = None;
while pos < spans.len() {
if working_set
.get_span_contents(spans[pos])
.starts_with(&[b'['])
|| working_set
.get_span_contents(spans[pos])
.starts_with(&[b'('])
{
signature_pos = Some(pos);
break;
}
pos += 1;
}
2021-09-26 18:39:19 +00:00
let Some(signature_pos) = signature_pos else {
return;
};
let mut allow_unknown_args = false;
for span in spans {
if working_set.get_span_contents(*span) == b"--wrapped" && def_type_name == b"def" {
allow_unknown_args = true;
2021-09-26 18:39:19 +00:00
}
}
let starting_error_count = working_set.parse_errors.len();
working_set.enter_scope();
// FIXME: because parse_signature will update the scope with the variables it sees
// we end up parsing the signature twice per def. The first time is during the predecl
// so that we can see the types that are part of the signature, which we need for parsing.
// The second time is when we actually parse the body itworking_set.
// We can't reuse the first time because the variables that are created during parse_signature
// are lost when we exit the scope below.
let sig = parse_full_signature(working_set, &spans[signature_pos..]);
working_set.parse_errors.truncate(starting_error_count);
working_set.exit_scope();
let Some(mut signature) = sig.as_signature() else {
return;
};
signature.name = name;
if allow_unknown_args {
signature.allows_unknown_args = true;
}
let decl = signature.predeclare();
if working_set.add_predecl(decl).is_some() {
working_set.error(ParseError::DuplicateCommandDef(spans[name_pos]));
2021-09-26 18:39:19 +00:00
}
}
pub fn parse_for(working_set: &mut StateWorkingSet, spans: &[Span]) -> Expression {
// Checking that the function is used with the correct name
// Maybe this is not necessary but it is a sanity check
if working_set.get_span_contents(spans[0]) != b"for" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'for' function".into(),
span(spans),
));
return garbage(spans[0]);
}
// Parsing the spans and checking that they match the register signature
// Using a parsed call makes more sense than checking for how many spans are in the call
// Also, by creating a call, it can be checked if it matches the declaration signature
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span) = match working_set.find_decl(b"for") {
None => {
working_set.error(ParseError::UnknownState(
"internal error: for declaration not found".into(),
span(spans),
));
return garbage(spans[0]);
}
Some(decl_id) => {
working_set.enter_scope();
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
working_set.exit_scope();
let call_span = span(spans);
let decl = working_set.get_decl(decl_id);
let sig = decl.signature();
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &sig, &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage(spans[0]);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
};
}
// Let's get our block and make sure it has the right signature
if let Some(arg) = call.positional_nth(2) {
match arg {
Expression {
expr: Expr::Block(block_id),
..
}
| Expression {
expr: Expr::RowCondition(block_id),
..
} => {
let block = working_set.get_block_mut(*block_id);
block.signature = Box::new(sig);
}
_ => {}
}
}
(call, call_span)
}
};
// All positional arguments must be in the call positional vector by this point
let var_decl = call.positional_nth(0).expect("for call already checked");
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
let iteration_expr = call.positional_nth(1).expect("for call already checked");
let block = call.positional_nth(2).expect("for call already checked");
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
let iteration_expr_ty = iteration_expr.ty.clone();
// Figure out the type of the variable the `for` uses for iteration
let var_type = match iteration_expr_ty {
Type::List(x) => *x,
Type::Table(x) => Type::Record(x),
x => x,
};
if let (Some(var_id), Some(block_id)) = (&var_decl.as_var(), block.as_block()) {
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
working_set.set_variable_type(*var_id, var_type.clone());
let block = working_set.get_block_mut(block_id);
block.signature.required_positional.insert(
0,
PositionalArg {
name: String::new(),
desc: String::new(),
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
shape: var_type.to_shape(),
var_id: Some(*var_id),
2022-03-07 20:08:56 +00:00
default_value: None,
},
);
}
Expression {
expr: Expr::Call(call),
span: call_span,
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
ty: Type::Nothing,
custom_completion: None,
}
}
/// If `name` is a keyword, emit an error.
fn verify_not_reserved_variable_name(working_set: &mut StateWorkingSet, name: &str, span: Span) {
if RESERVED_VARIABLE_NAMES.contains(&name) {
working_set.error(ParseError::NameIsBuiltinVar(name.to_string(), span))
}
}
// Returns also the parsed command name and ID
2021-09-26 18:39:19 +00:00
pub fn parse_def(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
module_name: Option<&[u8]>,
) -> (Pipeline, Option<(Vec<u8>, DeclId)>) {
let spans = &lite_command.parts[..];
2022-12-30 15:44:37 +00:00
let (usage, extra_usage) = working_set.build_usage(&lite_command.comments);
// Checking that the function is used with the correct name
// Maybe this is not necessary but it is a sanity check
// Note: "export def" is treated the same as "def"
let (name_span, split_id) =
if spans.len() > 1 && working_set.get_span_contents(spans[0]) == b"export" {
(spans[1], 2)
} else {
(spans[0], 1)
};
let def_call = working_set.get_span_contents(name_span).to_vec();
if def_call != b"def" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for def function".into(),
span(spans),
));
return (garbage_pipeline(spans), None);
}
2021-09-27 01:03:50 +00:00
// Parsing the spans and checking that they match the register signature
// Using a parsed call makes more sense than checking for how many spans are in the call
// Also, by creating a call, it can be checked if it matches the declaration signature
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span) = match working_set.find_decl(&def_call) {
None => {
working_set.error(ParseError::UnknownState(
"internal error: def declaration not found".into(),
span(spans),
));
return (garbage_pipeline(spans), None);
}
Some(decl_id) => {
working_set.enter_scope();
let (command_spans, rest_spans) = spans.split_at(split_id);
// Find the first span that is not a flag
let mut decl_name_span = None;
for span in rest_spans {
if !working_set.get_span_contents(*span).starts_with(&[b'-']) {
decl_name_span = Some(*span);
break;
}
}
if let Some(name_span) = decl_name_span {
// Check whether name contains [] or () -- possible missing space error
if let Some(err) = detect_params_in_name(
working_set,
name_span,
String::from_utf8_lossy(&def_call).as_ref(),
) {
working_set.error(err);
return (garbage_pipeline(spans), None);
}
}
let starting_error_count = working_set.parse_errors.len();
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, span(command_spans), rest_spans, decl_id);
// This is to preserve the order of the errors so that
// the check errors below come first
let mut new_errors = working_set.parse_errors[starting_error_count..].to_vec();
working_set.parse_errors.truncate(starting_error_count);
working_set.exit_scope();
2021-09-27 01:03:50 +00:00
let call_span = span(spans);
let decl = working_set.get_decl(decl_id);
let sig = decl.signature();
// Let's get our block and make sure it has the right signature
if let Some(arg) = call.positional_nth(2) {
match arg {
Expression {
expr: Expr::Block(block_id),
..
}
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
| Expression {
expr: Expr::Closure(block_id),
..
}
| Expression {
expr: Expr::RowCondition(block_id),
..
} => {
let block = working_set.get_block_mut(*block_id);
block.signature = Box::new(sig.clone());
}
_ => {}
}
}
2021-09-27 01:03:50 +00:00
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &sig, &call);
working_set.parse_errors.append(&mut new_errors);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return (garbage_pipeline(spans), None);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]),
None,
);
}
2021-09-27 01:03:50 +00:00
(call, call_span)
}
};
2021-09-27 01:03:50 +00:00
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(has_env) = has_flag_wrapped(working_set, &call, "env") else {
return (garbage_pipeline(spans), None);
};
let Ok(has_wrapped) = has_flag_wrapped(working_set, &call, "wrapped") else {
return (garbage_pipeline(spans), None);
};
// All positional arguments must be in the call positional vector by this point
let name_expr = call.positional_nth(0).expect("def call already checked");
let sig = call.positional_nth(1).expect("def call already checked");
let block = call.positional_nth(2).expect("def call already checked");
2021-09-27 01:03:50 +00:00
let name = if let Some(name) = name_expr.as_string() {
if let Some(mod_name) = module_name {
if name.as_bytes() == mod_name {
let name_expr_span = name_expr.span;
working_set.error(ParseError::NamedAsModule(
"command".to_string(),
name,
"main".to_string(),
name_expr_span,
));
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
None,
);
}
}
name
} else {
working_set.error(ParseError::UnknownState(
"Could not get string from string expression".into(),
name_expr.span,
));
return (garbage_pipeline(spans), None);
};
let mut result = None;
if let (Some(mut signature), Some(block_id)) = (sig.as_signature(), block.as_block()) {
for arg_name in &signature.required_positional {
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
}
for arg_name in &signature.optional_positional {
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
}
for arg_name in &signature.rest_positional {
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
}
for flag_name in &signature.get_names() {
verify_not_reserved_variable_name(working_set, flag_name, sig.span);
}
if has_wrapped {
if let Some(rest) = &signature.rest_positional {
if let Some(var_id) = rest.var_id {
let rest_var = &working_set.get_variable(var_id);
if rest_var.ty != Type::Any && rest_var.ty != Type::List(Box::new(Type::String))
{
working_set.error(ParseError::TypeMismatchHelp(
Type::List(Box::new(Type::String)),
rest_var.ty.clone(),
rest_var.declaration_span,
format!("...rest-like positional argument used in 'def --wrapped' supports only strings. Change the type annotation of ...{} to 'string'.", &rest.name)));
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
result,
);
}
}
} else {
working_set.error(ParseError::MissingPositional("...rest-like positional argument".to_string(), name_expr.span, "def --wrapped must have a ...rest-like positional argument. Add '...rest: string' to the command's signature.".to_string()));
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
result,
);
}
}
if let Some(decl_id) = working_set.find_predecl(name.as_bytes()) {
let declaration = working_set.get_decl_mut(decl_id);
signature.name = name.clone();
if !has_wrapped {
*signature = signature.add_help();
}
signature.usage = usage;
2022-12-30 15:44:37 +00:00
signature.extra_usage = extra_usage;
signature.allows_unknown_args = has_wrapped;
*declaration = signature.clone().into_block_command(block_id);
let block = working_set.get_block_mut(block_id);
let calls_itself = block_calls_itself(block, decl_id);
block.recursive = Some(calls_itself);
block.signature = signature;
block.redirect_env = has_env;
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
Custom command input/output types (#9690) # Description This adds input/output types to custom commands. These are input/output pairs that related an input type to an output type. For example (a single int-to-int input/output pair): ``` def foo []: int -> int { ... } ``` You can also have multiple input/output pairs: ``` def bar []: [int -> string, string -> list<string>] { ... } ``` These types are checked during definition time in the parser. If the block does not match the type, the user will get a parser error. This `:` to begin the input/output signatures should immediately follow the argument signature as shown above. The PR also improves type parsing by re-using the shape parser. The shape parser is now the canonical way to parse types/shapes in user code. This PR also splits `extern` into `extern`/`extern-wrapped` because of the parser limitation that a multi-span argument (which Signature now is) can't precede an optional argument. `extern-wrapped` now takes the required block that was previously optional. # User-Facing Changes The change to `extern` to split into `extern` and `extern-wrapped` is a breaking change. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-14 21:51:28 +00:00
if block.signature.input_output_types.is_empty() {
block
.signature
.input_output_types
.push((Type::Any, Type::Any));
}
let block = working_set.get_block(block_id);
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
Custom command input/output types (#9690) # Description This adds input/output types to custom commands. These are input/output pairs that related an input type to an output type. For example (a single int-to-int input/output pair): ``` def foo []: int -> int { ... } ``` You can also have multiple input/output pairs: ``` def bar []: [int -> string, string -> list<string>] { ... } ``` These types are checked during definition time in the parser. If the block does not match the type, the user will get a parser error. This `:` to begin the input/output signatures should immediately follow the argument signature as shown above. The PR also improves type parsing by re-using the shape parser. The shape parser is now the canonical way to parse types/shapes in user code. This PR also splits `extern` into `extern`/`extern-wrapped` because of the parser limitation that a multi-span argument (which Signature now is) can't precede an optional argument. `extern-wrapped` now takes the required block that was previously optional. # User-Facing Changes The change to `extern` to split into `extern` and `extern-wrapped` is a breaking change. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-14 21:51:28 +00:00
let typecheck_errors = check_block_input_output(working_set, block);
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
Custom command input/output types (#9690) # Description This adds input/output types to custom commands. These are input/output pairs that related an input type to an output type. For example (a single int-to-int input/output pair): ``` def foo []: int -> int { ... } ``` You can also have multiple input/output pairs: ``` def bar []: [int -> string, string -> list<string>] { ... } ``` These types are checked during definition time in the parser. If the block does not match the type, the user will get a parser error. This `:` to begin the input/output signatures should immediately follow the argument signature as shown above. The PR also improves type parsing by re-using the shape parser. The shape parser is now the canonical way to parse types/shapes in user code. This PR also splits `extern` into `extern`/`extern-wrapped` because of the parser limitation that a multi-span argument (which Signature now is) can't precede an optional argument. `extern-wrapped` now takes the required block that was previously optional. # User-Facing Changes The change to `extern` to split into `extern` and `extern-wrapped` is a breaking change. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-14 21:51:28 +00:00
working_set
.parse_errors
.extend_from_slice(&typecheck_errors);
result = Some((name.as_bytes().to_vec(), decl_id));
2021-09-27 01:03:50 +00:00
} else {
working_set.error(ParseError::InternalError(
"Predeclaration failed to add declaration".into(),
name_expr.span,
));
};
}
2021-09-27 01:03:50 +00:00
// It's OK if it returns None: The decl was already merged in previous parse pass.
working_set.merge_predecl(name.as_bytes());
(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
result,
)
2021-09-26 18:39:19 +00:00
}
pub fn parse_extern(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
module_name: Option<&[u8]>,
) -> Pipeline {
let spans = &lite_command.parts;
2022-12-30 15:44:37 +00:00
let (usage, extra_usage) = working_set.build_usage(&lite_command.comments);
// Checking that the function is used with the correct name
// Maybe this is not necessary but it is a sanity check
let (name_span, split_id) =
if spans.len() > 1 && (working_set.get_span_contents(spans[0]) == b"export") {
(spans[1], 2)
} else {
(spans[0], 1)
};
let extern_call = working_set.get_span_contents(name_span).to_vec();
if extern_call != b"extern" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for extern command".into(),
span(spans),
));
return garbage_pipeline(spans);
}
// Parsing the spans and checking that they match the register signature
// Using a parsed call makes more sense than checking for how many spans are in the call
// Also, by creating a call, it can be checked if it matches the declaration signature
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span) = match working_set.find_decl(&extern_call) {
None => {
working_set.error(ParseError::UnknownState(
"internal error: def declaration not found".into(),
span(spans),
));
return garbage_pipeline(spans);
}
Some(decl_id) => {
working_set.enter_scope();
let (command_spans, rest_spans) = spans.split_at(split_id);
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
if let Some(name_span) = rest_spans.first() {
if let Some(err) = detect_params_in_name(
working_set,
*name_span,
String::from_utf8_lossy(&extern_call).as_ref(),
) {
working_set.error(err);
return garbage_pipeline(spans);
}
}
let ParsedInternalCall { call, .. } =
parse_internal_call(working_set, span(command_spans), rest_spans, decl_id);
working_set.exit_scope();
let call_span = span(spans);
//let decl = working_set.get_decl(decl_id);
//let sig = decl.signature();
(call, call_span)
}
};
let name_expr = call.positional_nth(0);
let sig = call.positional_nth(1);
let body = call.positional_nth(2);
if let (Some(name_expr), Some(sig)) = (name_expr, sig) {
if let (Some(name), Some(mut signature)) = (&name_expr.as_string(), sig.as_signature()) {
if let Some(mod_name) = module_name {
if name.as_bytes() == mod_name {
let name_expr_span = name_expr.span;
working_set.error(ParseError::NamedAsModule(
"known external".to_string(),
name.clone(),
"main".to_string(),
name_expr_span,
));
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]);
}
}
if let Some(decl_id) = working_set.find_predecl(name.as_bytes()) {
let declaration = working_set.get_decl_mut(decl_id);
let external_name = if let Some(mod_name) = module_name {
if name.as_bytes() == b"main" {
String::from_utf8_lossy(mod_name).to_string()
} else {
name.clone()
}
} else {
name.clone()
};
signature.name = external_name.clone();
signature.usage = usage.clone();
2022-12-30 15:44:37 +00:00
signature.extra_usage = extra_usage.clone();
signature.allows_unknown_args = true;
if let Some(block_id) = body.and_then(|x| x.as_block()) {
if signature.rest_positional.is_none() {
working_set.error(ParseError::InternalError(
"Extern block must have a rest positional argument".into(),
name_expr.span,
));
} else {
*declaration = signature.clone().into_block_command(block_id);
let block = working_set.get_block_mut(block_id);
let calls_itself = block_calls_itself(block, decl_id);
block.recursive = Some(calls_itself);
block.signature = signature;
}
} else {
let decl = KnownExternal {
name: external_name,
usage,
extra_usage,
signature,
};
*declaration = Box::new(decl);
}
} else {
working_set.error(ParseError::InternalError(
"Predeclaration failed to add declaration".into(),
spans[split_id],
));
};
}
if let Some(name) = name_expr.as_string() {
// It's OK if it returns None: The decl was already merged in previous parse pass.
working_set.merge_predecl(name.as_bytes());
} else {
working_set.error(ParseError::UnknownState(
"Could not get string from string expression".into(),
name_expr.span,
));
}
}
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}])
}
fn block_calls_itself(block: &Block, decl_id: usize) -> bool {
block.pipelines.iter().any(|pipeline| {
pipeline
.elements
.iter()
.any(|pipe_element| match pipe_element {
PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(call_expr),
..
},
) => {
if call_expr.decl_id == decl_id {
return true;
}
call_expr.arguments.iter().any(|arg| match arg {
Argument::Positional(Expression { expr, .. }) => match expr {
Expr::Keyword(.., expr) => {
let expr = expr.as_ref();
let Expression { expr, .. } = expr;
match expr {
Expr::Call(call_expr2) => call_expr2.decl_id == decl_id,
_ => false,
}
}
Expr::Call(call_expr2) => call_expr2.decl_id == decl_id,
_ => false,
},
_ => false,
})
}
_ => false,
})
})
}
2021-09-26 18:39:19 +00:00
pub fn parse_alias(
working_set: &mut StateWorkingSet,
2022-12-30 15:44:37 +00:00
lite_command: &LiteCommand,
module_name: Option<&[u8]>,
) -> Pipeline {
2022-12-30 15:44:37 +00:00
let spans = &lite_command.parts;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
let (name_span, split_id) =
if spans.len() > 1 && working_set.get_span_contents(spans[0]) == b"export" {
(spans[1], 2)
} else {
(spans[0], 1)
};
let name = working_set.get_span_contents(name_span);
if name != b"alias" {
working_set.error(ParseError::InternalError(
"Alias statement unparsable".into(),
span(spans),
));
return garbage_pipeline(spans);
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
if let Some(span) = check_name(working_set, spans) {
return Pipeline::from_vec(vec![garbage(*span)]);
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(b"alias") {
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
let (command_spans, rest_spans) = spans.split_at(split_id);
let original_starting_error_count = working_set.parse_errors.len();
2023-03-10 21:20:31 +00:00
let ParsedInternalCall {
call: alias_call,
output,
..
} = parse_internal_call(working_set, span(command_spans), rest_spans, decl_id);
working_set
.parse_errors
.truncate(original_starting_error_count);
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(has_help_flag) = has_flag_wrapped(working_set, &alias_call, "help") else {
return garbage_pipeline(spans);
};
2023-03-10 21:20:31 +00:00
let alias_pipeline = Pipeline::from_vec(vec![Expression {
2023-04-06 21:05:09 +00:00
expr: Expr::Call(alias_call.clone()),
2023-03-10 21:20:31 +00:00
span: span(spans),
ty: output,
custom_completion: None,
}]);
if has_help_flag {
return alias_pipeline;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
let Some(alias_name_expr) = alias_call.positional_nth(0) else {
working_set.error(ParseError::UnknownState(
"Missing positional after call check".to_string(),
span(spans),
));
return garbage_pipeline(spans);
2023-04-06 21:05:09 +00:00
};
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
2023-04-06 21:05:09 +00:00
let alias_name = if let Some(name) = alias_name_expr.as_string() {
if name.contains('#')
|| name.contains('^')
|| name.parse::<bytesize::ByteSize>().is_ok()
|| name.parse::<f64>().is_ok()
{
working_set.error(ParseError::AliasNotValid(alias_name_expr.span));
return garbage_pipeline(spans);
2023-04-06 21:05:09 +00:00
} else {
name
}
2023-04-06 21:05:09 +00:00
} else {
working_set.error(ParseError::AliasNotValid(alias_name_expr.span));
return garbage_pipeline(spans);
2023-04-06 21:05:09 +00:00
};
2023-04-06 21:05:09 +00:00
if spans.len() >= split_id + 3 {
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
if let Some(mod_name) = module_name {
2023-04-06 21:05:09 +00:00
if alias_name.as_bytes() == mod_name {
working_set.error(ParseError::NamedAsModule(
"alias".to_string(),
alias_name,
"main".to_string(),
spans[split_id],
));
return alias_pipeline;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
2023-04-06 21:05:09 +00:00
if alias_name == "main" {
working_set.error(ParseError::ExportMainAliasNotAllowed(spans[split_id]));
return alias_pipeline;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
}
let _equals = working_set.get_span_contents(spans[split_id + 1]);
let replacement_spans = &spans[(split_id + 2)..];
let first_bytes = working_set.get_span_contents(replacement_spans[0]);
if first_bytes != b"if"
&& first_bytes != b"match"
&& is_math_expression_like(working_set, replacement_spans[0])
{
// TODO: Maybe we need to implement a Display trait for Expression?
let starting_error_count = working_set.parse_errors.len();
let expr = parse_expression(working_set, replacement_spans, false);
working_set.parse_errors.truncate(starting_error_count);
let msg = format!("{:?}", expr.expr);
let msg_parts: Vec<&str> = msg.split('(').collect();
working_set.error(ParseError::CantAliasExpression(
msg_parts[0].to_string(),
replacement_spans[0],
));
return alias_pipeline;
}
let starting_error_count = working_set.parse_errors.len();
working_set.search_predecls = false;
let expr = parse_call(
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
working_set,
replacement_spans,
replacement_spans[0],
false, // TODO: Should this be set properly???
);
working_set.search_predecls = true;
if starting_error_count != working_set.parse_errors.len() {
if let Some(e) = working_set.parse_errors.get(starting_error_count) {
if let ParseError::MissingPositional(..) = e {
working_set
.parse_errors
.truncate(original_starting_error_count);
// ignore missing required positional
} else {
return garbage_pipeline(replacement_spans);
}
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
}
let (command, wrapped_call) = match expr {
Expression {
2023-03-10 21:20:31 +00:00
expr: Expr::Call(ref rhs_call),
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
..
2023-03-10 21:20:31 +00:00
} => {
let cmd = working_set.get_decl(rhs_call.decl_id);
if cmd.is_parser_keyword()
&& !ALIASABLE_PARSER_KEYWORDS.contains(&cmd.name().as_bytes())
{
working_set.error(ParseError::CantAliasKeyword(
ALIASABLE_PARSER_KEYWORDS
.iter()
.map(|bytes| String::from_utf8_lossy(bytes).to_string())
.collect::<Vec<String>>()
.join(", "),
rhs_call.head,
));
return alias_pipeline;
2023-03-10 21:20:31 +00:00
}
(Some(cmd.clone_box()), expr)
}
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
Expression {
expr: Expr::ExternalCall(..),
..
} => (None, expr),
_ => {
working_set.error(ParseError::InternalError(
"Parsed call not a call".into(),
expr.span,
));
return alias_pipeline;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
};
// Tries to build a useful usage string
let (usage, extra_usage) = match lite_command.comments.is_empty() {
// First from comments, if any are present
false => working_set.build_usage(&lite_command.comments),
// Then from the command itself
true => match alias_call.arguments.get(1) {
Some(Argument::Positional(Expression {
expr: Expr::Keyword(.., expr),
..
})) => {
let aliased = working_set.get_span_contents(expr.span);
(
format!("Alias for `{}`", String::from_utf8_lossy(aliased)),
String::new(),
)
}
// Then with a default.
_ => ("User declared alias".into(), String::new()),
},
};
let decl = Alias {
2023-04-06 21:05:09 +00:00
name: alias_name,
command,
wrapped_call,
2023-08-17 08:58:38 +00:00
usage,
extra_usage,
};
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
working_set.add_decl(Box::new(decl));
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
// special case for `alias foo=bar`
if spans.len() == 2 && working_set.get_span_contents(spans[1]).contains(&b'=') {
let arg = String::from_utf8_lossy(working_set.get_span_contents(spans[1]));
// split at '='. Note that the output must never be None, the
// `unwrap` is just to avoid the possibility of panic, if the
// invariant is broken.
let (name, initial_value) = arg.split_once('=').unwrap_or((&arg, ""));
let name = if name.is_empty() { "{name}" } else { name };
let initial_value = if initial_value.is_empty() {
"{initial_value}"
} else {
initial_value
};
working_set.error(ParseError::IncorrectValue(
"alias argument".into(),
spans[1],
format!("Make sure to put spaces around '=': alias {name} = {initial_value}"),
))
} else if spans.len() < 4 {
working_set.error(ParseError::IncorrectValue(
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
"Incomplete alias".into(),
span(&spans[..split_id]),
"incomplete alias".into(),
));
}
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
return alias_pipeline;
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
working_set.error(ParseError::InternalError(
"Alias statement unparsable".into(),
span(spans),
));
garbage_pipeline(spans)
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
}
// This one will trigger if `export` appears during eval, e.g., in a script
pub fn parse_export_in_block(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
) -> Pipeline {
let call_span = span(&lite_command.parts);
let full_name = if lite_command.parts.len() > 1 {
let sub = working_set.get_span_contents(lite_command.parts[1]);
match sub {
b"alias" | b"def" | b"extern" | b"use" | b"module" | b"const" => {
[b"export ", sub].concat()
}
_ => b"export".to_vec(),
}
} else {
b"export".to_vec()
};
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(&full_name) {
let ParsedInternalCall { call, output, .. } = parse_internal_call(
working_set,
if full_name == b"export" {
lite_command.parts[0]
} else {
span(&lite_command.parts[0..2])
},
if full_name == b"export" {
&lite_command.parts[1..]
} else {
&lite_command.parts[2..]
},
decl_id,
);
let decl = working_set.get_decl(decl_id);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage_pipeline(&lite_command.parts);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]);
}
} else {
working_set.error(ParseError::UnknownState(
format!(
"internal error: '{}' declaration not found",
String::from_utf8_lossy(&full_name)
),
span(&lite_command.parts),
));
return garbage_pipeline(&lite_command.parts);
};
if &full_name == b"export" {
// export by itself is meaningless
working_set.error(ParseError::UnexpectedKeyword(
"export".into(),
lite_command.parts[0],
));
return garbage_pipeline(&lite_command.parts);
}
match full_name.as_slice() {
b"export alias" => parse_alias(working_set, lite_command, None),
b"export def" => parse_def(working_set, lite_command, None).0,
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
b"export const" => parse_const(working_set, &lite_command.parts[1..]),
b"export use" => {
let (pipeline, _) = parse_use(working_set, &lite_command.parts);
pipeline
}
2023-05-06 20:55:10 +00:00
b"export module" => parse_module(working_set, lite_command, None).0,
b"export extern" => parse_extern(working_set, lite_command, None),
_ => {
working_set.error(ParseError::UnexpectedKeyword(
String::from_utf8_lossy(&full_name).to_string(),
lite_command.parts[0],
));
garbage_pipeline(&lite_command.parts)
}
}
}
// This one will trigger only in a module
pub fn parse_export_in_module(
2021-09-28 17:29:38 +00:00
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
module_name: &[u8],
) -> (Pipeline, Vec<Exportable>) {
let spans = &lite_command.parts[..];
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
let export_span = if let Some(sp) = spans.first() {
if working_set.get_span_contents(*sp) != b"export" {
working_set.error(ParseError::UnknownState(
"expected export statement".into(),
span(spans),
));
return (garbage_pipeline(spans), vec![]);
}
*sp
} else {
working_set.error(ParseError::UnknownState(
"got empty input for parsing export statement".into(),
span(spans),
));
return (garbage_pipeline(spans), vec![]);
};
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let export_decl_id = if let Some(id) = working_set.find_decl(b"export") {
id
} else {
working_set.error(ParseError::InternalError(
"missing export command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
2021-09-28 17:29:38 +00:00
let mut call = Box::new(Call {
head: spans[0],
decl_id: export_decl_id,
arguments: vec![],
redirect_stdout: true,
redirect_stderr: false,
parser_info: HashMap::new(),
});
2021-09-28 17:29:38 +00:00
let exportables = if let Some(kw_span) = spans.get(1) {
let kw_name = working_set.get_span_contents(*kw_span);
match kw_name {
2021-09-28 18:03:53 +00:00
b"def" => {
let lite_command = LiteCommand {
comments: lite_command.comments.clone(),
parts: spans[1..].to_vec(),
};
let (pipeline, cmd_result) =
parse_def(working_set, &lite_command, Some(module_name));
let mut result = vec![];
if let Some((decl_name, decl_id)) = cmd_result {
result.push(Exportable::Decl {
name: decl_name.to_vec(),
id: decl_id,
});
}
2021-09-28 18:03:53 +00:00
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def") {
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export def' command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
2021-09-28 18:03:53 +00:00
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref def_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
{
call = def_call.clone();
call.head = span(&spans[0..=1]);
call.decl_id = export_def_decl_id;
2021-09-28 18:03:53 +00:00
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
2021-09-28 18:03:53 +00:00
};
result
}
b"extern" => {
let lite_command = LiteCommand {
comments: lite_command.comments.clone(),
parts: spans[1..].to_vec(),
};
let extern_name = [b"export ", kw_name].concat();
let pipeline = parse_extern(working_set, &lite_command, Some(module_name));
let export_def_decl_id = if let Some(id) = working_set.find_decl(&extern_name) {
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export extern' command".into(),
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref def_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
{
call = def_call.clone();
call.head = span(&spans[0..=1]);
call.decl_id = export_def_decl_id;
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
};
let mut result = vec![];
let decl_name = match spans.get(2) {
Some(span) => working_set.get_span_contents(*span),
None => &[],
};
let decl_name = trim_quotes(decl_name);
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(decl_name) {
result.push(Exportable::Decl {
name: decl_name.to_vec(),
id: decl_id,
});
} else {
working_set.error(ParseError::InternalError(
"failed to find added declaration".into(),
span(&spans[1..]),
));
}
result
}
b"alias" => {
let lite_command = LiteCommand {
comments: lite_command.comments.clone(),
parts: spans[1..].to_vec(),
};
let pipeline = parse_alias(working_set, &lite_command, Some(module_name));
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let export_alias_decl_id = if let Some(id) = working_set.find_decl(b"export alias")
{
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export alias' command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
// Trying to warp the 'alias' call into the 'export alias' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref alias_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
{
call = alias_call.clone();
call.head = span(&spans[0..=1]);
call.decl_id = export_alias_decl_id;
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
};
let mut result = vec![];
let alias_name = match spans.get(2) {
Some(span) => working_set.get_span_contents(*span),
None => &[],
};
let alias_name = trim_quotes(alias_name);
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(alias_id) = working_set.find_decl(alias_name) {
Re-implement aliases (#8123) # Description This PR adds an alternative alias implementation. Old aliases still work but you need to use `old-alias` instead of `alias`. Instead of replacing spans in the original code and re-parsing, which proved to be extremely error-prone and a constant source of panics, the new implementation creates a new command that references the old command. Consider the new alias defined as `alias ll = ls -l`. The parser creates a new command called `ll` and remembers that it is actually a `ls` command called with the `-l` flag. Then, when the parser sees the `ll` command, it will translate it to `ls -l` and passes to it any parameters that were passed to the call to `ll`. It works quite similar to how known externals defined with `extern` are implemented. The new alias implementation should work the same way as the old aliases, including exporting from modules, referencing both known and unknown externals. It seems to preserve custom completions and pipeline metadata. It is quite robust in most cases but there are some rough edges (see later). Fixes https://github.com/nushell/nushell/issues/7648, https://github.com/nushell/nushell/issues/8026, https://github.com/nushell/nushell/issues/7512, https://github.com/nushell/nushell/issues/5780, https://github.com/nushell/nushell/issues/7754 No effect: https://github.com/nushell/nushell/issues/8122 (we might revisit the completions code after this PR) Should use custom command instead: https://github.com/nushell/nushell/issues/6048 # User-Facing Changes Since aliases are now basically commands, it has some new implications: 1. `alias spam = "spam"` (requires command call) * **workaround**: use `alias spam = echo "spam"` 2. `def foo [] { 'foo' }; alias foo = ls -l` (foo defined more than once) * **workaround**: use different name (commands also have this limitation) 4. `alias ls = (ls | sort-by type name -i)` * **workaround**: Use custom command. _The common issue with this is that it is currently not easy to pass flags through custom commands and command referencing itself will lead to stack overflow. Both of these issues are meant to be addressed._ 5. TODO: Help messages, `which` command, `$nu.scope.aliases`, etc. * Should we treat the aliases as commands or should they be separated from regular commands? 6. Needs better error message and syntax highlight for recursed alias (`alias f = f`) 7. Can't create alias with the same name as existing command (`alias ls = ls -a`) * Might be possible to add support for it (not 100% sure) 8. Standalone `alias` doesn't list aliases anymore 9. Can't alias parser keywords (e.g., stuff like `alias ou = overlay use` won't work) * TODO: Needs a better error message when attempting to do so # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-27 07:44:05 +00:00
result.push(Exportable::Decl {
name: alias_name.to_vec(),
id: alias_id,
});
} else {
working_set.error(ParseError::InternalError(
"failed to find added alias".into(),
span(&spans[1..]),
));
}
result
}
b"use" => {
let lite_command = LiteCommand {
comments: lite_command.comments.clone(),
parts: spans[1..].to_vec(),
};
let (pipeline, exportables) = parse_use(working_set, &lite_command.parts);
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let export_use_decl_id = if let Some(id) = working_set.find_decl(b"export use") {
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export use' command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
// Trying to warp the 'use' call into the 'export use' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref use_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
{
call = use_call.clone();
call.head = span(&spans[0..=1]);
call.decl_id = export_use_decl_id;
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
};
exportables
}
b"module" => {
2023-05-06 20:55:10 +00:00
let (pipeline, maybe_module_id) =
parse_module(working_set, lite_command, Some(module_name));
let export_module_decl_id =
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(id) = working_set.find_decl(b"export module") {
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export module' command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
// Trying to warp the 'module' call into the 'export module' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref module_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
{
call = module_call.clone();
call.head = span(&spans[0..=1]);
call.decl_id = export_module_decl_id;
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
};
let mut result = vec![];
if let Some(module_name_span) = spans.get(2) {
let module_name = working_set.get_span_contents(*module_name_span);
let module_name = trim_quotes(module_name);
2023-05-06 20:55:10 +00:00
if let Some(module_id) = maybe_module_id {
result.push(Exportable::Module {
2023-05-06 20:55:10 +00:00
name: working_set.get_module(module_id).name(),
id: module_id,
});
} else {
working_set.error(ParseError::InternalError(
2023-05-06 20:55:10 +00:00
format!(
"failed to find added module '{}'",
String::from_utf8_lossy(module_name)
),
span(&spans[1..]),
));
}
}
result
}
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
b"const" => {
let pipeline = parse_const(working_set, &spans[1..]);
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
let export_const_decl_id = if let Some(id) = working_set.find_decl(b"export const")
{
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
id
} else {
working_set.error(ParseError::InternalError(
"missing 'export const' command".into(),
export_span,
));
return (garbage_pipeline(spans), vec![]);
};
// Trying to warp the 'const' call into the 'export const' in a very clumsy way
if let Some(PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(ref def_call),
..
},
Apply nightly clippy fixes (#11083) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Clippy fixes for rust 1.76.0-nightly # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> N/A # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-11-17 15:15:55 +00:00
)) = pipeline.elements.first()
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
{
call = def_call.clone();
call.head = span(&spans[0..=1]);
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
call.decl_id = export_const_decl_id;
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
} else {
working_set.error(ParseError::InternalError(
"unexpected output from parsing a definition".into(),
span(&spans[1..]),
));
};
let mut result = vec![];
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
if let Some(var_name_span) = spans.get(2) {
let var_name = working_set.get_span_contents(*var_name_span);
let var_name = trim_quotes(var_name);
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
if let Some(var_id) = working_set.find_variable(var_name) {
if let Err(err) = working_set.get_constant(var_id) {
working_set.error(err);
} else {
result.push(Exportable::VarDecl {
name: var_name.to_vec(),
id: var_id,
});
}
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
} else {
working_set.error(ParseError::InternalError(
"failed to find added variable".into(),
span(&spans[1..]),
));
}
}
result
}
_ => {
working_set.error(ParseError::Expected(
"def, alias, use, module, const or extern keyword",
spans[1],
));
vec![]
2021-09-28 18:03:53 +00:00
}
2021-09-28 17:29:38 +00:00
}
} else {
working_set.error(ParseError::MissingPositional(
"def, alias, use, module, const or extern keyword".to_string(),
Span::new(export_span.end, export_span.end),
"def, alias, use, module, const or extern keyword".to_string(),
));
vec![]
};
(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]),
exportables,
)
2021-09-28 17:29:38 +00:00
}
pub fn parse_export_env(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Pipeline, Option<BlockId>) {
if !spans.is_empty() && working_set.get_span_contents(spans[0]) != b"export-env" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'export-env' command".into(),
span(spans),
));
return (garbage_pipeline(spans), None);
}
if spans.len() < 2 {
working_set.error(ParseError::MissingPositional(
"block".into(),
span(spans),
"export-env <block>".into(),
));
return (garbage_pipeline(spans), None);
}
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let call = match working_set.find_decl(b"export-env") {
Some(decl_id) => {
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &[spans[1]], decl_id);
let decl = working_set.get_decl(decl_id);
let call_span = span(spans);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return (garbage_pipeline(spans), None);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]),
None,
);
}
call
}
None => {
working_set.error(ParseError::UnknownState(
"internal error: 'export-env' declaration not found".into(),
span(spans),
));
return (garbage_pipeline(spans), None);
}
};
let block_id = if let Some(block) = call.positional_nth(0) {
if let Some(block_id) = block.as_block() {
block_id
} else {
working_set.error(ParseError::UnknownState(
"internal error: 'export-env' block is not a block".into(),
block.span,
));
return (garbage_pipeline(spans), None);
}
} else {
working_set.error(ParseError::UnknownState(
"internal error: 'export-env' block is missing".into(),
span(spans),
));
return (garbage_pipeline(spans), None);
};
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]);
(pipeline, Some(block_id))
}
2022-12-30 15:44:37 +00:00
fn collect_first_comments(tokens: &[Token]) -> Vec<Span> {
let mut comments = vec![];
let mut tokens_iter = tokens.iter().peekable();
while let Some(token) = tokens_iter.next() {
match token.contents {
TokenContents::Comment => {
comments.push(token.span);
}
TokenContents::Eol => {
if let Some(Token {
contents: TokenContents::Eol,
..
}) = tokens_iter.peek()
{
if !comments.is_empty() {
break;
}
}
}
_ => {
comments.clear();
break;
}
}
}
comments
}
pub fn parse_module_block(
working_set: &mut StateWorkingSet,
span: Span,
module_name: &[u8],
) -> (Block, Module, Vec<Span>) {
working_set.enter_scope();
let source = working_set.get_span_contents(span);
let (output, err) = lex(source, span.start, &[], &[], false);
if let Some(err) = err {
working_set.error(err)
}
2022-12-30 15:44:37 +00:00
let module_comments = collect_first_comments(&output);
let (output, err) = lite_parse(&output);
if let Some(err) = err {
working_set.error(err)
}
for pipeline in &output.block {
if pipeline.commands.len() == 1 {
if let LiteElement::Command(_, command) = &pipeline.commands[0] {
parse_def_predecl(working_set, &command.parts);
}
}
}
let mut module = Module::from_span(module_name.to_vec(), span);
let mut block = Block::new_with_capacity(output.block.len());
for pipeline in output.block.iter() {
if pipeline.commands.len() == 1 {
match &pipeline.commands[0] {
LiteElement::Command(_, command) => {
let name = working_set.get_span_contents(command.parts[0]);
match name {
b"def" => {
block.pipelines.push(
parse_def(
working_set,
command,
None, // using commands named as the module locally is OK
)
.0,
)
}
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
b"const" => block
.pipelines
.push(parse_const(working_set, &command.parts)),
b"extern" => block
.pipelines
.push(parse_extern(working_set, command, None)),
b"alias" => {
block.pipelines.push(parse_alias(
working_set,
command,
None, // using aliases named as the module locally is OK
))
}
b"use" => {
let (pipeline, _) = parse_use(working_set, &command.parts);
block.pipelines.push(pipeline)
}
b"module" => {
2023-05-06 20:55:10 +00:00
let (pipeline, _) = parse_module(
working_set,
command,
None, // using modules named as the module locally is OK
);
block.pipelines.push(pipeline)
}
b"export" => {
let (pipe, exportables) =
parse_export_in_module(working_set, command, module_name);
for exportable in exportables {
match exportable {
Exportable::Decl { name, id } => {
if &name == b"main" {
if module.main.is_some() {
let err_span = if !pipe.elements.is_empty() {
if let PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(call),
..
},
) = &pipe.elements[0]
{
call.head
} else {
pipe.elements[0].span()
}
} else {
span
};
working_set.error(ParseError::ModuleDoubleMain(
String::from_utf8_lossy(module_name)
.to_string(),
err_span,
));
} else {
module.main = Some(id);
}
} else {
module.add_decl(name, id);
}
}
Exportable::Module { name, id } => {
if &name == b"mod" {
let (
submodule_main,
submodule_decls,
submodule_submodules,
) = {
let submodule = working_set.get_module(id);
(
submodule.main,
submodule.decls(),
submodule.submodules(),
)
};
// Add submodule's decls to the parent module
for (decl_name, decl_id) in submodule_decls {
module.add_decl(decl_name, decl_id);
}
// Add submodule's main command to the parent module
if let Some(main_decl_id) = submodule_main {
if module.main.is_some() {
let err_span = if !pipe.elements.is_empty() {
if let PipelineElement::Expression(
_,
Expression {
expr: Expr::Call(call),
..
},
) = &pipe.elements[0]
{
call.head
} else {
pipe.elements[0].span()
}
} else {
span
};
working_set.error(
ParseError::ModuleDoubleMain(
String::from_utf8_lossy(module_name)
.to_string(),
err_span,
),
);
} else {
module.main = Some(main_decl_id);
}
}
// Add submodule's submodules to the parent module
for (submodule_name, submodule_id) in
submodule_submodules
{
module.add_submodule(submodule_name, submodule_id);
}
} else {
module.add_submodule(name, id);
}
}
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
Exportable::VarDecl { name, id } => {
module.add_variable(name, id);
}
}
}
block.pipelines.push(pipe)
}
b"export-env" => {
let (pipe, maybe_env_block) =
parse_export_env(working_set, &command.parts);
if let Some(block_id) = maybe_env_block {
module.add_env_block(block_id);
}
block.pipelines.push(pipe)
}
_ => {
working_set.error(ParseError::ExpectedKeyword(
"def, const, extern, alias, use, module, export or export-env keyword".into(),
command.parts[0],
));
block.pipelines.push(garbage_pipeline(&command.parts))
}
}
}
LiteElement::Redirection(_, _, command, _) => {
block.pipelines.push(garbage_pipeline(&command.parts))
}
LiteElement::SeparateRedirection {
out: (_, command, _),
..
} => block.pipelines.push(garbage_pipeline(&command.parts)),
Avoid blocking when `o+e>` redirects too much stderr message (#8784) # Description Fixes: #8565 Here is another pr #7240 tried to address the issue, but it works in a wrong way. After this change `o+e>` won't redirect all stdout message then stderr message and it works more like how bash does. # User-Facing Changes For the given python code: ```python # test.py import sys print('aa'*300, flush=True) print('bb'*999999, file=sys.stderr, flush=True) print('cc'*300, flush=True) ``` Running `python test.py out+err> a.txt` shoudn't hang nushell, and `a.txt` keeps output in the same order ## About the change The core idea is that when doing lite-parsing, introduce a new variant `LiteElement::SameTargetRedirection` if we meet `out+err>` redirection token(which is generated by lex function), During converting from lite block to block, LiteElement::SameTargetRedirection will be converted to PipelineElement::SameTargetRedirection. Then in the block eval process, if we get PipelineElement::SameTargetRedirection, we'll invoke `run-external` with `--redirect-combine` flag, then pipe the result into save command ## What happened internally? Take the following command as example: `^ls o+e> log.txt` lex parsing result(`Tokens`) are not changed, but `LiteBlock` and `Block` is changed after this pr. ### LiteBlock before ```rust LiteBlock { block: [ LitePipeline { commands: [ Command(None, LiteCommand { comments: [], parts: [Span { start: 39041, end: 39044 }] }), // actually the span of first Redirection is wrong too.. Redirection(Span { start: 39058, end: 39062 }, StdoutAndStderr, LiteCommand { comments: [], parts: [Span { start: 39050, end: 39057 }] }), ] }] } ``` ### LiteBlock after ```rust LiteBlock { block: [ LitePipeline { commands: [ SameTargetRedirection { cmd: (None, LiteCommand { comments: [], parts: [Span { start: 147945, end: 147948}]}), redirection: (Span { start: 147949, end: 147957 }, LiteCommand { comments: [], parts: [Span { start: 147958, end: 147965 }]}) } ] } ] } ``` ### Block before ```rust Pipeline { elements: [ Expression(None, Expression { expr: ExternalCall(Expression { expr: String("ls"), span: Span { start: 39042, end: 39044 }, ty: String, custom_completion: None }, [], false), span: Span { start: 39041, end: 39044 }, ty: Any, custom_completion: None }), Redirection(Span { start: 39058, end: 39062 }, StdoutAndStderr, Expression { expr: String("out.txt"), span: Span { start: 39050, end: 39057 }, ty: String, custom_completion: None })] } ``` ### Block after ```rust Pipeline { elements: [ SameTargetRedirection { cmd: (None, Expression { expr: ExternalCall(Expression { expr: String("ls"), span: Span { start: 147946, end: 147948 }, ty: String, custom_completion: None}, [], false), span: Span { start: 147945, end: 147948}, ty: Any, custom_completion: None }), redirection: (Span { start: 147949, end: 147957}, Expression {expr: String("log.txt"), span: Span { start: 147958, end: 147965 },ty: String,custom_completion: None} } ] } ``` # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-utils/standard_library/tests.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-05-17 22:47:03 +00:00
LiteElement::SameTargetRedirection {
cmd: (_, command), ..
} => block.pipelines.push(garbage_pipeline(&command.parts)),
}
} else {
working_set.error(ParseError::Expected("not a pipeline", span));
block.pipelines.push(garbage_pipeline(&[span]))
}
}
working_set.exit_scope();
(block, module, module_comments)
}
fn parse_module_file(
working_set: &mut StateWorkingSet,
path: ParserPath,
path_span: Span,
name_override: Option<String>,
) -> Option<ModuleId> {
if let Some(i) = working_set
.parsed_module_files
.iter()
.rposition(|p| p == path.path())
{
let mut files: Vec<String> = working_set
.parsed_module_files
.split_off(i)
.iter()
.map(|p| p.to_string_lossy().to_string())
.collect();
files.push(path.path().to_string_lossy().to_string());
let msg = files.join("\nuses ");
working_set.error(ParseError::CyclicalModuleImport(msg, path_span));
return None;
}
let module_name = if let Some(name) = name_override {
name
} else if let Some(stem) = path.file_stem() {
stem.to_string_lossy().to_string()
} else {
working_set.error(ParseError::ModuleNotFound(path_span));
return None;
};
let contents = if let Some(contents) = path.read(working_set) {
contents
} else {
working_set.error(ParseError::ModuleNotFound(path_span));
return None;
};
let file_id = working_set.add_file(path.path().to_string_lossy().to_string(), &contents);
let new_span = working_set.get_span_for_file(file_id);
2023-05-07 11:41:40 +00:00
if let Some(module_id) = working_set.find_module_by_span(new_span) {
return Some(module_id);
}
// Change the currently parsed directory
let prev_currently_parsed_cwd = if let Some(parent) = path.parent() {
working_set.currently_parsed_cwd.replace(parent.into())
} else {
working_set.currently_parsed_cwd.clone()
};
// Add the file to the stack of parsed module files
working_set.parsed_module_files.push(path.path_buf());
// Parse the module
let (block, module, module_comments) =
parse_module_block(working_set, new_span, module_name.as_bytes());
// Remove the file from the stack of parsed module files
working_set.parsed_module_files.pop();
// Restore the currently parsed directory back
working_set.currently_parsed_cwd = prev_currently_parsed_cwd;
let _ = working_set.add_block(block);
let module_id = working_set.add_module(&module_name, module, module_comments);
Some(module_id)
}
pub fn parse_module_file_or_dir(
working_set: &mut StateWorkingSet,
path: &[u8],
path_span: Span,
name_override: Option<String>,
) -> Option<ModuleId> {
let (module_path_str, err) = unescape_unquote_string(path, path_span);
if let Some(err) = err {
working_set.error(err);
return None;
}
let cwd = working_set.get_cwd();
let module_path =
if let Some(path) = find_in_dirs(&module_path_str, working_set, &cwd, LIB_DIRS_VAR) {
path
} else {
working_set.error(ParseError::ModuleNotFound(path_span));
return None;
};
if module_path.is_dir() {
disable directory submodule auto export (#11157) should - close https://github.com/nushell/nushell/issues/11133 # Description to allow more freedom when writing complex modules, we are disabling the auto-export of director modules. the change was as simple as removing the crawling of files and modules next to any `mod.nu` and update the standard library. # User-Facing Changes users will have to explicitely use `export module <mod>` to define submodules and `export use <mod> <cmd>` to re-export definitions, e.g. ```nushell # my-module/mod.nu export module foo.nu # export a submodule export use bar.nu bar-1 # re-export an internal command export def top [] { print "`top` from `mod.nu`" } ``` ```nushell # my-module/foo.nu export def "foo-1" [] { print "`foo-1` from `lib/foo.nu`" } export def "foo-2" [] { print "`foo-2` from `lib/foo.nu`" } ``` ```nushell # my-module/bar.nu export def "bar-1" [] { print "`bar-1` from `lib/bar.nu`" } ``` # Tests + Formatting i had to add `export module` calls in the `tests/modules/samples/spam` directory module and allow the `not_allowed` module to not give an error, it is just empty, which is fine. # After Submitting - mention in the release note - update the following repos ``` #┬─────name─────┬version┬─type─┬─────────repo───────── 0│nu-git-manager│0.4.0 │module│amtoine/nu-git-manager 1│nu-scripts │0.1.0 │module│amtoine/scripts 2│nu-zellij │0.1.0 │module│amtoine/zellij-layouts 3│nu-scripts │0.1.0 │module│nushell/nu_scripts 4│nupm │0.1.0 │module│nushell/nupm ─┴──────────────┴───────┴──────┴────────────────────── ```
2023-12-15 11:37:55 +00:00
if module_path.read_dir().is_none() {
working_set.error(ParseError::ModuleNotFound(path_span));
return None;
};
let module_name = if let Some(stem) = module_path.file_stem() {
stem.to_string_lossy().to_string()
} else {
working_set.error(ParseError::ModuleNotFound(path_span));
return None;
};
let mod_nu_path = module_path.clone().join("mod.nu");
if !(mod_nu_path.exists() && mod_nu_path.is_file()) {
working_set.error(ParseError::ModuleMissingModNuFile(
module_path.path().to_string_lossy().to_string(),
path_span,
));
return None;
}
if let Some(module_id) = parse_module_file(
working_set,
mod_nu_path,
path_span,
name_override.or(Some(module_name)),
) {
disable directory submodule auto export (#11157) should - close https://github.com/nushell/nushell/issues/11133 # Description to allow more freedom when writing complex modules, we are disabling the auto-export of director modules. the change was as simple as removing the crawling of files and modules next to any `mod.nu` and update the standard library. # User-Facing Changes users will have to explicitely use `export module <mod>` to define submodules and `export use <mod> <cmd>` to re-export definitions, e.g. ```nushell # my-module/mod.nu export module foo.nu # export a submodule export use bar.nu bar-1 # re-export an internal command export def top [] { print "`top` from `mod.nu`" } ``` ```nushell # my-module/foo.nu export def "foo-1" [] { print "`foo-1` from `lib/foo.nu`" } export def "foo-2" [] { print "`foo-2` from `lib/foo.nu`" } ``` ```nushell # my-module/bar.nu export def "bar-1" [] { print "`bar-1` from `lib/bar.nu`" } ``` # Tests + Formatting i had to add `export module` calls in the `tests/modules/samples/spam` directory module and allow the `not_allowed` module to not give an error, it is just empty, which is fine. # After Submitting - mention in the release note - update the following repos ``` #┬─────name─────┬version┬─type─┬─────────repo───────── 0│nu-git-manager│0.4.0 │module│amtoine/nu-git-manager 1│nu-scripts │0.1.0 │module│amtoine/scripts 2│nu-zellij │0.1.0 │module│amtoine/zellij-layouts 3│nu-scripts │0.1.0 │module│nushell/nu_scripts 4│nupm │0.1.0 │module│nushell/nupm ─┴──────────────┴───────┴──────┴────────────────────── ```
2023-12-15 11:37:55 +00:00
let module = working_set.get_module(module_id).clone();
2023-05-07 11:41:40 +00:00
let module_name = String::from_utf8_lossy(&module.name).to_string();
2023-05-07 11:41:40 +00:00
let module_comments = if let Some(comments) = working_set.get_module_comments(module_id)
{
comments.to_vec()
} else {
vec![]
};
let new_module_id = working_set.add_module(&module_name, module, module_comments);
Some(new_module_id)
} else {
None
}
} else if module_path.is_file() {
parse_module_file(working_set, module_path, path_span, name_override)
} else {
working_set.error(ParseError::ModuleNotFound(path_span));
None
}
}
pub fn parse_module(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
module_name: Option<&[u8]>,
2023-05-06 20:55:10 +00:00
) -> (Pipeline, Option<ModuleId>) {
2021-09-26 18:39:19 +00:00
// TODO: Currently, module is closing over its parent scope (i.e., defs in the parent scope are
// visible and usable in this module's scope). We want to disable that for files.
2021-09-26 18:39:19 +00:00
2022-12-30 15:44:37 +00:00
let spans = &lite_command.parts;
let mut module_comments = lite_command.comments.clone();
let split_id = if spans.len() > 1 && working_set.get_span_contents(spans[0]) == b"export" {
2
} else {
1
};
2021-09-26 18:39:19 +00:00
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span) = match working_set.find_decl(b"module") {
Some(decl_id) => {
let (command_spans, rest_spans) = spans.split_at(split_id);
2021-09-26 18:39:19 +00:00
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, span(command_spans), rest_spans, decl_id);
let decl = working_set.get_decl(decl_id);
2021-09-26 18:39:19 +00:00
let call_span = span(spans);
2021-09-26 18:39:19 +00:00
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return (garbage_pipeline(spans), None);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
2023-05-06 20:55:10 +00:00
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]),
None,
);
}
(call, call_span)
}
None => {
working_set.error(ParseError::UnknownState(
"internal error: 'module' or 'export module' declaration not found".into(),
span(spans),
));
2023-05-06 20:55:10 +00:00
return (garbage_pipeline(spans), None);
2021-09-26 18:39:19 +00:00
}
};
2021-09-26 18:39:19 +00:00
let (module_name_or_path, module_name_or_path_span, module_name_or_path_expr) =
if let Some(name) = call.positional_nth(0) {
if let Some(s) = name.as_string() {
if let Some(mod_name) = module_name {
if s.as_bytes() == mod_name {
working_set.error(ParseError::NamedAsModule(
"module".to_string(),
s,
"mod".to_string(),
name.span,
));
2023-05-06 20:55:10 +00:00
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
None,
);
}
}
(s, name.span, name.clone())
} else {
working_set.error(ParseError::UnknownState(
"internal error: name not a string".into(),
span(spans),
));
2023-05-06 20:55:10 +00:00
return (garbage_pipeline(spans), None);
}
2021-09-26 18:39:19 +00:00
} else {
working_set.error(ParseError::UnknownState(
"internal error: missing positional".into(),
span(spans),
));
2023-05-06 20:55:10 +00:00
return (garbage_pipeline(spans), None);
};
2021-09-26 18:39:19 +00:00
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]);
2021-09-26 18:39:19 +00:00
if spans.len() == split_id + 1 {
if let Some(module_id) = parse_module_file_or_dir(
working_set,
module_name_or_path.as_bytes(),
module_name_or_path_span,
None,
) {
return (pipeline, Some(module_id));
} else {
working_set.error(ParseError::ModuleNotFound(module_name_or_path_span));
2023-05-06 20:55:10 +00:00
return (pipeline, None);
}
}
2022-12-30 15:44:37 +00:00
if spans.len() < split_id + 2 {
working_set.error(ParseError::UnknownState(
"Expected structure: module <name> or module <name> <block>".into(),
span(spans),
));
2021-09-26 18:39:19 +00:00
2023-05-06 20:55:10 +00:00
return (garbage_pipeline(spans), None);
}
2021-09-26 18:39:19 +00:00
let module_name = module_name_or_path;
2021-09-26 18:39:19 +00:00
let block_span = spans[split_id + 1];
let block_bytes = working_set.get_span_contents(block_span);
let mut start = block_span.start;
let mut end = block_span.end;
if block_bytes.starts_with(b"{") {
start += 1;
2021-09-26 18:39:19 +00:00
} else {
working_set.error(ParseError::Expected("block", block_span));
2023-05-06 20:55:10 +00:00
return (garbage_pipeline(spans), None);
}
if block_bytes.ends_with(b"}") {
end -= 1;
} else {
working_set.error(ParseError::Unclosed("}".into(), Span::new(end, end)));
2021-09-26 18:39:19 +00:00
}
let block_span = Span::new(start, end);
let (block, module, inner_comments) =
parse_module_block(working_set, block_span, module_name.as_bytes());
let block_id = working_set.add_block(block);
module_comments.extend(inner_comments);
2023-05-06 20:55:10 +00:00
let module_id = working_set.add_module(&module_name, module, module_comments);
let block_expr = Expression {
expr: Expr::Block(block_id),
span: block_span,
ty: Type::Block,
custom_completion: None,
};
let module_decl_id = working_set
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
.find_decl(b"module")
.expect("internal error: missing module command");
let call = Box::new(Call {
head: span(&spans[..split_id]),
decl_id: module_decl_id,
arguments: vec![
Argument::Positional(module_name_or_path_expr),
Argument::Positional(block_expr),
],
redirect_stdout: true,
redirect_stderr: false,
parser_info: HashMap::new(),
});
2023-05-06 20:55:10 +00:00
(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]),
Some(module_id),
)
2021-09-26 18:39:19 +00:00
}
pub fn parse_use(working_set: &mut StateWorkingSet, spans: &[Span]) -> (Pipeline, Vec<Exportable>) {
let (name_span, split_id) =
if spans.len() > 1 && working_set.get_span_contents(spans[0]) == b"export" {
(spans[1], 2)
} else {
(spans[0], 1)
};
let use_call = working_set.get_span_contents(name_span).to_vec();
if use_call != b"use" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'use' command".into(),
span(spans),
));
return (garbage_pipeline(spans), vec![]);
}
if working_set.get_span_contents(name_span) != b"use" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'use' command".into(),
span(spans),
));
return (garbage_pipeline(spans), vec![]);
}
2021-09-26 18:39:19 +00:00
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span, args_spans) = match working_set.find_decl(b"use") {
Some(decl_id) => {
let (command_spans, rest_spans) = spans.split_at(split_id);
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, span(command_spans), rest_spans, decl_id);
let decl = working_set.get_decl(decl_id);
let call_span = span(spans);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return (garbage_pipeline(spans), vec![]);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]),
vec![],
);
}
(call, call_span, rest_spans)
}
None => {
working_set.error(ParseError::UnknownState(
"internal error: 'use' declaration not found".into(),
span(spans),
));
return (garbage_pipeline(spans), vec![]);
}
};
2021-09-26 18:39:19 +00:00
let import_pattern_expr = parse_import_pattern(working_set, args_spans);
let import_pattern = if let Expression {
expr: Expr::ImportPattern(import_pattern),
..
} = &import_pattern_expr
{
import_pattern.clone()
} else {
working_set.error(ParseError::UnknownState(
"internal error: Import pattern positional is not import pattern".into(),
import_pattern_expr.span,
));
return (garbage_pipeline(spans), vec![]);
};
2021-09-26 18:39:19 +00:00
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
let (mut import_pattern, module, module_id) = if let Some(module_id) = import_pattern.head.id {
let module = working_set.get_module(module_id).clone();
(
ImportPattern {
head: ImportPatternHead {
name: module.name.clone(),
id: Some(module_id),
span: import_pattern.head.span,
},
members: import_pattern.members,
hidden: HashSet::new(),
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
constants: vec![],
},
module,
module_id,
)
} else if let Some(module_id) = parse_module_file_or_dir(
working_set,
&import_pattern.head.name,
import_pattern.head.span,
None,
) {
let module = working_set.get_module(module_id).clone();
(
ImportPattern {
head: ImportPatternHead {
name: module.name.clone(),
id: Some(module_id),
span: import_pattern.head.span,
},
members: import_pattern.members,
hidden: HashSet::new(),
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
constants: vec![],
},
module,
module_id,
)
} else {
working_set.error(ParseError::ModuleNotFound(import_pattern.head.span));
return (
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]),
vec![],
);
};
2021-09-26 18:39:19 +00:00
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
let (definitions, errors) = module.resolve_import_pattern(
working_set,
module_id,
&import_pattern.members,
None,
name_span,
);
working_set.parse_errors.extend(errors);
2021-09-26 18:39:19 +00:00
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
let mut constants = vec![];
for (name, const_val) in definitions.constants {
let const_var_id =
working_set.add_variable(name.clone(), name_span, const_val.get_type(), false);
working_set.set_variable_const_val(const_var_id, const_val);
constants.push((name, const_var_id));
}
let exportables = definitions
.decls
.iter()
.map(|(name, decl_id)| Exportable::Decl {
name: name.clone(),
id: *decl_id,
})
.chain(
definitions
.modules
.iter()
.map(|(name, module_id)| Exportable::Module {
name: name.clone(),
id: *module_id,
}),
)
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
.chain(
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
constants
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
.iter()
.map(|(name, variable_id)| Exportable::VarDecl {
name: name.clone(),
id: *variable_id,
}),
)
.collect();
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
import_pattern.constants = constants.iter().map(|(_, id)| *id).collect();
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
// Extend the current scope with the module's exportables
working_set.use_decls(definitions.decls);
working_set.use_modules(definitions.modules);
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
working_set.use_variables(constants);
2021-09-26 18:39:19 +00:00
// Create a new Use command call to pass the import pattern as parser info
let import_pattern_expr = Expression {
expr: Expr::ImportPattern(import_pattern),
span: span(args_spans),
ty: Type::Any,
custom_completion: None,
};
2021-09-26 18:39:19 +00:00
let mut call = call;
call.set_parser_info("import_pattern".to_string(), import_pattern_expr);
(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]),
exportables,
)
}
2021-09-26 18:39:19 +00:00
pub fn parse_hide(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
if working_set.get_span_contents(spans[0]) != b"hide" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'hide' command".into(),
span(spans),
));
return garbage_pipeline(spans);
2021-09-26 18:39:19 +00:00
}
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, args_spans) = match working_set.find_decl(b"hide") {
Some(decl_id) => {
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
let decl = working_set.get_decl(decl_id);
let call_span = span(spans);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage_pipeline(spans);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]);
}
(call, &spans[1..])
}
None => {
working_set.error(ParseError::UnknownState(
"internal error: 'hide' declaration not found".into(),
span(spans),
));
return garbage_pipeline(spans);
}
};
let import_pattern_expr = parse_import_pattern(working_set, args_spans);
let import_pattern = if let Expression {
expr: Expr::ImportPattern(import_pattern),
..
} = &import_pattern_expr
{
import_pattern.clone()
} else {
working_set.error(ParseError::UnknownState(
"internal error: Import pattern positional is not import pattern".into(),
import_pattern_expr.span,
));
return garbage_pipeline(spans);
};
let bytes = working_set.get_span_contents(spans[0]);
if bytes == b"hide" && spans.len() >= 2 {
for span in spans[1..].iter() {
parse_string(working_set, *span);
}
// module used only internally, not saved anywhere
let (is_module, module) =
if let Some(module_id) = working_set.find_module(&import_pattern.head.name) {
(true, working_set.get_module(module_id).clone())
} else if import_pattern.members.is_empty() {
// The pattern head can be:
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(id) = working_set.find_decl(&import_pattern.head.name) {
// a custom command,
let mut module = Module::new(b"tmp".to_vec());
module.add_decl(import_pattern.head.name.clone(), id);
(false, module)
} else {
// , or it could be an env var (handled by the engine)
(false, Module::new(b"tmp".to_vec()))
}
2021-10-04 17:08:24 +00:00
} else {
working_set.error(ParseError::ModuleNotFound(spans[1]));
return garbage_pipeline(spans);
};
2021-10-04 17:08:24 +00:00
// This kind of inverts the import pattern matching found in parse_use()
let decls_to_hide = if import_pattern.members.is_empty() {
if is_module {
module.decl_names_with_head(&import_pattern.head.name)
} else {
module.decl_names()
}
2021-10-04 17:08:24 +00:00
} else {
match &import_pattern.members[0] {
ImportPatternMember::Glob { .. } => module.decl_names(),
2021-10-04 17:08:24 +00:00
ImportPatternMember::Name { name, span } => {
let mut decls = vec![];
if name == b"main" {
if module.main.is_some() {
decls.push(import_pattern.head.name.clone());
} else {
working_set.error(ParseError::ExportNotFound(*span));
}
} else if let Some(item) =
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
module.decl_name_with_head(name, &import_pattern.head.name)
{
decls.push(item);
} else {
working_set.error(ParseError::ExportNotFound(*span));
2021-10-04 17:08:24 +00:00
}
decls
2021-10-04 17:08:24 +00:00
}
ImportPatternMember::List { names } => {
let mut decls = vec![];
2021-10-04 17:08:24 +00:00
for (name, span) in names {
if name == b"main" {
if module.main.is_some() {
decls.push(import_pattern.head.name.clone());
} else {
working_set.error(ParseError::ExportNotFound(*span));
break;
}
} else if let Some(item) =
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
module.decl_name_with_head(name, &import_pattern.head.name)
{
decls.push(item);
} else {
working_set.error(ParseError::ExportNotFound(*span));
break;
2021-10-04 17:08:24 +00:00
}
}
decls
2021-10-04 17:08:24 +00:00
}
}
};
let import_pattern = {
let decls: HashSet<Vec<u8>> = decls_to_hide.iter().cloned().collect();
import_pattern.with_hidden(decls)
};
// TODO: `use spam; use spam foo; hide foo` will hide both `foo` and `spam foo` since
// they point to the same DeclId. Do we want to keep it that way?
working_set.hide_decls(&decls_to_hide);
// Create a new Use command call to pass the new import pattern
let import_pattern_expr = Expression {
expr: Expr::ImportPattern(import_pattern),
span: span(args_spans),
ty: Type::Any,
custom_completion: None,
};
let mut call = call;
call.set_parser_info("import_pattern".to_string(), import_pattern_expr);
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}])
} else {
working_set.error(ParseError::UnknownState(
"Expected structure: hide <name>".into(),
span(spans),
));
garbage_pipeline(spans)
}
}
pub fn parse_overlay_new(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
2023-03-10 21:20:31 +00:00
let call_span = call.span();
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
Ok(val) => match val.as_string() {
Ok(s) => (s, expr.span),
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
},
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
}
} else {
working_set.error(ParseError::UnknownState(
"internal error: Missing required positional after call parsing".into(),
call_span,
));
return garbage_pipeline(&[call_span]);
};
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
2023-03-10 21:20:31 +00:00
span: call_span,
ty: Type::Any,
custom_completion: None,
}]);
let module_id = working_set.add_module(
&overlay_name,
Module::new(overlay_name.as_bytes().to_vec()),
vec![],
);
working_set.add_overlay(
overlay_name.as_bytes().to_vec(),
module_id,
vec![],
vec![],
false,
);
pipeline
}
pub fn parse_overlay_use(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
2023-03-10 21:20:31 +00:00
let call_span = call.span();
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
Ok(val) => match val.as_string() {
Ok(s) => (s, expr.span),
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
},
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
} else {
working_set.error(ParseError::UnknownState(
"internal error: Missing required positional after call parsing".into(),
call_span,
));
return garbage_pipeline(&[call_span]);
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
};
let new_name = if let Some(kw_expression) = call.positional_nth(1) {
if let Some(new_name_expression) = kw_expression.as_keyword() {
match eval_constant(working_set, new_name_expression) {
Ok(val) => match val.as_string() {
Ok(s) => Some(Spanned {
item: s,
span: new_name_expression.span,
}),
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
},
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
}
} else {
working_set.error(ParseError::ExpectedKeyword(
"as keyword".to_string(),
kw_expression.span,
));
return garbage_pipeline(&[call_span]);
}
} else {
None
};
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(has_prefix) = has_flag_wrapped(working_set, &call, "prefix") else {
return garbage_pipeline(&[call_span]);
};
let Ok(do_reload) = has_flag_wrapped(working_set, &call, "reload") else {
return garbage_pipeline(&[call_span]);
};
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call.clone()),
2023-03-10 21:20:31 +00:00
span: call_span,
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
ty: Type::Any,
custom_completion: None,
}]);
let (final_overlay_name, origin_module, origin_module_id, is_module_updated) =
if let Some(overlay_frame) = working_set.find_overlay(overlay_name.as_bytes()) {
// Activate existing overlay
// First, check for errors
if has_prefix && !overlay_frame.prefixed {
working_set.error(ParseError::OverlayPrefixMismatch(
overlay_name,
"without".to_string(),
overlay_name_span,
));
return pipeline;
}
if !has_prefix && overlay_frame.prefixed {
working_set.error(ParseError::OverlayPrefixMismatch(
overlay_name,
"with".to_string(),
overlay_name_span,
));
return pipeline;
}
if let Some(new_name) = new_name {
if new_name.item != overlay_name {
working_set.error(ParseError::CantAddOverlayHelp(
format!(
"Cannot add overlay as '{}' because it already exists under the name '{}'",
new_name.item, overlay_name
),
new_name.span,
));
return pipeline;
}
}
let module_id = overlay_frame.origin;
if let Some(new_module_id) = working_set.find_module(overlay_name.as_bytes()) {
if !do_reload && (module_id == new_module_id) {
(
overlay_name,
Module::new(working_set.get_module(module_id).name.clone()),
module_id,
false,
)
} else {
// The origin module of an overlay changed => update it
(
overlay_name,
working_set.get_module(new_module_id).clone(),
new_module_id,
true,
)
}
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
} else {
let module_name = overlay_name.as_bytes().to_vec();
(overlay_name, Module::new(module_name), module_id, true)
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
} else {
// Create a new overlay
if let Some(module_id) =
// the name is a module
working_set.find_module(overlay_name.as_bytes())
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
{
(
new_name.map(|spanned| spanned.item).unwrap_or(overlay_name),
working_set.get_module(module_id).clone(),
module_id,
true,
)
} else if let Some(module_id) = parse_module_file_or_dir(
working_set,
overlay_name.as_bytes(),
overlay_name_span,
new_name.as_ref().map(|spanned| spanned.item.clone()),
) {
// try file or directory
let new_module = working_set.get_module(module_id).clone();
(
new_name
.map(|spanned| spanned.item)
.unwrap_or_else(|| String::from_utf8_lossy(&new_module.name).to_string()),
new_module,
module_id,
true,
)
} else {
working_set.error(ParseError::ModuleOrOverlayNotFound(overlay_name_span));
return pipeline;
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
};
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
let (definitions, errors) = if is_module_updated {
Reorder export-env eval and allow reloading an overlay (#7231) # Description This PR is a response to the issues raised in https://github.com/nushell/nushell/pull/7087. It consists of two changes: * `export-env`, when evaluated in `overlay use`, will see the original environment. Previously, it would see the environment from previous overlay activation. * Added a new `--reload` flag that reloads the overlay. Custom definitions will be kept but the original definitions and environment will be reloaded. This enables a pattern when an overlay is supposed to shadow an existing environment variable, such as `PROMPT_COMMAND`, but `overlay use` would keep loading the value from the first activation. You can easily test it by defining a module ``` module prompt { export-env { let-env PROMPT_COMMAND = (date now | into string) } } ``` Calling `overlay use prompt` for the first time changes the prompt to the current time, however, subsequent calls of `overlay use` won't change the time. That's because overlays, once activated, store their state so they can be hidden and restored at later time. To force-reload the environment, use the new flag: Calling `overlay use --reload prompt` repeatedly now updates the prompt with the current time each time. # User-Facing Changes * When calling `overlay use`, if the module has an `export-env` block, the block will see the environment as it is _before_ the overlay is activated. Previously, it was _after_. * A new `overlay use --reload` flag. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-24 22:45:24 +00:00
if has_prefix {
origin_module.resolve_import_pattern(
working_set,
origin_module_id,
&[],
Some(final_overlay_name.as_bytes()),
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
call.head,
)
Reorder export-env eval and allow reloading an overlay (#7231) # Description This PR is a response to the issues raised in https://github.com/nushell/nushell/pull/7087. It consists of two changes: * `export-env`, when evaluated in `overlay use`, will see the original environment. Previously, it would see the environment from previous overlay activation. * Added a new `--reload` flag that reloads the overlay. Custom definitions will be kept but the original definitions and environment will be reloaded. This enables a pattern when an overlay is supposed to shadow an existing environment variable, such as `PROMPT_COMMAND`, but `overlay use` would keep loading the value from the first activation. You can easily test it by defining a module ``` module prompt { export-env { let-env PROMPT_COMMAND = (date now | into string) } } ``` Calling `overlay use prompt` for the first time changes the prompt to the current time, however, subsequent calls of `overlay use` won't change the time. That's because overlays, once activated, store their state so they can be hidden and restored at later time. To force-reload the environment, use the new flag: Calling `overlay use --reload prompt` repeatedly now updates the prompt with the current time each time. # User-Facing Changes * When calling `overlay use`, if the module has an `export-env` block, the block will see the environment as it is _before_ the overlay is activated. Previously, it was _after_. * A new `overlay use --reload` flag. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-24 22:45:24 +00:00
} else {
origin_module.resolve_import_pattern(
working_set,
origin_module_id,
&[ImportPatternMember::Glob {
span: overlay_name_span,
}],
Some(final_overlay_name.as_bytes()),
Recursively export constants from modules (#10049) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> https://github.com/nushell/nushell/pull/9773 introduced constants to modules and allowed to export them, but only within one level. This PR: * allows recursive exporting of constants from all submodules * fixes submodule imports in a list import pattern * makes sure exported constants are actual constants Should unblock https://github.com/nushell/nushell/pull/9678 ### Example: ```nushell module spam { export module eggs { export module bacon { export const viking = 'eats' } } } use spam print $spam.eggs.bacon.viking # prints 'eats' use spam [eggs] print $eggs.bacon.viking # prints 'eats' use spam eggs bacon viking print $viking # prints 'eats' ``` ### Limitation 1: Considering the above `spam` module, attempting to get `eggs bacon` from `spam` module doesn't work directly: ```nushell use spam [ eggs bacon ] # attempts to load `eggs`, then `bacon` use spam [ "eggs bacon" ] # obviously wrong name for a constant, but doesn't work also for commands ``` Workaround (for example): ```nushell use spam eggs use eggs [ bacon ] print $bacon.viking # prints 'eats' ``` I'm thinking I'll just leave it in, as you can easily work around this. It is also a limitation of the import pattern in general, not just constants. ### Limitation 2: `overlay use` successfully imports the constants, but `overlay hide` does not hide them, even though it seems to hide normal variables successfully. This needs more investigation. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Allows recursive constant exports from submodules. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-08-20 12:51:35 +00:00
call.head,
)
Reorder export-env eval and allow reloading an overlay (#7231) # Description This PR is a response to the issues raised in https://github.com/nushell/nushell/pull/7087. It consists of two changes: * `export-env`, when evaluated in `overlay use`, will see the original environment. Previously, it would see the environment from previous overlay activation. * Added a new `--reload` flag that reloads the overlay. Custom definitions will be kept but the original definitions and environment will be reloaded. This enables a pattern when an overlay is supposed to shadow an existing environment variable, such as `PROMPT_COMMAND`, but `overlay use` would keep loading the value from the first activation. You can easily test it by defining a module ``` module prompt { export-env { let-env PROMPT_COMMAND = (date now | into string) } } ``` Calling `overlay use prompt` for the first time changes the prompt to the current time, however, subsequent calls of `overlay use` won't change the time. That's because overlays, once activated, store their state so they can be hidden and restored at later time. To force-reload the environment, use the new flag: Calling `overlay use --reload prompt` repeatedly now updates the prompt with the current time each time. # User-Facing Changes * When calling `overlay use`, if the module has an `export-env` block, the block will see the environment as it is _before_ the overlay is activated. Previously, it was _after_. * A new `overlay use --reload` flag. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2022-11-24 22:45:24 +00:00
}
} else {
Module: support defining const and use const variables inside of function (#9773) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> Relative: #8248 After this pr, user can define const variable inside a module. ![image](https://github.com/nushell/nushell/assets/22256154/e3e03e56-c4b5-4144-a944-d1b20bec1cbd) And user can export const variables, the following screenshot shows how it works (it follows https://github.com/nushell/nushell/issues/8248#issuecomment-1637442612): ![image](https://github.com/nushell/nushell/assets/22256154/b2c14760-3f27-41cc-af77-af70a4367f2a) ## About the change 1. To make module support const, we need to change `parse_module_block` to support `const` keyword. 2. To suport export `const`, we need to make module tracking variables, so we add `variables` attribute to `Module` 3. During eval, the const variable may not exists in `stack`, because we don't eval `const` when we define a module, so we need to find variables which are already registered in `engine_state` ## One more thing to note about the const value. Consider the following code ``` module foo { const b = 3; export def bar [] { $b } } use foo bar const b = 4; bar ``` The result will be 3 (which is defined in module) rather than 4. I think it's expected behavior. It's something like [dynamic binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Dynamic-Binding-Tips.html) vs [lexical binding](https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html) in lisp like language, and lexical binding should be right behavior which generates more predicable result, and it doesn't introduce really subtle bugs in nushell code. What if user want dynamic-binding?(For example: the example code returns `4`) There is no way to do this, user should consider passing the value as argument to custom command rather than const. ## TODO - [X] adding tests for the feature. - [X] support export const out of module to use. # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-31 23:09:52 +00:00
(ResolvedImportPattern::new(vec![], vec![], vec![]), vec![])
};
if errors.is_empty() {
working_set.add_overlay(
final_overlay_name.as_bytes().to_vec(),
origin_module_id,
definitions.decls,
definitions.modules,
has_prefix,
);
} else {
working_set.parse_errors.extend(errors);
}
// Change the call argument to include the Overlay expression with the module ID
let mut call = call;
call.set_parser_info(
"overlay_expr".to_string(),
Expression {
expr: Expr::Overlay(if is_module_updated {
Some(origin_module_id)
} else {
None
}),
span: overlay_name_span,
ty: Type::Any,
custom_completion: None,
},
);
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
2023-03-10 21:20:31 +00:00
span: call_span,
ty: Type::Any,
custom_completion: None,
}])
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
pub fn parse_overlay_hide(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
2023-03-10 21:20:31 +00:00
let call_span = call.span();
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
Ok(val) => match val.as_string() {
Ok(s) => (s, expr.span),
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
},
Err(err) => {
working_set.error(err.wrap(working_set, call_span));
return garbage_pipeline(&[call_span]);
}
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
} else {
(
String::from_utf8_lossy(working_set.last_overlay_name()).to_string(),
2023-03-10 21:20:31 +00:00
call_span,
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
)
};
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(keep_custom) = has_flag_wrapped(working_set, &call, "keep-custom") else {
return garbage_pipeline(&[call_span]);
};
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
let pipeline = Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
2023-03-10 21:20:31 +00:00
span: call_span,
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
ty: Type::Any,
custom_completion: None,
}]);
if overlay_name == DEFAULT_OVERLAY_NAME {
working_set.error(ParseError::CantHideDefaultOverlay(
overlay_name,
overlay_name_span,
));
return pipeline;
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
if !working_set
.unique_overlay_names()
.contains(&overlay_name.as_bytes())
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
{
working_set.error(ParseError::ActiveOverlayNotFound(overlay_name_span));
return pipeline;
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
if working_set.num_overlays() < 2 {
working_set.error(ParseError::CantRemoveLastOverlay(overlay_name_span));
return pipeline;
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
working_set.remove_overlay(overlay_name.as_bytes(), keep_custom);
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
pipeline
Overlays (#5375) * WIP: Start laying overlays * Rename Overlay->Module; Start adding overlay * Revamp adding overlay * Add overlay add tests; Disable debug print * Fix overlay add; Add overlay remove * Add overlay remove tests * Add missing overlay remove file * Add overlay list command * (WIP?) Enable overlays for env vars * Move OverlayFrames to ScopeFrames * (WIP) Move everything to overlays only ScopeFrame contains nothing but overlays now * Fix predecls * Fix wrong overlay id translation and aliases * Fix broken env lookup logic * Remove TODOs * Add overlay add + remove for environment * Add a few overlay tests; Fix overlay add name * Some cleanup; Fix overlay add/remove names * Clippy * Fmt * Remove walls of comments * List overlays from stack; Add debugging flag Currently, the engine state ordering is somehow broken. * Fix (?) overlay list test * Fix tests on Windows * Fix activated overlay ordering * Check for active overlays equality in overlay list This removes the -p flag: Either both parser and engine will have the same overlays, or the command will fail. * Add merging on overlay remove * Change help message and comment * Add some remove-merge/discard tests * (WIP) Track removed overlays properly * Clippy; Fmt * Fix getting last overlay; Fix predecls in overlays * Remove merging; Fix re-add overwriting stuff Also some error message tweaks. * Fix overlay error in the engine * Update variable_completions.rs * Adds flags and optional arguments to view-source (#5446) * added flags and optional arguments to view-source * removed redundant code * removed redundant code * fmt * fix bug in shell_integration (#5450) * fix bug in shell_integration * add some comments * enable cd to work with directory abbreviations (#5452) * enable cd to work with abbreviations * add abbreviation example * fix tests * make it configurable * make cd recornize symblic link (#5454) * implement seq char command to generate single character sequence (#5453) * add tmp code * add seq char command * Add split number flag in `split row` (#5434) Signed-off-by: Yuheng Su <gipsyh.icu@gmail.com> * Add two more overlay tests * Add ModuleId to OverlayFrame * Fix env conversion accidentally activating overlay It activated overlay from permanent state prematurely which would cause `overlay add` to misbehave. * Remove unused parameter; Add overlay list test * Remove added traces * Add overlay commands examples * Modify TODO * Fix $nu.scope iteration * Disallow removing default overlay * Refactor some parser errors * Remove last overlay if no argument * Diversify overlay examples * Make it possible to update overlay's module In case the origin module updates, the overlay add loads the new module, makes it overlay's origin and applies the changes. Before, it was impossible to update the overlay if the module changed. Co-authored-by: JT <547158+jntrnr@users.noreply.github.com> Co-authored-by: pwygab <88221256+merelymyself@users.noreply.github.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <WindSoilder@outlook.com> Co-authored-by: Yuheng Su <gipsyh.icu@gmail.com>
2022-05-07 19:39:22 +00:00
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
pub fn parse_let(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
trace!("parsing: let");
2021-09-26 18:39:19 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
// JT: Disabling check_name because it doesn't work with optional types in the declaration
// if let Some(span) = check_name(working_set, spans) {
// return Pipeline::from_vec(vec![garbage(*span)]);
// }
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(b"let") {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
if spans.len() >= 4 {
// This is a bit of by-hand parsing to get around the issue where we want to parse in the reverse order
// so that the var-id created by the variable isn't visible in the expression that init it
for span in spans.iter().enumerate() {
let item = working_set.get_span_contents(*span.1);
// https://github.com/nushell/nushell/issues/9596, let = if $
// let x = 'f', = at least start from index 2
if item == b"=" && spans.len() > (span.0 + 1) && span.0 > 1 {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let (tokens, parse_error) = lex(
working_set.get_span_contents(nu_protocol::span(&spans[(span.0 + 1)..])),
spans[span.0 + 1].start,
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
&[],
&[],
true,
);
2021-09-26 18:39:19 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
if let Some(parse_error) = parse_error {
working_set.parse_errors.push(parse_error)
}
2022-01-03 23:14:33 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let rvalue_span = nu_protocol::span(&spans[(span.0 + 1)..]);
let rvalue_block = parse_block(working_set, &tokens, rvalue_span, false, true);
2021-09-26 18:39:19 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let output_type = rvalue_block.output_type();
2021-12-27 03:04:22 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let block_id = working_set.add_block(rvalue_block);
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let rvalue = Expression {
expr: Expr::Block(block_id),
span: rvalue_span,
ty: output_type,
custom_completion: None,
};
let mut idx = 0;
let (lvalue, explicit_type) =
parse_var_with_opt_type(working_set, &spans[1..(span.0)], &mut idx, false);
let var_name =
String::from_utf8_lossy(working_set.get_span_contents(lvalue.span))
.trim_start_matches('$')
.to_string();
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let var_id = lvalue.as_var();
let rhs_type = rvalue.ty.clone();
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
if let Some(explicit_type) = &explicit_type {
if !type_compatible(explicit_type, &rhs_type) {
working_set.error(ParseError::TypeMismatch(
explicit_type.clone(),
rhs_type.clone(),
nu_protocol::span(&spans[(span.0 + 1)..]),
));
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
if let Some(var_id) = var_id {
if explicit_type.is_none() {
working_set.set_variable_type(var_id, rhs_type);
}
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
redirect_stdout: true,
redirect_stderr: false,
parser_info: HashMap::new(),
});
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Any,
custom_completion: None,
}]);
}
}
}
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: output,
custom_completion: None,
}]);
} else {
working_set.error(ParseError::UnknownState(
"internal error: let or const statements not found in core language".into(),
span(spans),
))
}
working_set.error(ParseError::UnknownState(
"internal error: let or const statement unparsable".into(),
span(spans),
));
garbage_pipeline(spans)
}
pub fn parse_const(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
trace!("parsing: const");
// JT: Disabling check_name because it doesn't work with optional types in the declaration
// if let Some(span) = check_name(working_set, spans) {
// return Pipeline::from_vec(vec![garbage(*span)]);
// }
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(b"const") {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let cmd = working_set.get_decl(decl_id);
let call_signature = cmd.signature().call_signature();
if spans.len() >= 4 {
// This is a bit of by-hand parsing to get around the issue where we want to parse in the reverse order
// so that the var-id created by the variable isn't visible in the expression that init it
for span in spans.iter().enumerate() {
let item = working_set.get_span_contents(*span.1);
// const x = 'f', = at least start from index 2
if item == b"=" && spans.len() > (span.0 + 1) && span.0 > 1 {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let mut idx = span.0;
let rvalue = parse_multispan_value(
working_set,
spans,
&mut idx,
&SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::MathExpression)),
);
if idx < (spans.len() - 1) {
working_set
.error(ParseError::ExtraPositional(call_signature, spans[idx + 1]));
}
let mut idx = 0;
let (lvalue, explicit_type) =
parse_var_with_opt_type(working_set, &spans[1..(span.0)], &mut idx, false);
let var_name =
String::from_utf8_lossy(working_set.get_span_contents(lvalue.span))
.trim_start_matches('$')
.to_string();
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
}
let var_id = lvalue.as_var();
let rhs_type = rvalue.ty.clone();
if let Some(explicit_type) = &explicit_type {
if !type_compatible(explicit_type, &rhs_type) {
working_set.error(ParseError::TypeMismatch(
explicit_type.clone(),
rhs_type.clone(),
nu_protocol::span(&spans[(span.0 + 1)..]),
));
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
}
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
if let Some(var_id) = var_id {
if explicit_type.is_none() {
working_set.set_variable_type(var_id, rhs_type);
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
match eval_constant(working_set, &rvalue) {
Ok(val) => {
2023-07-13 21:02:05 +00:00
// In case rhs is parsed as 'any' but is evaluated to a concrete
// type:
let const_type = val.get_type();
if let Some(explicit_type) = &explicit_type {
if !type_compatible(explicit_type, &const_type) {
working_set.error(ParseError::TypeMismatch(
explicit_type.clone(),
const_type.clone(),
nu_protocol::span(&spans[(span.0 + 1)..]),
));
}
}
working_set.set_variable_type(var_id, const_type);
// Assign the constant value to the variable
working_set.set_variable_const_val(var_id, val);
}
Err(err) => working_set.error(err.wrap(working_set, rvalue.span)),
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
}
2021-09-26 18:39:19 +00:00
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
redirect_stdout: true,
redirect_stderr: false,
parser_info: HashMap::new(),
});
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Any,
custom_completion: None,
}]);
}
2021-09-26 18:39:19 +00:00
}
}
Let with pipeline (#9589) # Description This changes the default behaviour of `let` to be able to take a pipeline as its initial value. For example: ``` > let x = "hello world" | str length ``` This is a change from the existing behaviour, where the right hand side is assumed to be an expression. Pipelines are more general, and can be more powerful. My google foo is failing me, but this also fixes this issue: ``` let x = foo ``` Currently, this reads `foo` as a bareword that gets converted to a string rather than running the `foo` command. In practice, this is really annoying and is a really hard to spot bug in a script. # User-Facing Changes BREAKING CHANGE BREAKING CHANGE `let` gains the power to be assigned via a pipeline. However, this changes the behaviour of `let x = foo` from assigning the string "foo" to `$x` to being "run the command `foo` and give the result to `$x`" # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-03 05:45:10 +00:00
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: output,
custom_completion: None,
}]);
} else {
working_set.error(ParseError::UnknownState(
"internal error: let or const statements not found in core language".into(),
span(spans),
))
2021-09-26 18:39:19 +00:00
}
working_set.error(ParseError::UnknownState(
"internal error: let or const statement unparsable".into(),
span(spans),
));
garbage_pipeline(spans)
2021-09-26 18:39:19 +00:00
}
2021-10-02 02:24:43 +00:00
pub fn parse_mut(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
trace!("parsing: mut");
// JT: Disabling check_name because it doesn't work with optional types in the declaration
// if let Some(span) = check_name(working_set, spans) {
// return Pipeline::from_vec(vec![garbage(*span)]);
// }
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(b"mut") {
if spans.len() >= 4 {
// This is a bit of by-hand parsing to get around the issue where we want to parse in the reverse order
// so that the var-id created by the variable isn't visible in the expression that init it
for span in spans.iter().enumerate() {
let item = working_set.get_span_contents(*span.1);
// mut x = 'f', = at least start from index 2
if item == b"=" && spans.len() > (span.0 + 1) && span.0 > 1 {
let (tokens, parse_error) = lex(
working_set.get_span_contents(nu_protocol::span(&spans[(span.0 + 1)..])),
spans[span.0 + 1].start,
&[],
&[],
true,
);
if let Some(parse_error) = parse_error {
working_set.parse_errors.push(parse_error)
}
let rvalue_span = nu_protocol::span(&spans[(span.0 + 1)..]);
let rvalue_block = parse_block(working_set, &tokens, rvalue_span, false, true);
let output_type = rvalue_block.output_type();
let block_id = working_set.add_block(rvalue_block);
let rvalue = Expression {
expr: Expr::Block(block_id),
span: rvalue_span,
ty: output_type,
custom_completion: None,
};
let mut idx = 0;
let (lvalue, explicit_type) =
parse_var_with_opt_type(working_set, &spans[1..(span.0)], &mut idx, true);
let var_name =
String::from_utf8_lossy(working_set.get_span_contents(lvalue.span))
.trim_start_matches('$')
.to_string();
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
}
let var_id = lvalue.as_var();
let rhs_type = rvalue.ty.clone();
if let Some(explicit_type) = &explicit_type {
if !type_compatible(explicit_type, &rhs_type) {
working_set.error(ParseError::TypeMismatch(
explicit_type.clone(),
rhs_type.clone(),
nu_protocol::span(&spans[(span.0 + 1)..]),
));
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
}
}
Improve type hovers (#9515) # Description This PR does a few things to help improve type hovers and, in the process, fixes a few outstanding issues in the type system. Here's a list of the changes: * `for` now will try to infer the type of the iteration variable based on the expression it's given. This fixes things like `for x in [1, 2, 3] { }` where `x` now properly gets the int type. * Removed old input/output type fields from the signature, focuses on the vec of signatures. Updated a bunch of dataframe commands that hadn't moved over. This helps tie things together a bit better * Fixed inference of types from subexpressions to use the last expression in the block * Fixed handling of explicit types in `let` and `mut` calls, so we now respect that as the authoritative type I also tried to add `def` input/output type inference, but unfortunately we only know the predecl types universally, which means we won't have enough information to properly know what the types of the custom commands are. # User-Facing Changes Script typechecking will get tighter in some cases Hovers should be more accurate in some cases that previously resorted to any. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-std/tests/run.nu` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
2023-06-28 17:19:48 +00:00
if let Some(var_id) = var_id {
if explicit_type.is_none() {
working_set.set_variable_type(var_id, rhs_type);
}
}
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
redirect_stdout: true,
redirect_stderr: false,
parser_info: HashMap::new(),
});
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Any,
custom_completion: None,
}]);
}
}
}
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: output,
custom_completion: None,
}]);
} else {
working_set.error(ParseError::UnknownState(
"internal error: let or const statements not found in core language".into(),
span(spans),
))
}
working_set.error(ParseError::UnknownState(
"internal error: let or const statement unparsable".into(),
span(spans),
));
garbage_pipeline(spans)
}
pub fn parse_source(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
2021-10-02 02:24:43 +00:00
let name = working_set.get_span_contents(spans[0]);
if name == b"source" || name == b"source-env" {
let scoped = name == b"source-env";
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
if let Some(decl_id) = working_set.find_decl(name) {
let cwd = working_set.get_cwd();
2021-10-06 02:03:18 +00:00
// Is this the right call to be using here?
// Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't.
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
2021-10-02 02:24:43 +00:00
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage_pipeline(spans);
};
if is_help {
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: output,
custom_completion: None,
}]);
}
2021-10-02 02:24:43 +00:00
// Command and one file name
if spans.len() >= 2 {
let expr = parse_value(working_set, spans[1], &SyntaxShape::Any);
let val = match eval_constant(working_set, &expr) {
Ok(val) => val,
Err(err) => {
working_set.error(err.wrap(working_set, span(&spans[1..])));
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(&spans[1..]),
ty: Type::Any,
custom_completion: None,
}]);
}
};
let filename = match val.as_string() {
Ok(s) => s,
Err(err) => {
working_set.error(err.wrap(working_set, span(&spans[1..])));
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(&spans[1..]),
ty: Type::Any,
custom_completion: None,
}]);
}
};
if let Some(path) = find_in_dirs(&filename, working_set, &cwd, LIB_DIRS_VAR) {
if let Some(contents) = path.read(working_set) {
// Change currently parsed directory
let prev_currently_parsed_cwd = if let Some(parent) = path.parent() {
working_set.currently_parsed_cwd.replace(parent.into())
} else {
working_set.currently_parsed_cwd.clone()
};
// This will load the defs from the file into the
// working set, if it was a successful parse.
let block = parse(
working_set,
Some(&path.path().to_string_lossy()),
&contents,
scoped,
);
// Restore the currently parsed directory back
working_set.currently_parsed_cwd = prev_currently_parsed_cwd;
// Save the block into the working set
let block_id = working_set.add_block(block);
let mut call_with_block = call;
// FIXME: Adding this expression to the positional creates a syntax highlighting error
// after writing `source example.nu`
call_with_block.set_parser_info(
"block_id".to_string(),
Expression {
expr: Expr::Int(block_id as i64),
span: spans[1],
ty: Type::Any,
custom_completion: None,
},
);
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call_with_block),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]);
2021-10-02 02:24:43 +00:00
}
} else {
working_set.error(ParseError::SourcedFileNotFound(filename, spans[1]));
2021-10-02 02:24:43 +00:00
}
}
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}]);
2021-10-02 02:24:43 +00:00
}
}
working_set.error(ParseError::UnknownState(
"internal error: source statement unparsable".into(),
span(spans),
));
garbage_pipeline(spans)
2021-10-02 02:24:43 +00:00
}
2021-10-31 08:17:01 +00:00
pub fn parse_where_expr(working_set: &mut StateWorkingSet, spans: &[Span]) -> Expression {
trace!("parsing: where");
if !spans.is_empty() && working_set.get_span_contents(spans[0]) != b"where" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for 'where' command".into(),
span(spans),
));
return garbage(span(spans));
}
if spans.len() < 2 {
working_set.error(ParseError::MissingPositional(
"row condition".into(),
span(spans),
"where <row_condition>".into(),
));
return garbage(span(spans));
}
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let call = match working_set.find_decl(b"where") {
Some(decl_id) => {
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
let decl = working_set.get_decl(decl_id);
let call_span = span(spans);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage(span(spans));
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
};
}
call
}
None => {
working_set.error(ParseError::UnknownState(
"internal error: 'where' declaration not found".into(),
span(spans),
));
return garbage(span(spans));
}
};
Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
custom_completion: None,
}
}
pub fn parse_where(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
let expression = parse_where_expr(working_set, spans);
Pipeline::from_vec(vec![expression])
}
2021-11-02 20:56:00 +00:00
#[cfg(feature = "plugin")]
pub fn parse_register(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
use nu_plugin::{get_signature, PluginDeclaration};
Make plugin commands support examples. (#7984) # Description As title, we can't provide examples for plugin commands, this pr would make it possible # User-Facing Changes Take plugin `nu-example-1` as example: ``` ❯ nu-example-1 -h PluginSignature test 1 for plugin. Returns Value::Nothing Usage: > nu-example-1 {flags} <a> <b> (opt) ...(rest) Flags: -h, --help - Display the help message for this command -f, --flag - a flag for the signature -n, --named <String> - named string Parameters: a <int>: required integer value b <string>: required string value (optional) opt <int>: Optional number ...rest <string>: rest value string Examples: running example with an int value and string value > nu-example-1 3 bb ``` The examples session is newly added. ## Basic idea behind these changes when nushell query plugin signatures, plugin just returns it's signature without any examples, so nushell have no idea about the examples of plugin commands. To adding the feature, we just making plugin returns it's signature with examples. Before: ``` 1. get signature ----------------> Nushell ------------------ Plugin <----------------- 2. returns Vec<Signature> ``` After: ``` 1. get signature ----------------> Nushell ------------------ Plugin <----------------- 2. returns Vec<PluginSignature> ``` When writing plugin signature to $nu.plugin-path: Serialize `<PluginSignature>` rather than `<Signature>`, which would enable us to serialize examples to `$nu.plugin-path` ## Shortcoming It's a breaking changes because `Plugin::signature` is changed, and it requires plugin authors to change their code for new signatures. Fortunally it should be easy to change, for rust based plugin, we just need to make a global replace from word `Signature` to word `PluginSignature` in their plugin project. Our content of plugin-path is really large, if one plugin have many examples, it'd results to larger body of $nu.plugin-path, which is not really scale. A solution would be save register information in other binary formats rather than `json`. But I think it'd be another story. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-08 22:14:18 +00:00
use nu_protocol::{engine::Stack, PluginSignature};
let cwd = working_set.get_cwd();
// Checking that the function is used with the correct name
// Maybe this is not necessary but it is a sanity check
if working_set.get_span_contents(spans[0]) != b"register" {
working_set.error(ParseError::UnknownState(
"internal error: Wrong call name for parse plugin function".into(),
span(spans),
));
return garbage_pipeline(spans);
2021-10-31 08:17:01 +00:00
}
// Parsing the spans and checking that they match the register signature
// Using a parsed call makes more sense than checking for how many spans are in the call
// Also, by creating a call, it can be checked if it matches the declaration signature
Remove broken compile-time overload system (#9677) # Description This PR removes the compile-time overload system. Unfortunately, this system never worked correctly because in a gradual type system where types can be `Any`, you don't have enough information to correctly resolve function calls with overloads. These resolutions must be done at runtime, if they're supported. That said, there's a bit of work that needs to go into resolving input/output types (here overloads do not execute separate commands, but the same command and each overload explains how each output type corresponds to input types). This PR also removes the type scope, which would give incorrect answers in cases where multiple subexpressions were used in a pipeline. # User-Facing Changes Finishes removing compile-time overloads. These were only used in a few places in the code base, but it's possible it may impact user code. I'll mark this as breaking change so we can review. # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-07-13 19:05:03 +00:00
let (call, call_span) = match working_set.find_decl(b"register") {
None => {
working_set.error(ParseError::UnknownState(
"internal error: Register declaration not found".into(),
span(spans),
));
return garbage_pipeline(spans);
}
Some(decl_id) => {
let ParsedInternalCall { call, output } =
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
let decl = working_set.get_decl(decl_id);
2021-12-18 20:10:40 +00:00
let call_span = span(spans);
let starting_error_count = working_set.parse_errors.len();
check_call(working_set, call_span, &decl.signature(), &call);
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
let Ok(is_help) = has_flag_wrapped(working_set, &call, "help") else {
return garbage_pipeline(spans);
};
if starting_error_count != working_set.parse_errors.len() || is_help {
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: output,
custom_completion: None,
}]);
}
(call, call_span)
}
};
// Extracting the required arguments from the call and keeping them together in a tuple
let arguments = call
.positional_nth(0)
.map(|expr| {
let val =
eval_constant(working_set, expr).map_err(|err| err.wrap(working_set, call.head))?;
let filename = val
.as_string()
.map_err(|err| err.wrap(working_set, call.head))?;
let Some(path) = find_in_dirs(&filename, working_set, &cwd, PLUGIN_DIRS_VAR) else {
Auto format let-else block (#10214) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> rustfmt 1.6.0 has added support for formatting [let-else statements](https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html) See https://github.com/rust-lang/rustfmt/blob/master/CHANGELOG.md#added # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `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 std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
2023-09-04 07:42:31 +00:00
return Err(ParseError::RegisteredFileNotFound(filename, expr.span));
};
if path.exists() && path.is_file() {
Ok((path, expr.span))
} else {
Err(ParseError::RegisteredFileNotFound(filename, expr.span))
}
})
.expect("required positional has being checked");
2021-10-31 08:17:01 +00:00
// Signature is an optional value from the call and will be used to decide if
// the plugin is called to get the signatures or to use the given signature
let signature = call.positional_nth(1).map(|expr| {
let signature = working_set.get_span_contents(expr.span);
Make plugin commands support examples. (#7984) # Description As title, we can't provide examples for plugin commands, this pr would make it possible # User-Facing Changes Take plugin `nu-example-1` as example: ``` ❯ nu-example-1 -h PluginSignature test 1 for plugin. Returns Value::Nothing Usage: > nu-example-1 {flags} <a> <b> (opt) ...(rest) Flags: -h, --help - Display the help message for this command -f, --flag - a flag for the signature -n, --named <String> - named string Parameters: a <int>: required integer value b <string>: required string value (optional) opt <int>: Optional number ...rest <string>: rest value string Examples: running example with an int value and string value > nu-example-1 3 bb ``` The examples session is newly added. ## Basic idea behind these changes when nushell query plugin signatures, plugin just returns it's signature without any examples, so nushell have no idea about the examples of plugin commands. To adding the feature, we just making plugin returns it's signature with examples. Before: ``` 1. get signature ----------------> Nushell ------------------ Plugin <----------------- 2. returns Vec<Signature> ``` After: ``` 1. get signature ----------------> Nushell ------------------ Plugin <----------------- 2. returns Vec<PluginSignature> ``` When writing plugin signature to $nu.plugin-path: Serialize `<PluginSignature>` rather than `<Signature>`, which would enable us to serialize examples to `$nu.plugin-path` ## Shortcoming It's a breaking changes because `Plugin::signature` is changed, and it requires plugin authors to change their code for new signatures. Fortunally it should be easy to change, for rust based plugin, we just need to make a global replace from word `Signature` to word `PluginSignature` in their plugin project. Our content of plugin-path is really large, if one plugin have many examples, it'd results to larger body of $nu.plugin-path, which is not really scale. A solution would be save register information in other binary formats rather than `json`. But I think it'd be another story. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
2023-02-08 22:14:18 +00:00
serde_json::from_slice::<PluginSignature>(signature).map_err(|e| {
ParseError::LabeledError(
"Signature deserialization error".into(),
format!("unable to deserialize signature: {e}"),
spans[0],
)
})
});
2021-10-31 08:17:01 +00:00
// Shell is another optional value used as base to call shell to plugins
let shell = call.get_flag_expr("shell").map(|expr| {
let shell_expr = working_set.get_span_contents(expr.span);
String::from_utf8(shell_expr.to_vec())
.map_err(|_| ParseError::NonUtf8(expr.span))
.and_then(|name| {
canonicalize_with(&name, cwd)
.map_err(|_| ParseError::RegisteredFileNotFound(name, expr.span))
})
.and_then(|path| {
if path.exists() & path.is_file() {
Ok(path)
} else {
Err(ParseError::RegisteredFileNotFound(
format!("{path:?}"),
expr.span,
))
}
})
});
let shell = match shell {
None => None,
Some(path) => match path {
Ok(path) => Some(path),
Err(err) => {
working_set.error(err);
return Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
custom_completion: None,
}]);
}
},
};
// We need the current environment variables for `python` based plugins
// Or we'll likely have a problem when a plugin is implemented in a virtual Python environment.
let stack = Stack::new();
let current_envs =
nu_engine::env::env_to_strings(working_set.permanent_state, &stack).unwrap_or_default();
fix(nu-parser): do not update plugin.nu file on nu startup (#10007) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description I've been investigating the [issue mentioned](https://github.com/nushell/nushell/pull/9976#issuecomment-1673290467) in my prev pr and I've found that plugin.nu file that is used to cache plugins signatures gets overwritten on every nushell startup and that may actually mess up with the file content if 2 or more instances of nushell will run simultaneously. To reproduce: 1. register at least 2 plugins in your local nushell 2. remember how many entries you have in plugin.nu with `open $nu.plugin-path | find nu_plugin` 3. run - either `cargo test` inside nushell repo - or run smth like this `1..100 | par-each {|it| $"(random integer 1..100)ms" | into duration | sleep $in; nu -c "$nu.plugin-path"}` to simulate parallel access. This approach is not so reliable to reproduce as running test but still a good point that it may effect users actually 4. validate that your `plugin.nu` file was stripped <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> # Solution In this pr I've refactored the code of handling the `register` command to minimize code duplications and make sure that overwrite of `plugin.nu` file is happen only when user calls the command and not on nu startup Another option would be to use temp `plugin.nu` when running tests, but as the issue actually can affect users I've decided to prevent unnecessary writing at all. Although having isolated `plugin.nu` still worth of doing # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> It changes the behaviour actually as the call `register <plugin> <signature>` now doesn't updates `plugin.nu` and just reads signatures to the memory. But as I understand that kind of call with explicit signature is meant to use only by nushell itself in the `plugin.nu` file only. I've asked about it in [discord](https://discordapp.com/channels/601130461678272522/615962413203718156/1140013448915325018) <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> Actually, I think the way plugins are stored might be reworked to prevent or mitigate possible issues further: - problem with writing to file may still arise if we try to register in parallel as several instances will write to the same file so the lock for the file might be required - using additional parameters to command like `register` to implement some internal logic could be misleading to the users - `register` call actually affects global state of nushell that sounds a little bit inconsistent with immutability and isolation of other parts of the nu. See issues [1](https://github.com/nushell/nushell/issues/8581), [2](https://github.com/nushell/nushell/issues/8960)
2023-08-14 13:39:23 +00:00
let error = arguments.and_then(|(path, path_span)| {
let path = path.path_buf();
// restrict plugin file name starts with `nu_plugin_`
let valid_plugin_name = path
.file_name()
.map(|s| s.to_string_lossy().starts_with("nu_plugin_"));
let Some(true) = valid_plugin_name else {
return Err(ParseError::LabeledError(
"Register plugin failed".into(),
"plugin name must start with nu_plugin_".into(),
path_span,
));
};
let signatures = signature.map_or_else(
|| {
let signatures =
get_signature(&path, shell.as_deref(), &current_envs).map_err(|err| {
ParseError::LabeledError(
"Error getting signatures".into(),
err.to_string(),
spans[0],
)
});
fix(nu-parser): do not update plugin.nu file on nu startup (#10007) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description I've been investigating the [issue mentioned](https://github.com/nushell/nushell/pull/9976#issuecomment-1673290467) in my prev pr and I've found that plugin.nu file that is used to cache plugins signatures gets overwritten on every nushell startup and that may actually mess up with the file content if 2 or more instances of nushell will run simultaneously. To reproduce: 1. register at least 2 plugins in your local nushell 2. remember how many entries you have in plugin.nu with `open $nu.plugin-path | find nu_plugin` 3. run - either `cargo test` inside nushell repo - or run smth like this `1..100 | par-each {|it| $"(random integer 1..100)ms" | into duration | sleep $in; nu -c "$nu.plugin-path"}` to simulate parallel access. This approach is not so reliable to reproduce as running test but still a good point that it may effect users actually 4. validate that your `plugin.nu` file was stripped <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> # Solution In this pr I've refactored the code of handling the `register` command to minimize code duplications and make sure that overwrite of `plugin.nu` file is happen only when user calls the command and not on nu startup Another option would be to use temp `plugin.nu` when running tests, but as the issue actually can affect users I've decided to prevent unnecessary writing at all. Although having isolated `plugin.nu` still worth of doing # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> It changes the behaviour actually as the call `register <plugin> <signature>` now doesn't updates `plugin.nu` and just reads signatures to the memory. But as I understand that kind of call with explicit signature is meant to use only by nushell itself in the `plugin.nu` file only. I've asked about it in [discord](https://discordapp.com/channels/601130461678272522/615962413203718156/1140013448915325018) <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> Actually, I think the way plugins are stored might be reworked to prevent or mitigate possible issues further: - problem with writing to file may still arise if we try to register in parallel as several instances will write to the same file so the lock for the file might be required - using additional parameters to command like `register` to implement some internal logic could be misleading to the users - `register` call actually affects global state of nushell that sounds a little bit inconsistent with immutability and isolation of other parts of the nu. See issues [1](https://github.com/nushell/nushell/issues/8581), [2](https://github.com/nushell/nushell/issues/8960)
2023-08-14 13:39:23 +00:00
if signatures.is_ok() {
// mark plugins file as dirty only when the user is registering plugins
// and not when we evaluate plugin.nu on shell startup
2022-09-04 23:00:20 +00:00
working_set.mark_plugins_file_dirty();
fix(nu-parser): do not update plugin.nu file on nu startup (#10007) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description I've been investigating the [issue mentioned](https://github.com/nushell/nushell/pull/9976#issuecomment-1673290467) in my prev pr and I've found that plugin.nu file that is used to cache plugins signatures gets overwritten on every nushell startup and that may actually mess up with the file content if 2 or more instances of nushell will run simultaneously. To reproduce: 1. register at least 2 plugins in your local nushell 2. remember how many entries you have in plugin.nu with `open $nu.plugin-path | find nu_plugin` 3. run - either `cargo test` inside nushell repo - or run smth like this `1..100 | par-each {|it| $"(random integer 1..100)ms" | into duration | sleep $in; nu -c "$nu.plugin-path"}` to simulate parallel access. This approach is not so reliable to reproduce as running test but still a good point that it may effect users actually 4. validate that your `plugin.nu` file was stripped <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> # Solution In this pr I've refactored the code of handling the `register` command to minimize code duplications and make sure that overwrite of `plugin.nu` file is happen only when user calls the command and not on nu startup Another option would be to use temp `plugin.nu` when running tests, but as the issue actually can affect users I've decided to prevent unnecessary writing at all. Although having isolated `plugin.nu` still worth of doing # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> It changes the behaviour actually as the call `register <plugin> <signature>` now doesn't updates `plugin.nu` and just reads signatures to the memory. But as I understand that kind of call with explicit signature is meant to use only by nushell itself in the `plugin.nu` file only. I've asked about it in [discord](https://discordapp.com/channels/601130461678272522/615962413203718156/1140013448915325018) <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> Actually, I think the way plugins are stored might be reworked to prevent or mitigate possible issues further: - problem with writing to file may still arise if we try to register in parallel as several instances will write to the same file so the lock for the file might be required - using additional parameters to command like `register` to implement some internal logic could be misleading to the users - `register` call actually affects global state of nushell that sounds a little bit inconsistent with immutability and isolation of other parts of the nu. See issues [1](https://github.com/nushell/nushell/issues/8581), [2](https://github.com/nushell/nushell/issues/8960)
2023-08-14 13:39:23 +00:00
}
2021-10-31 08:17:01 +00:00
fix(nu-parser): do not update plugin.nu file on nu startup (#10007) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description I've been investigating the [issue mentioned](https://github.com/nushell/nushell/pull/9976#issuecomment-1673290467) in my prev pr and I've found that plugin.nu file that is used to cache plugins signatures gets overwritten on every nushell startup and that may actually mess up with the file content if 2 or more instances of nushell will run simultaneously. To reproduce: 1. register at least 2 plugins in your local nushell 2. remember how many entries you have in plugin.nu with `open $nu.plugin-path | find nu_plugin` 3. run - either `cargo test` inside nushell repo - or run smth like this `1..100 | par-each {|it| $"(random integer 1..100)ms" | into duration | sleep $in; nu -c "$nu.plugin-path"}` to simulate parallel access. This approach is not so reliable to reproduce as running test but still a good point that it may effect users actually 4. validate that your `plugin.nu` file was stripped <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> # Solution In this pr I've refactored the code of handling the `register` command to minimize code duplications and make sure that overwrite of `plugin.nu` file is happen only when user calls the command and not on nu startup Another option would be to use temp `plugin.nu` when running tests, but as the issue actually can affect users I've decided to prevent unnecessary writing at all. Although having isolated `plugin.nu` still worth of doing # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> It changes the behaviour actually as the call `register <plugin> <signature>` now doesn't updates `plugin.nu` and just reads signatures to the memory. But as I understand that kind of call with explicit signature is meant to use only by nushell itself in the `plugin.nu` file only. I've asked about it in [discord](https://discordapp.com/channels/601130461678272522/615962413203718156/1140013448915325018) <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> Actually, I think the way plugins are stored might be reworked to prevent or mitigate possible issues further: - problem with writing to file may still arise if we try to register in parallel as several instances will write to the same file so the lock for the file might be required - using additional parameters to command like `register` to implement some internal logic could be misleading to the users - `register` call actually affects global state of nushell that sounds a little bit inconsistent with immutability and isolation of other parts of the nu. See issues [1](https://github.com/nushell/nushell/issues/8581), [2](https://github.com/nushell/nushell/issues/8960)
2023-08-14 13:39:23 +00:00
signatures
},
|sig| sig.map(|sig| vec![sig]),
)?;
for signature in signatures {
// create plugin command declaration (need struct impl Command)
// store declaration in working set
let plugin_decl = PluginDeclaration::new(path.clone(), signature, shell.clone());
working_set.add_decl(Box::new(plugin_decl));
}
Ok(())
});
fix(nu-parser): do not update plugin.nu file on nu startup (#10007) <!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description I've been investigating the [issue mentioned](https://github.com/nushell/nushell/pull/9976#issuecomment-1673290467) in my prev pr and I've found that plugin.nu file that is used to cache plugins signatures gets overwritten on every nushell startup and that may actually mess up with the file content if 2 or more instances of nushell will run simultaneously. To reproduce: 1. register at least 2 plugins in your local nushell 2. remember how many entries you have in plugin.nu with `open $nu.plugin-path | find nu_plugin` 3. run - either `cargo test` inside nushell repo - or run smth like this `1..100 | par-each {|it| $"(random integer 1..100)ms" | into duration | sleep $in; nu -c "$nu.plugin-path"}` to simulate parallel access. This approach is not so reliable to reproduce as running test but still a good point that it may effect users actually 4. validate that your `plugin.nu` file was stripped <!-- Thank you for improving Nushell. Please, check our [contributing guide](../CONTRIBUTING.md) and talk to the core team before making major changes. Description of your pull request goes here. **Provide examples and/or screenshots** if your changes affect the user experience. --> # Solution In this pr I've refactored the code of handling the `register` command to minimize code duplications and make sure that overwrite of `plugin.nu` file is happen only when user calls the command and not on nu startup Another option would be to use temp `plugin.nu` when running tests, but as the issue actually can affect users I've decided to prevent unnecessary writing at all. Although having isolated `plugin.nu` still worth of doing # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> It changes the behaviour actually as the call `register <plugin> <signature>` now doesn't updates `plugin.nu` and just reads signatures to the memory. But as I understand that kind of call with explicit signature is meant to use only by nushell itself in the `plugin.nu` file only. I've asked about it in [discord](https://discordapp.com/channels/601130461678272522/615962413203718156/1140013448915325018) <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect -A clippy::result_large_err` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --> Actually, I think the way plugins are stored might be reworked to prevent or mitigate possible issues further: - problem with writing to file may still arise if we try to register in parallel as several instances will write to the same file so the lock for the file might be required - using additional parameters to command like `register` to implement some internal logic could be misleading to the users - `register` call actually affects global state of nushell that sounds a little bit inconsistent with immutability and isolation of other parts of the nu. See issues [1](https://github.com/nushell/nushell/issues/8581), [2](https://github.com/nushell/nushell/issues/8960)
2023-08-14 13:39:23 +00:00
if let Err(err) = error {
working_set.error(err);
}
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Nothing,
custom_completion: None,
}])
2021-10-31 08:17:01 +00:00
}
pub fn find_dirs_var(working_set: &StateWorkingSet, var_name: &str) -> Option<VarId> {
working_set
.find_variable(format!("${}", var_name).as_bytes())
2023-07-13 21:02:05 +00:00
.filter(|var_id| working_set.get_variable(*var_id).const_val.is_some())
}
/// This helper function is used to find files during parsing
///
/// First, the actual current working directory is selected as
/// a) the directory of a file currently being parsed
/// b) current working directory (PWD)
///
/// Then, if the file is not found in the actual cwd, dirs_var is checked.
/// For now, we first check for a const with the name of `dirs_var_name`,
/// and if that's not found, then we try to look for an environment variable of the same name.
/// If there is a relative path in dirs_var, it is assumed to be relative to the actual cwd
/// determined in the first step.
///
/// Always returns an absolute path
pub fn find_in_dirs(
filename: &str,
working_set: &StateWorkingSet,
cwd: &str,
dirs_var_name: &str,
) -> Option<ParserPath> {
pub fn find_in_dirs_with_id(
filename: &str,
working_set: &StateWorkingSet,
cwd: &str,
dirs_var_name: &str,
) -> Option<ParserPath> {
// Choose whether to use file-relative or PWD-relative path
let actual_cwd = if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
currently_parsed_cwd.as_path()
} else {
Path::new(cwd)
};
// Try if we have an existing virtual path
if let Some(virtual_path) = working_set.find_virtual_path(filename) {
return Some(ParserPath::from_virtual_path(
working_set,
filename,
virtual_path,
));
} else {
let abs_virtual_filename = actual_cwd.join(filename);
let abs_virtual_filename = abs_virtual_filename.to_string_lossy();
if let Some(virtual_path) = working_set.find_virtual_path(&abs_virtual_filename) {
return Some(ParserPath::from_virtual_path(
working_set,
&abs_virtual_filename,
virtual_path,
));
}
}
// Try if we have an existing physical path
if let Ok(p) = canonicalize_with(filename, actual_cwd) {
return Some(ParserPath::RealPath(p));
}
// Early-exit if path is non-existent absolute path
let path = Path::new(filename);
if !path.is_relative() {
return None;
}
// Look up relative path from NU_LIB_DIRS
working_set
2023-07-13 21:02:05 +00:00
.get_variable(find_dirs_var(working_set, dirs_var_name)?)
.const_val
.as_ref()?
.as_list()
.ok()?
.iter()
.map(|lib_dir| -> Option<PathBuf> {
let dir = lib_dir.as_path().ok()?;
let dir_abs = canonicalize_with(dir, actual_cwd).ok()?;
canonicalize_with(filename, dir_abs).ok()
})
.find(Option::is_some)
.flatten()
.map(ParserPath::RealPath)
}
// TODO: remove (see #8310)
// Same as find_in_dirs_with_id but using $env.NU_LIB_DIRS instead of constant
pub fn find_in_dirs_old(
filename: &str,
working_set: &StateWorkingSet,
cwd: &str,
dirs_env: &str,
) -> Option<PathBuf> {
// Choose whether to use file-relative or PWD-relative path
let actual_cwd = if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
currently_parsed_cwd.as_path()
} else {
Path::new(cwd)
};
if let Ok(p) = canonicalize_with(filename, actual_cwd) {
Some(p)
} else {
let path = Path::new(filename);
if path.is_relative() {
if let Some(lib_dirs) = working_set.get_env_var(dirs_env) {
if let Ok(dirs) = lib_dirs.as_list() {
for lib_dir in dirs {
if let Ok(dir) = lib_dir.as_path() {
// make sure the dir is absolute path
if let Ok(dir_abs) = canonicalize_with(dir, actual_cwd) {
if let Ok(path) = canonicalize_with(filename, dir_abs) {
return Some(path);
}
}
}
}
None
} else {
None
}
} else {
None
}
} else {
None
}
}
}
find_in_dirs_with_id(filename, working_set, cwd, dirs_var_name).or_else(|| {
find_in_dirs_old(filename, working_set, cwd, dirs_var_name).map(ParserPath::RealPath)
})
}
fn detect_params_in_name(
working_set: &StateWorkingSet,
name_span: Span,
decl_name: &str,
) -> Option<ParseError> {
let name = working_set.get_span_contents(name_span);
let extract_span = |delim: u8| {
// it is okay to unwrap because we know the slice contains the byte
let (idx, _) = name
.iter()
.find_position(|c| **c == delim)
.unwrap_or((name.len(), &b' '));
let param_span = Span::new(name_span.start + idx - 1, name_span.start + idx - 1);
let error = ParseError::LabeledErrorWithHelp{
error: "no space between name and parameters".into(),
label: "expected space".into(),
help: format!("consider adding a space between the `{decl_name}` command's name and its parameters"),
span: param_span,
};
Some(error)
};
if name.contains(&b'[') {
extract_span(b'[')
} else if name.contains(&b'(') {
extract_span(b'(')
} else {
None
}
}
Fix incorrect handling of boolean flags for builtin commands (#11492) # Description Possible fix of #11456 This PR fixes a bug where builtin commands did not respect the logic of dynamically passed boolean flags. The reason is [has_flag](https://github.com/nushell/nushell/blob/6f59abaf4310487f7a6319437be6ec61abcbc3b9/crates/nu-protocol/src/ast/call.rs#L204C5-L212C6) method did not evaluate and take into consideration expression used with flag. To address this issue a solution is proposed: 1. `has_flag` method is moved to `CallExt` and new logic to evaluate expression and check if it is a boolean value is added 2. `has_flag_const` method is added to `CallExt` which is a constant version of `has_flag` 3. `has_named` method is added to `Call` which is basically the old logic of `has_flag` 4. All usages of `has_flag` in code are updated, mostly to pass `engine_state` and `stack` to new `has_flag`. In `run_const` commands it is replaced with `has_flag_const`. And in a few select places: parser, `to nuon` and `into string` old logic via `has_named` is used. # User-Facing Changes Explicit values of boolean flags are now respected in builtin commands. Before: ![image](https://github.com/nushell/nushell/assets/17511668/f9fbabb2-3cfd-43f9-ba9e-ece76d80043c) After: ![image](https://github.com/nushell/nushell/assets/17511668/21867596-2075-437f-9c85-45563ac70083) Another example: Before: ![image](https://github.com/nushell/nushell/assets/17511668/efdbc5ca-5227-45a4-ac5b-532cdc2bbf5f) After: ![image](https://github.com/nushell/nushell/assets/17511668/2907d5c5-aa93-404d-af1c-21cdc3d44646) # Tests + Formatting Added test reproducing some variants of original issue.
2024-01-11 15:19:48 +00:00
/// Run has_flag_const and and push possible error to working_set
fn has_flag_wrapped(
working_set: &mut StateWorkingSet,
call: &Call,
name: &str,
) -> Result<bool, ()> {
call.has_flag_const(working_set, name).map_err(|err| {
working_set.error(err.wrap(working_set, call.span()));
})
}