feat: prepare for natural sort

This commit is contained in:
Anton Simonov 2023-08-23 08:48:10 +03:00 committed by sxyazi
parent a7a085e41c
commit c6eb52b457
No known key found for this signature in database
3 changed files with 40 additions and 21 deletions

View file

@ -11,6 +11,7 @@
- `"alphabetical"`: Sort alphabetically - `"alphabetical"`: Sort alphabetically
- `"created"`: Sort by creation time - `"created"`: Sort by creation time
- `"modified"`: Sort by last modified time - `"modified"`: Sort by last modified time
- `"natural"`: Sort naturally
- `"size"`: Sort by file size - `"size"`: Sort by file size
- sort_reverse: Display files in reverse order - sort_reverse: Display files in reverse order

View file

@ -8,6 +8,7 @@ pub enum SortBy {
Alphabetical, Alphabetical,
Created, Created,
Modified, Modified,
Natural,
Size, Size,
} }
@ -19,6 +20,7 @@ impl TryFrom<String> for SortBy {
"alphabetical" => Self::Alphabetical, "alphabetical" => Self::Alphabetical,
"created" => Self::Created, "created" => Self::Created,
"modified" => Self::Modified, "modified" => Self::Modified,
"natural" => Self::Natural,
"size" => Self::Size, "size" => Self::Size,
_ => bail!("invalid sort_by value: {s}"), _ => bail!("invalid sort_by value: {s}"),
}) })

View file

@ -1,4 +1,9 @@
use std::{cmp::Ordering, collections::BTreeMap, ops::{Deref, DerefMut}, path::{Path, PathBuf}}; use std::{
cmp::Ordering,
collections::BTreeMap,
ops::{Deref, DerefMut},
path::{Path, PathBuf},
};
use anyhow::Result; use anyhow::Result;
use config::{manager::SortBy, MANAGER}; use config::{manager::SortBy, MANAGER};
@ -15,11 +20,7 @@ pub struct Files {
impl Default for Files { impl Default for Files {
fn default() -> Self { fn default() -> Self {
Self { Self { items: Default::default(), sort: Default::default(), show_hidden: MANAGER.show_hidden }
items: Default::default(),
sort: Default::default(),
show_hidden: MANAGER.show_hidden,
}
} }
} }
@ -122,13 +123,21 @@ impl Files {
if promote != Ordering::Equal { if promote != Ordering::Equal {
promote promote
} else { } else {
if reverse { b.cmp(&a) } else { a.cmp(&b) } if reverse {
b.cmp(&a)
} else {
a.cmp(&b)
}
} }
} }
#[inline] #[inline]
fn promote(a: &File, b: &File, dir_first: bool) -> Ordering { fn promote(a: &File, b: &File, dir_first: bool) -> Ordering {
if dir_first { b.meta.is_dir().cmp(&a.meta.is_dir()) } else { Ordering::Equal } if dir_first {
b.meta.is_dir().cmp(&a.meta.is_dir())
} else {
Ordering::Equal
}
} }
let reverse = self.sort.reverse; let reverse = self.sort.reverse;
@ -149,6 +158,9 @@ impl Files {
} }
Ordering::Equal Ordering::Equal
}), }),
SortBy::Natural => {
self.items.sort_by(|_, a, _, b| cmp(&a.path, &b.path, reverse, promote(a, b, dir_first)))
}
SortBy::Size => self.items.sort_by(|_, a, _, b| { SortBy::Size => self.items.sort_by(|_, a, _, b| {
cmp(a.length.unwrap_or(0), b.length.unwrap_or(0), reverse, promote(a, b, dir_first)) cmp(a.length.unwrap_or(0), b.length.unwrap_or(0), reverse, promote(a, b, dir_first))
}), }),
@ -160,11 +172,15 @@ impl Files {
impl Deref for Files { impl Deref for Files {
type Target = IndexMap<PathBuf, File>; type Target = IndexMap<PathBuf, File>;
fn deref(&self) -> &Self::Target { &self.items } fn deref(&self) -> &Self::Target {
&self.items
}
} }
impl DerefMut for Files { impl DerefMut for Files {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.items } fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.items
}
} }
#[derive(PartialEq)] #[derive(PartialEq)]
@ -176,11 +192,7 @@ pub struct FilesSort {
impl Default for FilesSort { impl Default for FilesSort {
fn default() -> Self { fn default() -> Self {
Self { Self { by: MANAGER.sort_by, reverse: MANAGER.sort_reverse, dir_first: MANAGER.sort_dir_first }
by: MANAGER.sort_by,
reverse: MANAGER.sort_reverse,
dir_first: MANAGER.sort_dir_first,
}
} }
} }
@ -205,8 +217,12 @@ impl FilesOp {
} }
#[inline] #[inline]
pub fn read_empty(path: &Path) -> Self { Self::Read(path.to_path_buf(), BTreeMap::new()) } pub fn read_empty(path: &Path) -> Self {
Self::Read(path.to_path_buf(), BTreeMap::new())
}
#[inline] #[inline]
pub fn search_empty(path: &Path) -> Self { Self::Search(path.to_path_buf(), BTreeMap::new()) } pub fn search_empty(path: &Path) -> Self {
Self::Search(path.to_path_buf(), BTreeMap::new())
}
} }