2022-08-10 06:28:03 +02:00
|
|
|
use nu_test_support::fs::Stub::EmptyFile;
|
2025-01-15 23:10:28 +01:00
|
|
|
use nu_test_support::nu;
|
2022-07-17 23:30:33 +02:00
|
|
|
use nu_test_support::playground::Playground;
|
2025-01-15 23:10:28 +01:00
|
|
|
use rstest::rstest;
|
|
|
|
use rstest_reuse::*;
|
|
|
|
|
|
|
|
// Template for run-external test to ensure tests work when calling
|
|
|
|
// the binary directly, using the caret operator, and when using
|
|
|
|
// the run-external command
|
|
|
|
#[template]
|
|
|
|
#[rstest]
|
|
|
|
#[case("")]
|
|
|
|
#[case("^")]
|
|
|
|
#[case("run-external ")]
|
|
|
|
fn run_external_prefixes(#[case] prefix: &str) {}
|
|
|
|
|
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn better_empty_redirection(prefix: &str) {
|
2022-03-08 02:17:33 +01:00
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: "tests/fixtures/formats",
|
|
|
|
"ls | each {{ |it| {}nu `--testbin` cococo $it.name }} | ignore",
|
|
|
|
prefix
|
|
|
|
);
|
2022-03-08 02:17:33 +01:00
|
|
|
|
|
|
|
eprintln!("out: {}", actual.out);
|
|
|
|
|
|
|
|
assert!(!actual.out.contains('2'));
|
|
|
|
}
|
2022-07-17 23:30:33 +02:00
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn explicit_glob(prefix: &str) {
|
2022-07-17 23:30:33 +02:00
|
|
|
Playground::setup("external with explicit glob", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[
|
2022-07-17 23:30:33 +02:00
|
|
|
EmptyFile("D&D_volume_1.txt"),
|
|
|
|
EmptyFile("D&D_volume_2.txt"),
|
|
|
|
EmptyFile("foo.sh"),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-07-17 23:30:33 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo ('*.txt' | into glob)
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-17 23:30:33 +02:00
|
|
|
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
assert!(actual.out.contains("D&D_volume_1.txt"));
|
|
|
|
assert!(actual.out.contains("D&D_volume_2.txt"));
|
2022-07-17 23:30:33 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn bare_word_expand_path_glob(prefix: &str) {
|
2022-07-17 23:30:33 +02:00
|
|
|
Playground::setup("bare word should do the expansion", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[
|
2022-07-17 23:30:33 +02:00
|
|
|
EmptyFile("D&D_volume_1.txt"),
|
|
|
|
EmptyFile("D&D_volume_2.txt"),
|
|
|
|
EmptyFile("foo.sh"),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2023-07-21 17:32:37 +02:00
|
|
|
"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo *.txt
|
|
|
|
",
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-17 23:30:33 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("D&D_volume_1.txt"));
|
|
|
|
assert!(actual.out.contains("D&D_volume_2.txt"));
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn backtick_expand_path_glob(prefix: &str) {
|
2022-07-17 23:30:33 +02:00
|
|
|
Playground::setup("backtick should do the expansion", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[
|
2022-07-17 23:30:33 +02:00
|
|
|
EmptyFile("D&D_volume_1.txt"),
|
|
|
|
EmptyFile("D&D_volume_2.txt"),
|
|
|
|
EmptyFile("foo.sh"),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-07-17 23:30:33 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo `*.txt`
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-17 23:30:33 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("D&D_volume_1.txt"));
|
|
|
|
assert!(actual.out.contains("D&D_volume_2.txt"));
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn single_quote_does_not_expand_path_glob(prefix: &str) {
|
2022-07-17 23:30:33 +02:00
|
|
|
Playground::setup("single quote do not run the expansion", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[
|
2022-07-17 23:30:33 +02:00
|
|
|
EmptyFile("D&D_volume_1.txt"),
|
|
|
|
EmptyFile("D&D_volume_2.txt"),
|
|
|
|
EmptyFile("foo.sh"),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-07-17 23:30:33 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo '*.txt'
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-17 23:30:33 +02:00
|
|
|
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
assert_eq!(actual.out, "*.txt");
|
2022-07-17 23:30:33 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn double_quote_does_not_expand_path_glob(prefix: &str) {
|
2022-07-17 23:30:33 +02:00
|
|
|
Playground::setup("double quote do not run the expansion", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[
|
2022-07-17 23:30:33 +02:00
|
|
|
EmptyFile("D&D_volume_1.txt"),
|
|
|
|
EmptyFile("D&D_volume_2.txt"),
|
|
|
|
EmptyFile("foo.sh"),
|
|
|
|
]);
|
|
|
|
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-07-17 23:30:33 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo "*.txt"
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-17 23:30:33 +02:00
|
|
|
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
assert_eq!(actual.out, "*.txt");
|
2022-07-17 23:30:33 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn failed_command_with_semicolon_will_not_execute_following_cmds(prefix: &str) {
|
2022-07-20 14:44:42 +02:00
|
|
|
Playground::setup("external failed command with semicolon", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2023-07-21 17:32:37 +02:00
|
|
|
"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` fail; echo done
|
|
|
|
",
|
|
|
|
prefix
|
|
|
|
);
|
2022-07-20 14:44:42 +02:00
|
|
|
|
|
|
|
assert!(!actual.out.contains("done"));
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_args_with_quoted(prefix: &str) {
|
2022-08-26 13:50:41 +02:00
|
|
|
Playground::setup("external failed command with semicolon", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-08-26 13:50:41 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo "foo=bar 'hi'"
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-08-26 13:50:41 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo=bar 'hi'");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
// don't use template for this once since echo with no prefix is an internal command
|
|
|
|
// and arguments flags are treated as arguments to run-external
|
|
|
|
// (but wrapping them in quotes defeats the point of test)
|
2022-08-26 13:50:41 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
#[test]
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
fn external_arg_with_option_like_embedded_quotes() {
|
|
|
|
// TODO: would be nice to make this work with cococo, but arg parsing interferes
|
|
|
|
Playground::setup(
|
|
|
|
"external arg with option like embedded quotes",
|
|
|
|
|dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
^echo --foo='bar' -foo='bar'
|
|
|
|
"#,
|
|
|
|
);
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "--foo=bar -foo=bar");
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
// FIXME: parser complains about invalid characters after single quote
|
|
|
|
#[rstest]
|
|
|
|
#[case("")]
|
|
|
|
#[case("^")]
|
|
|
|
fn external_arg_with_non_option_like_embedded_quotes(#[case] prefix: &str) {
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
Playground::setup(
|
|
|
|
"external arg with non option like embedded quotes",
|
|
|
|
|dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo foo='bar' 'foo'=bar
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo=bar foo=bar");
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
// FIXME: parser bug prevents expressions from appearing within GlobPattern substrings
|
|
|
|
#[rstest]
|
|
|
|
#[case("")]
|
|
|
|
#[case("^")]
|
|
|
|
fn external_arg_with_string_interpolation(#[case] prefix: &str) {
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
Playground::setup("external arg with string interpolation", |dirs, _| {
|
2022-08-26 13:50:41 +02:00
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-08-26 13:50:41 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo foo=(2 + 2) $"foo=(2 + 2)" foo=$"(2 + 2)"
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-08-26 13:50:41 +02:00
|
|
|
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
assert_eq!(actual.out, "foo=4 foo=4 foo=4");
|
2022-08-26 13:50:41 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_arg_with_variable_name(prefix: &str) {
|
2022-08-27 15:22:02 +02:00
|
|
|
Playground::setup("external failed command with semicolon", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-08-27 15:22:02 +02:00
|
|
|
r#"
|
|
|
|
let dump_command = "PGPASSWORD='db_secret' pg_dump -Fc -h 'db.host' -p '$db.port' -U postgres -d 'db_name' > '/tmp/dump_name'";
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` nonu $dump_command
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-08-27 15:22:02 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
actual.out,
|
|
|
|
r#"PGPASSWORD='db_secret' pg_dump -Fc -h 'db.host' -p '$db.port' -U postgres -d 'db_name' > '/tmp/dump_name'"#
|
|
|
|
);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_escape_args(prefix: &str) {
|
2022-09-17 13:07:45 +02:00
|
|
|
Playground::setup("external failed command with semicolon", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2022-09-17 13:07:45 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo "\"abcd"
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2022-09-17 13:07:45 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, r#""abcd"#);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_ndots_args(prefix: &str) {
|
|
|
|
let actual = nu!(
|
|
|
|
r#"
|
|
|
|
{}nu `--testbin` cococo foo/. foo/.. foo/... foo/./bar foo/../bar foo/.../bar ./bar ../bar .../bar
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
Mitigate the poor interaction between ndots expansion and non-path strings (#13218)
# Description
@hustcer reported that slashes were disappearing from external args
since #13089:
```
$> ossutil ls oss://abc/b/c
Error: invalid cloud url: "oss:/abc/b/c", please make sure the url starts with: "oss://"
$> ossutil ls 'oss://abc/b/c'
Error: oss: service returned error: StatusCode=403, ErrorCode=UserDisable, ErrorMessage="UserDisable", RequestId=66791EDEFE87B73537120838, Ec=0003-00000801, Bucket=abc, Object=
```
I narrowed this down to the ndots handling, since that does path parsing
and path reconstruction in every case. I decided to change that so that
it only activates if the string contains at least `...`, since that
would be the minimum trigger for ndots, and also to not activate it if
the string contains `://`, since it's probably undesirable for a URL.
Kind of a hack, but I'm not really sure how else we decide whether
someone wants ndots or not.
# User-Facing Changes
- bare strings not containing ndots are not modified
- bare strings containing `://` are not modified
# Tests + Formatting
Added tests to prevent regression.
2024-06-25 01:39:01 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
actual.out,
|
|
|
|
if cfg!(windows) {
|
|
|
|
// Windows is a bit weird right now, where if ndots has to fix something it's going to
|
|
|
|
// change everything to backslashes too. Would be good to fix that
|
|
|
|
r"foo/. foo/.. foo\..\.. foo/./bar foo/../bar foo\..\..\bar ./bar ../bar ..\..\bar"
|
|
|
|
} else {
|
|
|
|
r"foo/. foo/.. foo/../.. foo/./bar foo/../bar foo/../../bar ./bar ../bar ../../bar"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_ndots_leading_dot_slash(prefix: &str) {
|
Don't expand ndots if prefixed with `./` (#14755)
<!--
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
Prevents ndots from being expanded if they are prefixed with `./`, as
the agreed resolution to #13303. Only applies to externals, mirroring
the fix from #13218.
I did
[attempt](https://github.com/132ikl/nushell/tree/internal-ndots-attempt)
to apply the fix for internal commands as well, but it seems like the
path is expanded too aggressively and I haven't investigated it further
yet. `./...` gets normalized into `<pwd>/./...`, which gets normalized
into `<pwd>/...` before being handed to `expand_ndots`, and at that
point it just looks like a normal n-dots so we can't tell we shouldn't
expand.
(Fixes #13303)
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
* N-dots are no longer expanded to external command calls when prefixed
with `./`.
# 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
Added tests to prevent regression.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# 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.
-->
N/A
2025-01-05 23:07:34 +01:00
|
|
|
// Don't expand ndots with a leading `./`
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(
|
|
|
|
r#"
|
|
|
|
{}nu `--testbin` cococo ./... ./....
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
Don't expand ndots if prefixed with `./` (#14755)
<!--
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
Prevents ndots from being expanded if they are prefixed with `./`, as
the agreed resolution to #13303. Only applies to externals, mirroring
the fix from #13218.
I did
[attempt](https://github.com/132ikl/nushell/tree/internal-ndots-attempt)
to apply the fix for internal commands as well, but it seems like the
path is expanded too aggressively and I haven't investigated it further
yet. `./...` gets normalized into `<pwd>/./...`, which gets normalized
into `<pwd>/...` before being handed to `expand_ndots`, and at that
point it just looks like a normal n-dots so we can't tell we shouldn't
expand.
(Fixes #13303)
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
* N-dots are no longer expanded to external command calls when prefixed
with `./`.
# 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 toolkit.nu; toolkit test stdlib"` 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
> ```
-->
Added tests to prevent regression.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# 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.
-->
N/A
2025-01-05 23:07:34 +01:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "./... ./....");
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_url_args(prefix: &str) {
|
Mitigate the poor interaction between ndots expansion and non-path strings (#13218)
# Description
@hustcer reported that slashes were disappearing from external args
since #13089:
```
$> ossutil ls oss://abc/b/c
Error: invalid cloud url: "oss:/abc/b/c", please make sure the url starts with: "oss://"
$> ossutil ls 'oss://abc/b/c'
Error: oss: service returned error: StatusCode=403, ErrorCode=UserDisable, ErrorMessage="UserDisable", RequestId=66791EDEFE87B73537120838, Ec=0003-00000801, Bucket=abc, Object=
```
I narrowed this down to the ndots handling, since that does path parsing
and path reconstruction in every case. I decided to change that so that
it only activates if the string contains at least `...`, since that
would be the minimum trigger for ndots, and also to not activate it if
the string contains `://`, since it's probably undesirable for a URL.
Kind of a hack, but I'm not really sure how else we decide whether
someone wants ndots or not.
# User-Facing Changes
- bare strings not containing ndots are not modified
- bare strings containing `://` are not modified
# Tests + Formatting
Added tests to prevent regression.
2024-06-25 01:39:01 +02:00
|
|
|
// If ndots is not handled correctly, we can lose the double forward slashes that are needed
|
|
|
|
// here
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(
|
|
|
|
r#"
|
|
|
|
{}nu `--testbin` cococo http://example.com http://example.com/.../foo //foo
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
Mitigate the poor interaction between ndots expansion and non-path strings (#13218)
# Description
@hustcer reported that slashes were disappearing from external args
since #13089:
```
$> ossutil ls oss://abc/b/c
Error: invalid cloud url: "oss:/abc/b/c", please make sure the url starts with: "oss://"
$> ossutil ls 'oss://abc/b/c'
Error: oss: service returned error: StatusCode=403, ErrorCode=UserDisable, ErrorMessage="UserDisable", RequestId=66791EDEFE87B73537120838, Ec=0003-00000801, Bucket=abc, Object=
```
I narrowed this down to the ndots handling, since that does path parsing
and path reconstruction in every case. I decided to change that so that
it only activates if the string contains at least `...`, since that
would be the minimum trigger for ndots, and also to not activate it if
the string contains `://`, since it's probably undesirable for a URL.
Kind of a hack, but I'm not really sure how else we decide whether
someone wants ndots or not.
# User-Facing Changes
- bare strings not containing ndots are not modified
- bare strings containing `://` are not modified
# Tests + Formatting
Added tests to prevent regression.
2024-06-25 01:39:01 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
actual.out,
|
|
|
|
"http://example.com http://example.com/.../foo //foo"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
#[cfg_attr(
|
|
|
|
not(target_os = "linux"),
|
|
|
|
ignore = "only runs on Linux, where controlling the HOME var is reliable"
|
|
|
|
)]
|
2025-01-15 23:10:28 +01:00
|
|
|
fn external_command_expand_tilde(prefix: &str) {
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
Playground::setup("external command expand tilde", |dirs, _| {
|
|
|
|
// Make a copy of the nu executable that we can use
|
|
|
|
let mut src = std::fs::File::open(nu_test_support::fs::binaries().join("nu"))
|
|
|
|
.expect("failed to open nu");
|
|
|
|
let mut dst = std::fs::File::create_new(dirs.test().join("test_nu"))
|
|
|
|
.expect("failed to create test_nu file");
|
|
|
|
std::io::copy(&mut src, &mut dst).expect("failed to copy data for nu binary");
|
|
|
|
|
|
|
|
// Make test_nu have the same permissions so that it's executable
|
|
|
|
dst.set_permissions(
|
|
|
|
src.metadata()
|
|
|
|
.expect("failed to get nu metadata")
|
|
|
|
.permissions(),
|
|
|
|
)
|
|
|
|
.expect("failed to set permissions on test_nu");
|
|
|
|
|
|
|
|
// Close the files
|
|
|
|
drop(dst);
|
|
|
|
drop(src);
|
|
|
|
|
|
|
|
let actual = nu!(
|
|
|
|
envs: vec![
|
|
|
|
("HOME".to_string(), dirs.test().to_string_lossy().into_owned()),
|
|
|
|
],
|
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}~/test_nu `--testbin` cococo hello
|
|
|
|
"#,
|
|
|
|
prefix
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
);
|
|
|
|
assert_eq!(actual.out, "hello");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
// FIXME: parser bug prevents expressions from appearing within GlobPattern substrings
|
|
|
|
#[rstest]
|
|
|
|
#[case("")]
|
|
|
|
#[case("^")]
|
|
|
|
fn external_arg_expand_tilde(#[case] prefix: &str) {
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
Playground::setup("external arg expand tilde", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo ~/foo ~/(2 + 2)
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
|
2024-07-16 14:16:26 +02:00
|
|
|
let home = dirs::home_dir().expect("failed to find home dir");
|
Move most of the peculiar argument handling for external calls into the parser (#13089)
# Description
We've had a lot of different issues and PRs related to arg handling with
externals since the rewrite of `run-external` in #12921:
- #12950
- #12955
- #13000
- #13001
- #13021
- #13027
- #13028
- #13073
Many of these are caused by the argument handling of external calls and
`run-external` being very special and involving the parser handing
quoted strings over to `run-external` so that it knows whether to expand
tildes and globs and so on. This is really unusual and also makes it
harder to use `run-external`, and also harder to understand it (and
probably is part of the reason why it was rewritten in the first place).
This PR moves a lot more of that work over to the parser, so that by the
time `run-external` gets it, it's dealing with much more normal Nushell
values. In particular:
- Unquoted strings are handled as globs with no expand
- The unescaped-but-quoted handling of strings was removed, and the
parser constructs normal looking strings instead, removing internal
quotes so that `run-external` doesn't have to do it
- Bare word interpolation is now supported and expansion is done in this
case
- Expressions typed as `Glob` containing `Expr::StringInterpolation` now
produce `Value::Glob` instead, with the quoted status from the expr
passed through so we know if it was a bare word
- Bare word interpolation for values typed as `glob` now possible, but
not implemented
- Because expansion is now triggered by `Value::Glob(_, false)` instead
of looking at the expr, externals now support glob types
# User-Facing Changes
- Bare word interpolation works for external command options, and
otherwise embedded in other strings:
```nushell
^echo --foo=(2 + 2) # prints --foo=4
^echo -foo=$"(2 + 2)" # prints -foo=4
^echo foo="(2 + 2)" # prints (no interpolation!) foo=(2 + 2)
^echo foo,(2 + 2),bar # prints foo,4,bar
```
- Bare word interpolation expands for external command head/args:
```nushell
let name = "exa"
~/.cargo/bin/($name) # this works, and expands the tilde
^$"~/.cargo/bin/($name)" # this doesn't expand the tilde
^echo ~/($name)/* # this glob is expanded
^echo $"~/($name)/*" # this isn't expanded
```
- Ndots are now supported for the head of an external command
(`^.../foo` works)
- Glob values are now supported for head/args of an external command,
and expanded appropriately:
```nushell
^("~/.cargo/bin/exa" | into glob) # the tilde is expanded
^echo ("*.txt" | into glob) # this glob is expanded
```
- `run-external` now works more like any other command, without
expecting a special call convention
for its args:
```nushell
run-external echo "'foo'"
# before PR: 'foo'
# after PR: foo
run-external echo "*.txt"
# before PR: (glob is expanded)
# after PR: *.txt
```
# Tests + Formatting
Lots of tests added and cleaned up. Some tests that weren't active on
Windows changed to use `nu --testbin cococo` so that they can work.
Added a test for Linux only to make sure tilde expansion of commands
works, because changing `HOME` there causes `~` to reliably change.
- :green_circle: `toolkit fmt`
- :green_circle: `toolkit clippy`
- :green_circle: `toolkit test`
- :green_circle: `toolkit test stdlib`
# After Submitting
- [ ] release notes: make sure to mention the new syntaxes that are
supported
2024-06-20 06:00:03 +02:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
actual.out,
|
|
|
|
format!(
|
|
|
|
"{} {}",
|
|
|
|
home.join("foo").display(),
|
|
|
|
home.join("4").display()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_not_expand_tilde_with_quotes(prefix: &str) {
|
2023-01-12 01:14:19 +01:00
|
|
|
Playground::setup(
|
|
|
|
"external command not expand tilde with quotes",
|
|
|
|
|dirs, _| {
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), r#"{}nu `--testbin` nonu "~""#, prefix);
|
2023-01-12 01:14:19 +01:00
|
|
|
assert_eq!(actual.out, r#"~"#);
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_expand_tilde_with_back_quotes(prefix: &str) {
|
2023-03-26 11:17:51 +02:00
|
|
|
Playground::setup(
|
|
|
|
"external command not expand tilde with quotes",
|
|
|
|
|dirs, _| {
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), r#"{}nu `--testbin` nonu `~`"#, prefix);
|
Require that values that look like numbers parse as numberlike (#8635)
# Description
Require that any value that looks like it might be a number (starts with
a digit, or a '-' + digit, or a '+' + digits, or a special form float
like `-inf`, `inf`, or `NaN`) must now be treated as a number-like
value. Number-like syntax can only parse into number-like values.
Number-like values include: durations, ints, floats, ranges, filesizes,
binary data, etc.
# User-Facing Changes
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
BREAKING CHANGE
Just making sure we see this for release notes 😅
This breaks any and all numberlike values that were treated as strings
before. Example, we used to allow `3,` as a bare word. Anything like
this would now require quotes or backticks to be treated as a string or
bare word, respectively.
# 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
> **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-03-28 08:31:38 +02:00
|
|
|
assert!(!actual.out.contains('~'));
|
2023-03-26 11:17:51 +02:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn external_command_receives_raw_binary_data(prefix: &str) {
|
2023-02-24 21:39:52 +01:00
|
|
|
Playground::setup("external command receives raw binary data", |dirs, _| {
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(
|
|
|
|
cwd: dirs.test(),
|
|
|
|
"0x[deadbeef] | {}nu `--testbin` input_bytes_length",
|
|
|
|
prefix
|
|
|
|
);
|
2023-02-24 21:39:52 +01:00
|
|
|
assert_eq!(actual.out, r#"4"#);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-08-10 01:24:08 +02:00
|
|
|
#[cfg(windows)]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn can_run_cmd_files(prefix: &str) {
|
2022-08-10 06:28:03 +02:00
|
|
|
use nu_test_support::fs::Stub::FileWithContent;
|
2024-11-20 14:55:26 +01:00
|
|
|
Playground::setup("run a Windows cmd file", |dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[FileWithContent(
|
2022-08-10 01:24:08 +02:00
|
|
|
"foo.cmd",
|
|
|
|
r#"
|
|
|
|
@echo off
|
|
|
|
echo Hello World
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), "{}foo.cmd", prefix);
|
2022-08-10 01:24:08 +02:00
|
|
|
assert!(actual.out.contains("Hello World"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-11-20 14:55:26 +01:00
|
|
|
#[cfg(windows)]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn can_run_batch_files(prefix: &str) {
|
2024-11-20 14:55:26 +01:00
|
|
|
use nu_test_support::fs::Stub::FileWithContent;
|
|
|
|
Playground::setup("run a Windows batch file", |dirs, sandbox| {
|
|
|
|
sandbox.with_files(&[FileWithContent(
|
|
|
|
"foo.bat",
|
|
|
|
r#"
|
|
|
|
@echo off
|
|
|
|
echo Hello World
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), "{}foo.bat", prefix);
|
2024-11-20 14:55:26 +01:00
|
|
|
assert!(actual.out.contains("Hello World"));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-08-10 01:24:08 +02:00
|
|
|
#[cfg(windows)]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn can_run_batch_files_without_cmd_extension(prefix: &str) {
|
2022-08-10 06:28:03 +02:00
|
|
|
use nu_test_support::fs::Stub::FileWithContent;
|
2022-08-10 01:24:08 +02:00
|
|
|
Playground::setup(
|
2024-11-20 14:55:26 +01:00
|
|
|
"run a Windows cmd file without specifying the extension",
|
2022-08-10 01:24:08 +02:00
|
|
|
|dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[FileWithContent(
|
2022-08-10 01:24:08 +02:00
|
|
|
"foo.cmd",
|
|
|
|
r#"
|
|
|
|
@echo off
|
|
|
|
echo Hello World
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), "{}foo", prefix);
|
2022-08-10 01:24:08 +02:00
|
|
|
assert!(actual.out.contains("Hello World"));
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn can_run_batch_files_without_bat_extension(prefix: &str) {
|
2022-08-10 06:28:03 +02:00
|
|
|
use nu_test_support::fs::Stub::FileWithContent;
|
2022-08-10 01:24:08 +02:00
|
|
|
Playground::setup(
|
|
|
|
"run a Windows batch file without specifying the extension",
|
|
|
|
|dirs, sandbox| {
|
2024-05-04 02:53:15 +02:00
|
|
|
sandbox.with_files(&[FileWithContent(
|
2022-08-10 01:24:08 +02:00
|
|
|
"foo.bat",
|
|
|
|
r#"
|
|
|
|
@echo off
|
|
|
|
echo Hello World
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), "{}foo", prefix);
|
2022-08-10 01:24:08 +02:00
|
|
|
assert!(actual.out.contains("Hello World"));
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2023-01-13 20:00:30 +01:00
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn quotes_trimmed_when_shelling_out(prefix: &str) {
|
2023-01-13 20:00:30 +01:00
|
|
|
// regression test for a bug where we weren't trimming quotes around string args before shelling out to cmd.exe
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(
|
2023-01-13 20:00:30 +01:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}nu `--testbin` cococo "foo"
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2023-01-13 20:00:30 +01:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
}
|
2023-04-28 14:55:48 +02:00
|
|
|
|
2023-11-07 09:35:24 +01:00
|
|
|
#[cfg(not(windows))]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn redirect_combine(prefix: &str) {
|
2023-04-28 14:55:48 +02:00
|
|
|
Playground::setup("redirect_combine", |dirs, _| {
|
|
|
|
let actual = nu!(
|
2025-01-15 23:10:28 +01:00
|
|
|
cwd: dirs.test(),
|
2023-04-28 14:55:48 +02:00
|
|
|
r#"
|
2025-01-15 23:10:28 +01:00
|
|
|
{}sh ...[-c 'echo Foo; echo >&2 Bar'] o+e>| print
|
|
|
|
"#,
|
|
|
|
prefix
|
|
|
|
);
|
2023-04-28 14:55:48 +02:00
|
|
|
|
|
|
|
// Lines are collapsed in the nu! macro
|
|
|
|
assert_eq!(actual.out, "FooBar");
|
|
|
|
});
|
|
|
|
}
|
2024-11-20 14:55:26 +01:00
|
|
|
|
|
|
|
#[cfg(windows)]
|
2025-01-15 23:10:28 +01:00
|
|
|
#[apply(run_external_prefixes)]
|
|
|
|
fn can_run_ps1_files(prefix: &str) {
|
2024-11-20 14:55:26 +01:00
|
|
|
use nu_test_support::fs::Stub::FileWithContent;
|
|
|
|
Playground::setup("run_a_windows_ps_file", |dirs, sandbox| {
|
|
|
|
sandbox.with_files(&[FileWithContent(
|
|
|
|
"foo.ps1",
|
|
|
|
r#"
|
|
|
|
Write-Host Hello World
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
2025-01-15 23:10:28 +01:00
|
|
|
let actual = nu!(cwd: dirs.test(), "{}foo.ps1", prefix);
|
2024-11-20 14:55:26 +01:00
|
|
|
assert!(actual.out.contains("Hello World"));
|
|
|
|
});
|
|
|
|
}
|