mirror of
https://github.com/nushell/nushell.git
synced 2025-08-18 14:52:12 +02:00
Path Command Enhancement Project (#2742)
* Add string argument support for path subcommands * Add --replace option to 'path extension' command * Add examples of replacing for path extension * Refactor path extension and its example * Add replacement functionality to path basename * Refactor path subcommands to support more args This adds a lot of redundancy to non-relevant subcommands such as type, exists or expand. * Add replace and num_levels options to path dirname * Rename num_levels option to num-levels * Remove commented code * Clean up path basename * Fix path dirname description * Add path filestem opts; Rename extension -> suffix * Add prefix option and examples to path filestem * Fix broken num-levels of path dirname * Fix failing example test of path filestem * Fix failing test of path extension * Formatting * Add Windows-specific path subcommand examples `path expand` is still broken but otherwise seems to fix all examples on Windows * Fix weird path expand on Windows Also disable example tests for path expand. Failed caconicalization (e.g., due to path not existing) returns the original path so the examples always fail. * Formatting * Return path datatype when appropriate * Do not append empty remainder to path dirname * Add tests for path subcommands * Formatting * Revisit path subcommand description strings * Apply clippy suggestions; Formatting * Remove problematic test checking '~' expansion Wouldn't run on minimal due to useing optional dependency. The test success was also deending on the presence of home dir on the testing machine which might not be completely robust. * Add missing newline to file
This commit is contained in:
@@ -34,6 +34,7 @@ mod mkdir;
|
||||
mod move_;
|
||||
mod open;
|
||||
mod parse;
|
||||
mod path;
|
||||
mod prepend;
|
||||
mod random;
|
||||
mod range;
|
||||
|
83
crates/nu-cli/tests/commands/path/basename.rs
Normal file
83
crates/nu-cli/tests/commands/path/basename.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
use super::join_path_sep;
|
||||
|
||||
#[test]
|
||||
fn returns_basename_of_empty_input() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ""
|
||||
| path basename
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_basename_of_empty_input() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ""
|
||||
| path basename -r newname.txt
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "newname.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_basename_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/file.txt/."
|
||||
| path basename
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "file.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_basename_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/file.txt/."
|
||||
| path basename -r viking.txt
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["some", "viking.txt"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_basename_of_path_ending_with_double_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/file.txt/.."
|
||||
| path basename
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_basename_of_path_ending_with_double_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/file.txt/.."
|
||||
| path basename -r eggs
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["some/file.txt/..", "eggs"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
137
crates/nu-cli/tests/commands/path/dirname.rs
Normal file
137
crates/nu-cli/tests/commands/path/dirname.rs
Normal file
@@ -0,0 +1,137 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
use super::join_path_sep;
|
||||
|
||||
#[test]
|
||||
fn returns_dirname_of_empty_input() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ""
|
||||
| path dirname
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_empty_input() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo ""
|
||||
| path dirname -r newdir
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "newdir");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_dirname_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/."
|
||||
| path dirname
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "some");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/."
|
||||
| path dirname -r eggs
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["eggs", "dir"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_dirname_of_path_ending_with_double_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/.."
|
||||
| path dirname
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "some/dir");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_path_with_double_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/.."
|
||||
| path dirname -r eggs
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["eggs", ".."]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_dirname_of_zero_levels() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/with/spam.txt"
|
||||
| path dirname -n 0
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "some/dir/with/spam.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_zero_levels_with_empty_string() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/with/spam.txt"
|
||||
| path dirname -n 0 -r ""
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_more_levels() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/with/spam.txt"
|
||||
| path dirname -r eggs -n 2
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["eggs", "with/spam.txt"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_dirname_of_way_too_many_levels() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "some/dir/with/spam.txt"
|
||||
| path dirname -r eggs -n 999
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["eggs", "some/dir/with/spam.txt"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
53
crates/nu-cli/tests/commands/path/exists.rs
Normal file
53
crates/nu-cli/tests/commands/path/exists.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use nu_test_support::fs::Stub::EmptyFile;
|
||||
use nu_test_support::nu;
|
||||
use nu_test_support::playground::Playground;
|
||||
|
||||
#[test]
|
||||
fn checks_if_existing_file_exists() {
|
||||
Playground::setup("path_exists_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![EmptyFile("spam.txt")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"echo spam.txt | path exists"
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "true");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_if_missing_file_exists() {
|
||||
Playground::setup("path_exists_2", |dirs, _| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"echo spam.txt | path exists"
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "false");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_if_dot_exists() {
|
||||
Playground::setup("path_exists_3", |dirs, _| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"echo '.' | path exists"
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "true");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_if_double_dot_exists() {
|
||||
Playground::setup("path_exists_4", |dirs, _| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"echo '..' | path exists"
|
||||
);
|
||||
|
||||
assert_eq!(actual.out, "true");
|
||||
})
|
||||
}
|
45
crates/nu-cli/tests/commands/path/expand.rs
Normal file
45
crates/nu-cli/tests/commands/path/expand.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use nu_test_support::fs::Stub::EmptyFile;
|
||||
use nu_test_support::playground::Playground;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
fn expands_path_with_dot() {
|
||||
Playground::setup("path_expand_1", |dirs, sandbox| {
|
||||
sandbox
|
||||
.within("menu")
|
||||
.with_files(vec![EmptyFile("spam.txt")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo "menu/./spam.txt"
|
||||
| path expand
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = dirs.test.join("menu").join("spam.txt");
|
||||
assert_eq!(PathBuf::from(actual.out), expected);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expands_path_with_double_dot() {
|
||||
Playground::setup("path_expand_2", |dirs, sandbox| {
|
||||
sandbox
|
||||
.within("menu")
|
||||
.with_files(vec![EmptyFile("spam.txt")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo "menu/../menu/spam.txt"
|
||||
| path expand
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = dirs.test.join("menu").join("spam.txt");
|
||||
assert_eq!(PathBuf::from(actual.out), expected);
|
||||
})
|
||||
}
|
37
crates/nu-cli/tests/commands/path/extension.rs
Normal file
37
crates/nu-cli/tests/commands/path/extension.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn returns_extension_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "bacon." | path extension
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_extension_with_dot_of_path_ending_with_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "bacon." | path extension -r .egg
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "bacon..egg");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_extension_of_empty_path() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "" | path extension -r egg
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
95
crates/nu-cli/tests/commands/path/filestem.rs
Normal file
95
crates/nu-cli/tests/commands/path/filestem.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
use super::join_path_sep;
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_of_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/eggs/."
|
||||
| path filestem
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "eggs");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_of_double_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/eggs/.."
|
||||
| path filestem
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_of_path_with_empty_prefix() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path filestem -p ""
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "spam");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_of_path_with_empty_suffix() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path filestem -s ""
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "spam.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_of_path_with_empty_prefix_and_suffix() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path filestem -p "" -s ""
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "spam.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_filestem_with_wrong_prefix_and_suffix() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path filestem -p "bacon" -s "eggs"
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "spam.txt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replaces_filestem_stripped_to_dot() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path filestem -p "spam" -s "txt" -r ".eggs."
|
||||
"#
|
||||
));
|
||||
|
||||
let expected = join_path_sep(&["menu", "spam.eggs.txt"]);
|
||||
assert_eq!(actual.out, expected);
|
||||
}
|
33
crates/nu-cli/tests/commands/path/mod.rs
Normal file
33
crates/nu-cli/tests/commands/path/mod.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
mod basename;
|
||||
mod dirname;
|
||||
mod exists;
|
||||
mod expand;
|
||||
mod extension;
|
||||
mod filestem;
|
||||
mod type_;
|
||||
|
||||
use std::path::MAIN_SEPARATOR;
|
||||
|
||||
/// Helper function that joins string literals with '/' or '\', based on host OS
|
||||
fn join_path_sep(pieces: &[&str]) -> String {
|
||||
let sep_string = String::from(MAIN_SEPARATOR);
|
||||
pieces.join(&sep_string)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn joins_path_on_windows() {
|
||||
let pieces = ["sausage", "bacon", "spam"];
|
||||
let actual = join_path_sep(&pieces);
|
||||
|
||||
assert_eq!(&actual, "sausage\\bacon\\spam");
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[test]
|
||||
fn joins_path_on_other_than_windows() {
|
||||
let pieces = ["sausage", "bacon", "spam"];
|
||||
let actual = join_path_sep(&pieces);
|
||||
|
||||
assert_eq!(&actual, "sausage/bacon/spam");
|
||||
}
|
54
crates/nu-cli/tests/commands/path/type_.rs
Normal file
54
crates/nu-cli/tests/commands/path/type_.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use nu_test_support::fs::Stub::EmptyFile;
|
||||
use nu_test_support::playground::Playground;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn returns_type_of_missing_file() {
|
||||
let actual = nu!(
|
||||
cwd: "tests", pipeline(
|
||||
r#"
|
||||
echo "spam.txt"
|
||||
| path type
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_type_of_existing_file() {
|
||||
Playground::setup("path_expand_1", |dirs, sandbox| {
|
||||
sandbox
|
||||
.within("menu")
|
||||
.with_files(vec![EmptyFile("spam.txt")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo "menu"
|
||||
| path type
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "Dir");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_type_of_existing_directory() {
|
||||
Playground::setup("path_expand_1", |dirs, sandbox| {
|
||||
sandbox
|
||||
.within("menu")
|
||||
.with_files(vec![EmptyFile("spam.txt")]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo "menu/spam.txt"
|
||||
| path type
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "File");
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user