2022-08-31 22:32:56 +02:00
|
|
|
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
|
|
|
|
use nu_test_support::playground::Playground;
|
2022-07-29 22:42:00 +02:00
|
|
|
use nu_test_support::{nu, nu_repl_code, pipeline};
|
2023-04-08 20:52:37 +02:00
|
|
|
use pretty_assertions::assert_eq;
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_overlay() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
2022-09-13 09:38:21 +02:00
|
|
|
#[test]
|
|
|
|
fn add_overlay_as_new_name() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"overlay use spam as spam_new"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
2022-08-12 20:06:51 +02:00
|
|
|
#[test]
|
|
|
|
fn add_overlay_twice() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay use spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_prefixed_overlay() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use --prefix spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"spam foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_prefixed_overlay_twice() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use --prefix spam"#,
|
|
|
|
r#"overlay use --prefix spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"spam foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_prefixed_overlay_mismatch_1() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use --prefix spam"#,
|
|
|
|
r#"overlay use spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("exists with a prefix"));
|
|
|
|
// Why doesn't the REPL test work with the previous expected output
|
|
|
|
assert!(actual_repl.err.contains("overlay_prefix_mismatch"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_prefixed_overlay_mismatch_2() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay use --prefix spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("exists without a prefix"));
|
|
|
|
// Why doesn't the REPL test work with the previous expected output
|
|
|
|
assert!(actual_repl.err.contains("overlay_prefix_mismatch"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn prefixed_overlay_keeps_custom_decl() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use --prefix spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"def bar [] { "bar" }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"bar"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
|
|
|
assert_eq!(actual_repl.out, "bar");
|
|
|
|
}
|
|
|
|
|
2022-05-07 21:39:22 +02:00
|
|
|
#[test]
|
|
|
|
fn add_overlay_env() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
2022-08-12 20:06:51 +02:00
|
|
|
#[test]
|
|
|
|
fn add_prefixed_overlay_env_no_prefix() {
|
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use --prefix spam"#,
|
2022-08-12 20:06:51 +02:00
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
2022-05-07 21:39:22 +02:00
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_file_decl() {
|
2022-08-21 16:27:56 +02:00
|
|
|
let inp = &[r#"overlay use samples/spam.nu"#, r#"foo"#];
|
2022-05-08 15:09:39 +02:00
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
2022-12-21 23:21:03 +01:00
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_const_file_decl() {
|
|
|
|
let inp = &[
|
|
|
|
r#"const file = 'samples/spam.nu'"#,
|
|
|
|
r#"overlay use $file"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_const_module_name_decl() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"const mod = 'spam'"#,
|
|
|
|
r#"overlay use $mod"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
}
|
|
|
|
|
2023-01-11 23:18:06 +01:00
|
|
|
#[test]
|
|
|
|
fn new_overlay_from_const_name() {
|
|
|
|
let inp = &[
|
|
|
|
r#"const mod = 'spam'"#,
|
|
|
|
r#"overlay new $mod"#,
|
|
|
|
r#"overlay list | last"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn hide_overlay_from_const_name() {
|
|
|
|
let inp = &[
|
|
|
|
r#"const mod = 'spam'"#,
|
|
|
|
r#"overlay new $mod"#,
|
|
|
|
r#"overlay hide $mod"#,
|
|
|
|
r#"overlay list | str join ' '"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert!(!actual.out.contains("spam"));
|
|
|
|
}
|
|
|
|
|
2022-05-08 15:09:39 +02:00
|
|
|
// This one tests that the `nu_repl()` loop works correctly
|
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_file_decl_cd() {
|
2022-08-21 16:27:56 +02:00
|
|
|
let inp = &[r#"cd samples"#, r#"overlay use spam.nu"#, r#"foo"#];
|
2022-05-08 15:09:39 +02:00
|
|
|
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-08 15:09:39 +02:00
|
|
|
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_file_alias() {
|
2022-08-21 16:27:56 +02:00
|
|
|
let inp = &[r#"overlay use samples/spam.nu"#, r#"bar"#];
|
2022-05-08 15:09:39 +02:00
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "bar");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_overlay_from_file_env() {
|
2022-08-21 16:27:56 +02:00
|
|
|
let inp = &[r#"overlay use samples/spam.nu"#, r#"$env.BAZ"#];
|
2022-05-08 15:09:39 +02:00
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "baz");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "baz");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_overlay_scoped() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"do { overlay use spam }"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-08 15:09:39 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn update_overlay_from_module() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"module spam { export def foo [] { "bar" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "bar");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn update_overlay_from_module_env() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "bar" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "bar");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
2022-09-04 17:36:42 +02:00
|
|
|
#[test]
|
|
|
|
fn overlay_use_do_not_eval_twice() {
|
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-09-04 17:36:42 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"let-env FOO = "bar""#,
|
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
|
|
|
assert_eq!(actual_repl.out, "bar");
|
|
|
|
}
|
|
|
|
|
2022-05-07 21:39:22 +02:00
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay hide spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_last_overlay() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay hide"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_scoped() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"do { overlay hide spam }"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_env() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay hide spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_scoped_env() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-09-25 18:52:43 +02:00
|
|
|
r#"module spam { export-env { let-env FOO = "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"do { overlay hide spam }"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn list_default_overlay() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[r#"overlay list | last"#];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "zero");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "zero");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn list_last_overlay() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"overlay list | last"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "spam");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn list_overlay_scoped() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"do { overlay list | last }"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "spam");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_discard_decl() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"def bagr [] { "bagr" }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "bagr");
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_discard_alias() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias bagr = echo "bagr""#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "bagr");
|
2022-05-08 15:09:39 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_discard_env() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2023-02-16 03:30:56 +01:00
|
|
|
r#"let-env BAGR = 'bagr'"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"$env.BAGR"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
2022-05-24 23:22:17 +02:00
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_keep_decl() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"def bagr [] { "bagr" }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("bagr"));
|
|
|
|
assert!(actual_repl.out.contains("bagr"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_keep_alias() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias bagr = echo 'bagr'"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("bagr"));
|
|
|
|
assert!(actual_repl.out.contains("bagr"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_dont_keep_env() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2023-02-16 03:30:56 +01:00
|
|
|
r#"let-env BAGR = 'bagr'"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"$env.BAGR"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-05-24 23:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_dont_keep_overwritten_decl() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"def foo [] { 'bar' }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "bagr");
|
2022-05-24 23:22:17 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_dont_keep_overwritten_alias() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias bar = echo `baz`"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"bar"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "bagr");
|
2022-05-24 23:22:17 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_dont_keep_overwritten_env() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2023-02-16 03:30:56 +01:00
|
|
|
r#"let-env BAZ = 'bagr'"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"$env.BAZ"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-05-24 23:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_keep_decl_in_latest_overlay() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"def bagr [] { 'bagr' }"#,
|
|
|
|
r#"module eggs { }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("bagr"));
|
|
|
|
assert!(actual_repl.out.contains("bagr"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_keep_alias_in_latest_overlay() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias bagr = echo 'bagr'"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"module eggs { }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"bagr"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
|
|
|
assert!(actual.out.contains("bagr"));
|
|
|
|
assert!(actual_repl.out.contains("bagr"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn hide_overlay_dont_keep_env_in_latest_overlay() {
|
2022-05-24 23:22:17 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2023-02-16 03:30:56 +01:00
|
|
|
r#"let-env BAGR = 'bagr'"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"module eggs { }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"overlay hide --keep-custom spam"#,
|
2022-05-24 23:22:17 +02:00
|
|
|
r#"$env.BAGR"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-24 23:22:17 +02:00
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-05-24 23:22:17 +02:00
|
|
|
}
|
|
|
|
|
2022-05-07 21:39:22 +02:00
|
|
|
#[test]
|
|
|
|
fn preserve_overrides() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"def foo [] { "new-foo" }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"overlay use spam"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "new-foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "new-foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn reset_overrides() {
|
2022-05-08 15:09:39 +02:00
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"def foo [] { "new-foo" }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"overlay use samples/spam.nu"#,
|
2022-05-08 15:09:39 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-07 21:39:22 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
2022-05-08 15:09:39 +02:00
|
|
|
assert_eq!(actual_repl.out, "foo");
|
2022-05-07 21:39:22 +02:00
|
|
|
}
|
2022-05-26 16:47:04 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_new() {
|
|
|
|
let inp = &[r#"overlay new spam"#, r#"overlay list | last"#];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-05-26 16:47:04 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
assert_eq!(actual_repl.out, "spam");
|
|
|
|
}
|
2022-07-11 22:58:28 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_keep_pwd() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"cd samples"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay hide --keep-env [ PWD ] spam"#,
|
2022-07-11 22:58:28 +02:00
|
|
|
r#"$env.PWD | path basename"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
2022-07-29 22:42:00 +02:00
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
2022-07-11 22:58:28 +02:00
|
|
|
|
|
|
|
assert_eq!(actual.out, "samples");
|
|
|
|
assert_eq!(actual_repl.out, "samples");
|
|
|
|
}
|
2022-08-13 16:28:18 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_wrong_rename_type() {
|
2022-08-21 16:27:56 +02:00
|
|
|
let inp = &[r#"module spam {}"#, r#"overlay use spam as { echo foo }"#];
|
2022-08-13 16:28:18 +02:00
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("parse_mismatch"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_add_renamed() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam as eggs --prefix"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
r#"eggs foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
2022-12-21 23:21:03 +01:00
|
|
|
#[test]
|
|
|
|
fn overlay_add_renamed_const() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"const name = 'spam'"#,
|
|
|
|
r#"const new_name = 'eggs'"#,
|
|
|
|
r#"overlay use $name as $new_name --prefix"#,
|
|
|
|
r#"eggs foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
2022-08-13 16:28:18 +02:00
|
|
|
#[test]
|
|
|
|
fn overlay_add_renamed_from_file() {
|
|
|
|
let inp = &[
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use samples/spam.nu as eggs --prefix"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
r#"eggs foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_cant_rename_existing_overlay() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"overlay use spam as eggs"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("cant_add_overlay_help"));
|
|
|
|
assert!(actual_repl.err.contains("cant_add_overlay_help"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_can_add_renamed_overlay() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam as eggs --prefix"#,
|
|
|
|
r#"overlay use spam --prefix"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
r#"(spam foo) + (eggs foo)"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foofoo");
|
|
|
|
assert_eq!(actual_repl.out, "foofoo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn overlay_hide_renamed_overlay() {
|
2022-08-13 16:28:18 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam as eggs"#,
|
|
|
|
r#"overlay hide eggs"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
2022-12-30 16:44:37 +01:00
|
|
|
assert!(actual.err.contains("external_command"));
|
|
|
|
assert!(actual_repl.err.contains("external_command"));
|
2022-08-13 16:28:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2023-03-10 22:20:31 +01:00
|
|
|
fn overlay_hide_and_add_renamed_overlay() {
|
2022-08-13 16:28:18 +02:00
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
2022-08-21 16:27:56 +02:00
|
|
|
r#"overlay use spam as eggs"#,
|
|
|
|
r#"overlay hide eggs"#,
|
|
|
|
r#"overlay use eggs"#,
|
2022-08-13 16:28:18 +02:00
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
2022-08-27 00:32:19 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_export_env() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export-env { let-env FOO = 'foo' } }"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_export_env_hide() {
|
|
|
|
let inp = &[
|
|
|
|
r#"let-env FOO = 'foo'"#,
|
|
|
|
r#"module spam { export-env { hide-env FOO } }"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
2022-12-10 18:23:34 +01:00
|
|
|
assert!(actual.err.contains("not_found"));
|
|
|
|
assert!(actual_repl.err.contains("not_found"));
|
2022-08-27 00:32:19 +02:00
|
|
|
}
|
2022-08-31 22:32:56 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_do_cd() {
|
|
|
|
Playground::setup("overlay_use_do_cd", |dirs, sandbox| {
|
|
|
|
sandbox
|
|
|
|
.mkdir("test1/test2")
|
|
|
|
.with_files(vec![FileWithContentToBeTrimmed(
|
|
|
|
"test1/test2/spam.nu",
|
|
|
|
r#"
|
|
|
|
export-env { cd test1/test2 }
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay use test1/test2/spam.nu"#,
|
|
|
|
r#"$env.PWD | path basename"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: dirs.test(), pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "test2");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_do_cd_file_relative() {
|
|
|
|
Playground::setup("overlay_use_do_cd_file_relative", |dirs, sandbox| {
|
|
|
|
sandbox
|
|
|
|
.mkdir("test1/test2")
|
|
|
|
.with_files(vec![FileWithContentToBeTrimmed(
|
|
|
|
"test1/test2/spam.nu",
|
|
|
|
r#"
|
|
|
|
export-env { cd ($env.FILE_PWD | path join '..') }
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay use test1/test2/spam.nu"#,
|
|
|
|
r#"$env.PWD | path basename"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: dirs.test(), pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "test1");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_dont_cd_overlay() {
|
|
|
|
Playground::setup("overlay_use_dont_cd_overlay", |dirs, sandbox| {
|
|
|
|
sandbox
|
|
|
|
.mkdir("test1/test2")
|
|
|
|
.with_files(vec![FileWithContentToBeTrimmed(
|
|
|
|
"test1/test2/spam.nu",
|
|
|
|
r#"
|
|
|
|
export-env {
|
|
|
|
overlay new spam
|
|
|
|
cd test1/test2
|
|
|
|
overlay hide spam
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)]);
|
|
|
|
|
|
|
|
let inp = &[
|
|
|
|
r#"source-env test1/test2/spam.nu"#,
|
|
|
|
r#"$env.PWD | path basename"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: dirs.test(), pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "overlay_use_dont_cd_overlay");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-09-04 17:36:42 +02:00
|
|
|
fn overlay_use_find_scoped_module() {
|
2022-08-31 22:32:56 +02:00
|
|
|
Playground::setup("overlay_use_find_module_scoped", |dirs, _| {
|
2022-09-04 17:36:42 +02:00
|
|
|
let inp = r#"
|
2022-08-31 22:32:56 +02:00
|
|
|
do {
|
2022-09-04 17:36:42 +02:00
|
|
|
module spam { }
|
2022-08-31 22:32:56 +02:00
|
|
|
|
|
|
|
overlay use spam
|
2022-09-04 17:36:42 +02:00
|
|
|
overlay list | last
|
2022-08-31 22:32:56 +02:00
|
|
|
}
|
2022-09-04 17:36:42 +02:00
|
|
|
"#;
|
2022-08-31 22:32:56 +02:00
|
|
|
|
2022-09-04 17:36:42 +02:00
|
|
|
let actual = nu!(cwd: dirs.test(), inp);
|
2022-08-31 22:32:56 +02:00
|
|
|
|
2022-09-04 17:36:42 +02:00
|
|
|
assert_eq!(actual.out, "spam");
|
2022-08-31 22:32:56 +02:00
|
|
|
})
|
|
|
|
}
|
2022-09-04 19:32:06 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_preserve_hidden_env_1() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"let-env FOO = 'foo'"#,
|
|
|
|
r#"overlay new eggs"#,
|
|
|
|
r#"let-env FOO = 'bar'"#,
|
|
|
|
r#"hide-env FOO"#,
|
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_preserve_hidden_env_2() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"let-env FOO = 'foo'"#,
|
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"overlay new eggs"#,
|
|
|
|
r#"let-env FOO = 'bar'"#,
|
|
|
|
r#"hide-env FOO"#,
|
|
|
|
r#"overlay hide eggs"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_reset_hidden_env() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"let-env FOO = 'foo'"#,
|
|
|
|
r#"overlay new eggs"#,
|
|
|
|
r#"let-env FOO = 'bar'"#,
|
|
|
|
r#"hide-env FOO"#,
|
|
|
|
r#"module eggs { export-env { let-env FOO = 'bar' } }"#,
|
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"$env.FOO"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "bar");
|
|
|
|
assert_eq!(actual_repl.out, "bar");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[ignore = "TODO: For this to work, we'd need to make predecls respect overlays"]
|
|
|
|
#[test]
|
|
|
|
fn overlay_preserve_hidden_decl() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"def foo [] { 'foo' }"#,
|
|
|
|
r#"overlay new eggs"#,
|
|
|
|
r#"def foo [] { 'bar' }"#,
|
|
|
|
r#"hide foo"#,
|
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
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 08:44:05 +01:00
|
|
|
#[ignore = "TODO: For this to work, we'd need to make predecls respect overlays"]
|
2022-09-04 19:32:06 +02:00
|
|
|
#[test]
|
|
|
|
fn overlay_preserve_hidden_alias() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias foo = echo 'foo'"#,
|
2022-09-04 19:32:06 +02:00
|
|
|
r#"overlay new eggs"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias foo = echo 'bar'"#,
|
2022-09-04 19:32:06 +02:00
|
|
|
r#"hide foo"#,
|
|
|
|
r#"overlay use eggs"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
2022-09-16 09:27:12 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_trim_single_quote() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"overlay use 'spam'"#,
|
|
|
|
r#"overlay list | last "#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_trim_single_quote_hide() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"overlay use 'spam'"#,
|
|
|
|
r#"overlay hide spam "#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "foo");
|
2022-09-16 09:27:12 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_trim_double_quote() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"overlay use "spam" "#,
|
|
|
|
r#"overlay list | last "#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_trim_double_quote_hide() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { "foo" } }"#,
|
|
|
|
r#"overlay use "spam" "#,
|
|
|
|
r#"overlay hide spam "#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(!actual.err.is_empty());
|
|
|
|
#[cfg(windows)]
|
2023-01-15 03:03:32 +01:00
|
|
|
assert_ne!(actual_repl.out, "foo");
|
2022-09-16 09:27:12 +02:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
assert!(!actual_repl.err.is_empty());
|
|
|
|
}
|
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 23:45:24 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_and_restore_older_env_vars() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam {
|
|
|
|
export-env {
|
|
|
|
let old_baz = $env.BAZ;
|
|
|
|
let-env BAZ = $old_baz + 'baz'
|
|
|
|
}
|
|
|
|
}"#,
|
|
|
|
r#"let-env BAZ = 'baz'"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"overlay hide spam"#,
|
|
|
|
r#"let-env BAZ = 'new-baz'"#,
|
|
|
|
r#"overlay use --reload spam"#,
|
|
|
|
r#"$env.BAZ"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "new-bazbaz");
|
|
|
|
assert_eq!(actual_repl.out, "new-bazbaz");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_and_reload() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam {
|
|
|
|
export def foo [] { 'foo' };
|
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 08:44:05 +01:00
|
|
|
export alias fooalias = echo 'foo';
|
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 23:45:24 +01:00
|
|
|
export-env {
|
|
|
|
let-env FOO = 'foo'
|
|
|
|
}
|
|
|
|
}"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"def foo [] { 'newfoo' }"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias fooalias = echo 'newfoo'"#,
|
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 23:45:24 +01:00
|
|
|
r#"let-env FOO = 'newfoo'"#,
|
|
|
|
r#"overlay use --reload spam"#,
|
|
|
|
r#"$'(foo)(fooalias)($env.FOO)'"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foofoofoo");
|
|
|
|
assert_eq!(actual_repl.out, "foofoofoo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_and_reolad_keep_custom() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"def foo [] { 'newfoo' }"#,
|
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 08:44:05 +01:00
|
|
|
r#"alias fooalias = echo 'newfoo'"#,
|
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 23:45:24 +01:00
|
|
|
r#"let-env FOO = 'newfoo'"#,
|
|
|
|
r#"overlay use --reload spam"#,
|
|
|
|
r#"$'(foo)(fooalias)($env.FOO)'"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "newfoonewfoonewfoo");
|
|
|
|
assert_eq!(actual_repl.out, "newfoonewfoonewfoo");
|
|
|
|
}
|
2023-01-22 20:34:15 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_main() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def main [] { "spam" } }"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"spam"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: ".", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_main_prefix() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def main [] { "spam" } }"#,
|
|
|
|
r#"overlay use spam --prefix"#,
|
|
|
|
r#"spam"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: ".", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_main_def_env() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def-env main [] { let-env SPAM = "spam" } }"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"spam"#,
|
|
|
|
r#"$env.SPAM"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: ".", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "spam");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_main_def_known_external() {
|
|
|
|
// note: requires installed cargo
|
|
|
|
let inp = &[
|
|
|
|
r#"module cargo { export extern main [] }"#,
|
|
|
|
r#"overlay use cargo"#,
|
|
|
|
r#"cargo --version"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: ".", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert!(actual.out.contains("cargo"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overlay_use_main_not_exported() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { def main [] { "spam" } }"#,
|
|
|
|
r#"overlay use spam"#,
|
|
|
|
r#"spam"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: ".", pipeline(&inp.join("; ")));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("external_command"));
|
|
|
|
}
|
2023-03-10 22:20:31 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_overlay_hide() {
|
|
|
|
let inp = &[
|
|
|
|
r#"overlay new spam"#,
|
|
|
|
r#"def foo [] { 'foo' }"#,
|
|
|
|
r#"overlay new eggs"#,
|
|
|
|
r#"alias oh = overlay hide"#,
|
|
|
|
r#"oh spam"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert!(actual.err.contains("external_command"));
|
|
|
|
assert!(actual_repl.err.contains("external_command"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_overlay_use() {
|
|
|
|
let inp = &[
|
|
|
|
r#"module spam { export def foo [] { 'foo' } }"#,
|
|
|
|
r#"alias ou = overlay use"#,
|
|
|
|
r#"ou spam"#,
|
|
|
|
r#"foo"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "foo");
|
|
|
|
assert_eq!(actual_repl.out, "foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn alias_overlay_new() {
|
|
|
|
let inp = &[
|
|
|
|
r#"alias on = overlay new"#,
|
|
|
|
r#"on spam"#,
|
|
|
|
r#"on eggs"#,
|
|
|
|
r#"overlay list | last"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
let actual = nu!(cwd: "tests/overlays", pipeline(&inp.join("; ")));
|
|
|
|
let actual_repl = nu!(cwd: "tests/overlays", nu_repl_code(inp));
|
|
|
|
|
|
|
|
assert_eq!(actual.out, "eggs");
|
|
|
|
assert_eq!(actual_repl.out, "eggs");
|
|
|
|
}
|