mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-13 13:42:34 +00:00
sort: ✨ add version sort
fix https://github.com/Peltoche/lsd/issues/394
This commit is contained in:
parent
08a55f90d3
commit
16f1b1ce7c
7 changed files with 103 additions and 4 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -201,6 +201,11 @@ dependencies = [
|
|||
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "human-sort"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.14"
|
||||
|
@ -264,6 +269,7 @@ dependencies = [
|
|||
"chrono-humanize 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"globset 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"human-sort 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lscolors 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"predicates 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -609,6 +615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum globset 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120"
|
||||
"checksum globwalk 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d9db17aec586697a93219b19726b5b68307eba92898c34b170857343fe67c99d"
|
||||
"checksum hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
|
||||
"checksum human-sort 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "140a09c9305e6d5e557e2ed7cbc68e05765a7d4213975b87cb04920689cc6219"
|
||||
"checksum ignore 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf60d063dbe6b75388eec66cfc07781167ae3d34a09e0c433e6c5de0511f7fb"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
|
|
@ -31,6 +31,7 @@ unicode-width = "0.1.*"
|
|||
lscolors = "0.7"
|
||||
wild = "2.0.*"
|
||||
globset = "0.4.*"
|
||||
human-sort = "0.2.2"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
users = "0.10.*"
|
||||
|
|
12
src/app.rs
12
src/app.rs
|
@ -146,6 +146,7 @@ pub fn build() -> App<'static, 'static> {
|
|||
.long("timesort")
|
||||
.overrides_with("sizesort")
|
||||
.overrides_with("extensionsort")
|
||||
.overrides_with("versionsort")
|
||||
.multiple(true)
|
||||
.help("Sort by time modified"),
|
||||
)
|
||||
|
@ -155,6 +156,7 @@ pub fn build() -> App<'static, 'static> {
|
|||
.long("sizesort")
|
||||
.overrides_with("timesort")
|
||||
.overrides_with("extensionsort")
|
||||
.overrides_with("versionsort")
|
||||
.multiple(true)
|
||||
.help("Sort by size"),
|
||||
)
|
||||
|
@ -164,9 +166,19 @@ pub fn build() -> App<'static, 'static> {
|
|||
.long("extensionsort")
|
||||
.overrides_with("sizesort")
|
||||
.overrides_with("timesort")
|
||||
.overrides_with("versionsort")
|
||||
.multiple(true)
|
||||
.help("Sort by file extension"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("versionsort")
|
||||
.short("v")
|
||||
.multiple(true)
|
||||
.overrides_with("timesort")
|
||||
.overrides_with("sizesort")
|
||||
.overrides_with("extensionsort")
|
||||
.help("Natural sort of (version) numbers within text"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("reverse")
|
||||
.short("r")
|
||||
|
|
|
@ -60,6 +60,8 @@ impl Flags {
|
|||
SortFlag::Size
|
||||
} else if matches.is_present("extensionsort") {
|
||||
SortFlag::Extension
|
||||
} else if matches.is_present("versionsort") {
|
||||
SortFlag::Version
|
||||
} else {
|
||||
SortFlag::Name
|
||||
};
|
||||
|
@ -308,6 +310,7 @@ pub enum SortFlag {
|
|||
Name,
|
||||
Time,
|
||||
Size,
|
||||
Version,
|
||||
Extension,
|
||||
}
|
||||
|
||||
|
|
|
@ -81,10 +81,7 @@ impl FileType {
|
|||
}
|
||||
|
||||
pub fn is_dirlike(self) -> bool {
|
||||
match self {
|
||||
FileType::Directory { .. } | FileType::SymLink { is_dir: true } => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, FileType::Directory { .. } | FileType::SymLink { is_dir: true })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
32
src/sort.rs
32
src/sort.rs
|
@ -1,5 +1,6 @@
|
|||
use crate::flags::{DirOrderFlag, Flags, SortFlag, SortOrder};
|
||||
use crate::meta::Meta;
|
||||
use human_sort::compare;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
pub type SortFn = fn(&Meta, &Meta) -> Ordering;
|
||||
|
@ -19,6 +20,7 @@ pub fn assemble_sorters(flags: &Flags) -> Vec<(SortOrder, SortFn)> {
|
|||
SortFlag::Name => by_name,
|
||||
SortFlag::Size => by_size,
|
||||
SortFlag::Time => by_date,
|
||||
SortFlag::Version => by_version,
|
||||
SortFlag::Extension => by_extension,
|
||||
};
|
||||
sorters.push((flags.sort_order, other_sort));
|
||||
|
@ -56,6 +58,10 @@ fn by_date(a: &Meta, b: &Meta) -> Ordering {
|
|||
b.date.cmp(&a.date).then(a.name.cmp(&b.name))
|
||||
}
|
||||
|
||||
fn by_version(a: &Meta, b: &Meta) -> Ordering {
|
||||
compare(&a.name.name, &b.name.name)
|
||||
}
|
||||
|
||||
fn by_extension(a: &Meta, b: &Meta) -> Ordering {
|
||||
a.name.extension().cmp(&b.name.extension())
|
||||
}
|
||||
|
@ -263,4 +269,30 @@ mod tests {
|
|||
let sorter = assemble_sorters(&flags);
|
||||
assert_eq!(by_meta(&sorter, &meta_a, &meta_t), Ordering::Less);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sort_assemble_sorters_by_version() {
|
||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||
|
||||
let path_a = tmp_dir.path().join("2");
|
||||
File::create(&path_a).expect("failed to create file");
|
||||
let meta_a = Meta::from_path(&path_a, false).expect("failed to get meta");
|
||||
|
||||
let path_b = tmp_dir.path().join("11");
|
||||
File::create(&path_b).expect("failed to create file");
|
||||
let meta_b = Meta::from_path(&path_b, false).expect("failed to get meta");
|
||||
|
||||
let path_c = tmp_dir.path().join("12");
|
||||
File::create(&path_c).expect("failed to create file");
|
||||
let meta_c = Meta::from_path(&path_c, false).expect("failed to get meta");
|
||||
|
||||
let mut flags = Flags::default();
|
||||
flags.sort_by = SortFlag::Version;
|
||||
|
||||
let sorter = assemble_sorters(&flags);
|
||||
assert_eq!(by_meta(&sorter, &meta_b, &meta_a), Ordering::Greater);
|
||||
|
||||
let sorter = assemble_sorters(&flags);
|
||||
assert_eq!(by_meta(&sorter, &meta_b, &meta_c), Ordering::Less);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,6 +260,53 @@ fn test_show_folder_of_symlink_for_long_multi() {
|
|||
.stdout(predicate::str::contains("link/:"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_sort() {
|
||||
let dir = tempdir();
|
||||
dir.child("0.3.7").touch().unwrap();
|
||||
dir.child("0.11.5").touch().unwrap();
|
||||
dir.child("11a").touch().unwrap();
|
||||
dir.child("0.2").touch().unwrap();
|
||||
dir.child("0.11").touch().unwrap();
|
||||
dir.child("1").touch().unwrap();
|
||||
dir.child("11").touch().unwrap();
|
||||
dir.child("2").touch().unwrap();
|
||||
dir.child("22").touch().unwrap();
|
||||
cmd().arg("-v").arg(dir.path()).assert().stdout(
|
||||
predicate::str::is_match("0.2\n0.3.7\n0.11\n0.11.5\n1\n2\n11\n11a\n22\n$").unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_sort_overwrite_by_timesort() {
|
||||
let dir = tempdir();
|
||||
dir.child("2").touch().unwrap();
|
||||
dir.child("11").touch().unwrap();
|
||||
cmd()
|
||||
.arg("-v")
|
||||
.arg("-t")
|
||||
.arg(dir.path())
|
||||
.assert()
|
||||
.stdout(predicate::str::is_match("11\n2\n$").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_sort_overwrite_by_sizesort() {
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
let dir = tempdir();
|
||||
dir.child("2").touch().unwrap();
|
||||
let larger = dir.path().join("11");
|
||||
let mut larger_file = File::create(larger).unwrap();
|
||||
writeln!(larger_file, "this is larger").unwrap();
|
||||
cmd()
|
||||
.arg("-v")
|
||||
.arg("-S")
|
||||
.arg(dir.path())
|
||||
.assert()
|
||||
.stdout(predicate::str::is_match("11\n2\n$").unwrap());
|
||||
}
|
||||
|
||||
fn cmd() -> Command {
|
||||
Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue