mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-14 14:12:31 +00:00
Create closure to do sorting.
This commit is contained in:
parent
2603261a4a
commit
874d07f89d
2 changed files with 75 additions and 122 deletions
|
@ -118,7 +118,8 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort(&self, metas: &mut Vec<Meta>) {
|
fn sort(&self, metas: &mut Vec<Meta>) {
|
||||||
metas.sort_unstable_by(|a, b| sort::by_meta(a, b, &self.flags));
|
let sorter = sort::create_sorter(&self.flags);
|
||||||
|
metas.sort_unstable_by(|a, b| (sorter)(a, b));
|
||||||
|
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
if let Some(ref mut content) = meta.content {
|
if let Some(ref mut content) = meta.content {
|
||||||
|
|
194
src/sort.rs
194
src/sort.rs
|
@ -2,126 +2,65 @@ use crate::flags::{DirOrderFlag, Flags, SortFlag, SortOrder};
|
||||||
use crate::meta::{FileType, Meta};
|
use crate::meta::{FileType, Meta};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
pub fn by_meta(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
pub type Sorter = Box<dyn Fn(&Meta, &Meta) -> Ordering>;
|
||||||
match flags.sort_by {
|
|
||||||
SortFlag::Name => match flags.directory_order {
|
pub fn create_sorter(flags: &Flags) -> Sorter {
|
||||||
DirOrderFlag::First => by_name_with_dirs_first(a, b, &flags),
|
let mut sorters: Vec<(SortOrder, Sorter)> = vec![];
|
||||||
DirOrderFlag::None => by_name(a, b, &flags),
|
match flags.directory_order {
|
||||||
DirOrderFlag::Last => by_name_with_files_first(a, b, &flags),
|
DirOrderFlag::First => {
|
||||||
},
|
sorters.push((SortOrder::Default, Box::new(with_dirs_first)));
|
||||||
SortFlag::Size => match flags.directory_order {
|
}
|
||||||
DirOrderFlag::First => by_size_with_dirs_first(a, b, &flags),
|
DirOrderFlag::Last => {
|
||||||
DirOrderFlag::None => by_size(a, b, &flags),
|
sorters.push((SortOrder::Reverse, Box::new(with_dirs_first)));
|
||||||
DirOrderFlag::Last => by_size_with_files_first(a, b, &flags),
|
}
|
||||||
},
|
DirOrderFlag::None => {}
|
||||||
SortFlag::Time => match flags.directory_order {
|
};
|
||||||
DirOrderFlag::First => by_date_with_dirs_first(a, b, &flags),
|
let other_sort = match flags.sort_by {
|
||||||
DirOrderFlag::None => by_date(a, b, &flags),
|
SortFlag::Name => by_name,
|
||||||
DirOrderFlag::Last => by_date_with_files_first(a, b, &flags),
|
SortFlag::Size => by_size,
|
||||||
},
|
SortFlag::Time => by_date,
|
||||||
}
|
};
|
||||||
|
sorters.push((flags.sort_order, Box::new(other_sort)));
|
||||||
|
|
||||||
|
Box::new(move |a, b| {
|
||||||
|
for (direction, sorter) in sorters.iter() {
|
||||||
|
match (sorter)(a, b) {
|
||||||
|
Ordering::Equal => continue,
|
||||||
|
ordering => {
|
||||||
|
return match direction {
|
||||||
|
SortOrder::Reverse => ordering.reverse(),
|
||||||
|
SortOrder::Default => ordering,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ordering::Equal
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn by_size(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
fn with_dirs_first(a: &Meta, b: &Meta) -> Ordering {
|
||||||
if flags.sort_order == SortOrder::Default {
|
|
||||||
b.size.get_bytes().cmp(&a.size.get_bytes())
|
|
||||||
} else {
|
|
||||||
a.size.get_bytes().cmp(&b.size.get_bytes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn by_size_with_dirs_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
|
||||||
match (a.file_type, b.file_type) {
|
match (a.file_type, b.file_type) {
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_size(a, b, &flags),
|
(FileType::Directory { .. }, FileType::Directory { .. }) => Ordering::Equal,
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_size(a, b, &flags),
|
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => Ordering::Equal,
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_size(a, b, &flags),
|
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => Ordering::Equal,
|
||||||
(FileType::Directory { .. }, _) => Ordering::Less,
|
(FileType::Directory { .. }, _) => Ordering::Less,
|
||||||
(_, FileType::Directory { .. }) => Ordering::Greater,
|
(_, FileType::Directory { .. }) => Ordering::Greater,
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Less,
|
(FileType::SymLink { is_dir: true }, _) => Ordering::Less,
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Greater,
|
(_, FileType::SymLink { is_dir: true }) => Ordering::Greater,
|
||||||
_ => by_size(a, b, &flags),
|
_ => Ordering::Equal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn by_size_with_files_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
fn by_size(a: &Meta, b: &Meta) -> Ordering {
|
||||||
match (a.file_type, b.file_type) {
|
b.size.get_bytes().cmp(&a.size.get_bytes())
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_size(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_size(a, b, &flags),
|
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_size(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::Directory { .. }) => Ordering::Less,
|
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Less,
|
|
||||||
_ => by_size(a, b, &flags),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn by_name(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
fn by_name(a: &Meta, b: &Meta) -> Ordering {
|
||||||
if flags.sort_order == SortOrder::Default {
|
a.name.cmp(&b.name)
|
||||||
a.name.cmp(&b.name)
|
|
||||||
} else {
|
|
||||||
b.name.cmp(&a.name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn by_name_with_dirs_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
fn by_date(a: &Meta, b: &Meta) -> Ordering {
|
||||||
match (a.file_type, b.file_type) {
|
b.date.cmp(&a.date).then(a.name.cmp(&b.name))
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_name(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_name(a, b, &flags),
|
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_name(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, _) => Ordering::Less,
|
|
||||||
(_, FileType::Directory { .. }) => Ordering::Greater,
|
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Less,
|
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Greater,
|
|
||||||
_ => by_name(a, b, &flags),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn by_name_with_files_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
|
||||||
match (a.file_type, b.file_type) {
|
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_name(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_name(a, b, &flags),
|
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_name(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::Directory { .. }) => Ordering::Less,
|
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Less,
|
|
||||||
_ => by_name(a, b, &flags),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn by_date(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
|
||||||
if flags.sort_order == SortOrder::Default {
|
|
||||||
b.date.cmp(&a.date).then(a.name.cmp(&b.name))
|
|
||||||
} else {
|
|
||||||
a.date.cmp(&b.date).then(b.name.cmp(&a.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn by_date_with_dirs_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
|
||||||
match (a.file_type, b.file_type) {
|
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_date(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_date(a, b, &flags),
|
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_date(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, _) => Ordering::Less,
|
|
||||||
(_, FileType::Directory { .. }) => Ordering::Greater,
|
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Less,
|
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Greater,
|
|
||||||
_ => by_date(a, b, &flags),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn by_date_with_files_first(a: &Meta, b: &Meta, flags: &Flags) -> Ordering {
|
|
||||||
match (a.file_type, b.file_type) {
|
|
||||||
(FileType::Directory { .. }, FileType::Directory { .. }) => by_date(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, FileType::SymLink { is_dir: true }) => by_date(a, b, &flags),
|
|
||||||
(FileType::SymLink { is_dir: true }, FileType::Directory { .. }) => by_date(a, b, &flags),
|
|
||||||
(FileType::Directory { .. }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::Directory { .. }) => Ordering::Less,
|
|
||||||
(FileType::SymLink { is_dir: true }, _) => Ordering::Greater,
|
|
||||||
(_, FileType::SymLink { is_dir: true }) => Ordering::Less,
|
|
||||||
_ => by_date(a, b, &flags),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -133,7 +72,7 @@ mod tests {
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sort_by_meta_by_name_with_dirs_first() {
|
fn test_sort_create_sorter_by_name_with_dirs_first() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
|
@ -150,15 +89,18 @@ mod tests {
|
||||||
flags.directory_order = DirOrderFlag::First;
|
flags.directory_order = DirOrderFlag::First;
|
||||||
|
|
||||||
// Sort with the dirs first
|
// Sort with the dirs first
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Greater);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Greater);
|
||||||
|
|
||||||
// Sort with the dirs first (the dirs stay first)
|
// Sort with the dirs first (the dirs stay first)
|
||||||
flags.sort_order = SortOrder::Reverse;
|
flags.sort_order = SortOrder::Reverse;
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Greater);
|
|
||||||
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Greater);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sort_by_meta_by_name_with_files_first() {
|
fn test_sort_create_sorter_by_name_with_files_first() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
|
@ -175,14 +117,16 @@ mod tests {
|
||||||
flags.directory_order = DirOrderFlag::Last;
|
flags.directory_order = DirOrderFlag::Last;
|
||||||
|
|
||||||
// Sort with file first
|
// Sort with file first
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Less);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Less);
|
||||||
|
|
||||||
// Sort with file first reversed (thie files stay first)
|
// Sort with file first reversed (thie files stay first)
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Less);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Less);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sort_by_meta_by_name_unordered() {
|
fn test_sort_create_sorter_by_name_unordered() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
|
@ -199,15 +143,18 @@ mod tests {
|
||||||
flags.directory_order = DirOrderFlag::None;
|
flags.directory_order = DirOrderFlag::None;
|
||||||
|
|
||||||
// Sort by name unordered
|
// Sort by name unordered
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Less);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Less);
|
||||||
|
|
||||||
// Sort by name unordered
|
// Sort by name unordered
|
||||||
flags.sort_order = SortOrder::Reverse;
|
flags.sort_order = SortOrder::Reverse;
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Greater);
|
|
||||||
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Greater);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sort_by_meta_by_name_unordered_2() {
|
fn test_sort_create_sorter_by_name_unordered_2() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
|
@ -224,15 +171,18 @@ mod tests {
|
||||||
flags.directory_order = DirOrderFlag::None;
|
flags.directory_order = DirOrderFlag::None;
|
||||||
|
|
||||||
// Sort by name unordered
|
// Sort by name unordered
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Greater);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Greater);
|
||||||
|
|
||||||
// Sort by name unordered reversed
|
// Sort by name unordered reversed
|
||||||
flags.sort_order = SortOrder::Reverse;
|
flags.sort_order = SortOrder::Reverse;
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Less);
|
|
||||||
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Less);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sort_by_meta_by_time() {
|
fn test_sort_create_sorter_by_time() {
|
||||||
let tmp_dir = tempdir().expect("failed to create temp dir");
|
let tmp_dir = tempdir().expect("failed to create temp dir");
|
||||||
|
|
||||||
// Create the file;
|
// Create the file;
|
||||||
|
@ -270,10 +220,12 @@ mod tests {
|
||||||
flags.sort_by = SortFlag::Time;
|
flags.sort_by = SortFlag::Time;
|
||||||
|
|
||||||
// Sort by time
|
// Sort by time
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Less);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Less);
|
||||||
|
|
||||||
// Sort by time reversed
|
// Sort by time reversed
|
||||||
flags.sort_order = SortOrder::Reverse;
|
flags.sort_order = SortOrder::Reverse;
|
||||||
assert_eq!(by_meta(&meta_a, &meta_z, &flags), Ordering::Greater);
|
let sorter = create_sorter(&flags);
|
||||||
|
assert_eq!((sorter)(&meta_a, &meta_z), Ordering::Greater);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue