This commit is contained in:
Nguyen Duc Toan 2023-09-16 21:50:22 +07:00
commit b85a3a1a32
6 changed files with 49 additions and 17 deletions

View file

@ -151,6 +151,7 @@ impl Executor {
let b = cx.manager.active_mut().set_sorter(FilesSorter {
by: SortBy::try_from(exec.args.get(0).cloned().unwrap_or_default())
.unwrap_or_default(),
sensitive: exec.named.contains_key("sensitive"),
reverse: exec.named.contains_key("reverse"),
dir_first: exec.named.contains_key("dir_first"),
});

View file

@ -14,6 +14,11 @@
- `"natural"`: Sort naturally, e.g. `1.md` < `2.md` < `10.md`
- `"size"`: Sort by file size
- sort_sensitive: Sort case-sensitively
- `true`: Case-sensitive
- `false`: Case-insensitive
- sort_reverse: Display files in reverse order
- `true`: Reverse order
@ -81,8 +86,8 @@ rules = [
Available rule parameters are as follows:
- name: Glob expression for matching the file name
- mime: Glob expression for matching the MIME type
- name: Glob expression for matching the file name. Case insensitive by default, add `\s` to the beginning to make it sensitive.
- mime: Glob expression for matching the MIME type. Case insensitive by default, add `\s` to the beginning to make it sensitive.
- use: Opener name corresponding to the names in the opener section.
## tasks

View file

@ -1,6 +1,7 @@
[manager]
layout = [ 1, 4, 3 ]
sort_by = "modified"
sort_sensitive = false
sort_reverse = true
sort_dir_first = true
show_hidden = false

View file

@ -9,6 +9,7 @@ pub struct Manager {
// Sorting
pub sort_by: SortBy,
pub sort_sensitive: bool,
pub sort_reverse: bool,
pub sort_dir_first: bool,

View file

@ -1,18 +1,26 @@
use std::path::Path;
use glob::MatchOptions;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[serde(try_from = "String")]
pub struct Pattern {
inner: glob::Pattern,
sensitive: bool,
is_folder: bool,
full_path: bool,
}
impl Pattern {
#[inline]
pub fn matches(&self, str: impl AsRef<str>) -> bool { self.inner.matches(str.as_ref()) }
pub fn matches(&self, str: impl AsRef<str>) -> bool {
self.inner.matches_with(str.as_ref(), MatchOptions {
case_sensitive: self.sensitive,
require_literal_separator: false,
require_literal_leading_dot: false,
})
}
#[inline]
pub fn match_path(&self, path: impl AsRef<Path>, is_folder: Option<bool>) -> bool {
@ -20,7 +28,7 @@ impl Pattern {
let s = if self.full_path {
path.to_str()
} else {
path.file_name().and_then(|n| n.to_str()).or(path.to_str())
path.file_name().and_then(|n| n.to_str()).or_else(|| path.to_str())
};
is_folder.map_or(true, |f| f == self.is_folder) && s.map_or(false, |s| self.matches(s))
}
@ -30,11 +38,13 @@ impl TryFrom<&str> for Pattern {
type Error = anyhow::Error;
fn try_from(s: &str) -> Result<Self, Self::Error> {
let new = s.trim_end_matches('/');
let a = s.trim_start_matches("\\s");
let b = a.trim_end_matches('/');
Ok(Self {
inner: glob::Pattern::new(new)?,
is_folder: new.len() < s.len(),
full_path: new.contains('/'),
inner: glob::Pattern::new(b)?,
sensitive: a.len() < s.len(),
is_folder: b.len() < a.len(),
full_path: b.contains('/'),
})
}
}

View file

@ -1,4 +1,4 @@
use std::{cmp::Ordering, collections::BTreeMap, mem};
use std::{cmp::Ordering, collections::BTreeMap, mem, ops::Deref};
use config::{manager::SortBy, MANAGER};
use shared::Url;
@ -8,6 +8,7 @@ use super::File;
#[derive(Clone, Copy, PartialEq)]
pub struct FilesSorter {
pub by: SortBy,
pub sensitive: bool,
pub reverse: bool,
pub dir_first: bool,
}
@ -16,6 +17,7 @@ impl Default for FilesSorter {
fn default() -> Self {
Self {
by: MANAGER.sort_by,
sensitive: MANAGER.sort_sensitive,
reverse: MANAGER.sort_reverse,
dir_first: MANAGER.sort_dir_first,
}
@ -29,9 +31,17 @@ impl FilesSorter {
}
match self.by {
SortBy::Alphabetical => {
items.sort_unstable_by(|a, b| self.cmp(&*a.url, &*b.url, self.promote(a, b)))
}
SortBy::Alphabetical => items.sort_unstable_by(|a, b| {
if self.sensitive {
return self.cmp(&*a.url, &*b.url, self.promote(a, b));
}
self.cmp(
a.url.as_os_str().to_ascii_lowercase(),
b.url.as_os_str().to_ascii_lowercase(),
self.promote(a, b),
)
}),
SortBy::Created => items.sort_unstable_by(|a, b| {
if let (Ok(aa), Ok(bb)) = (a.meta.created(), b.meta.created()) {
return self.cmp(aa, bb, self.promote(a, b));
@ -65,12 +75,16 @@ impl FilesSorter {
indices.sort_unstable_by(|&a, &b| {
let promote = self.promote(entities[a].1, entities[b].1);
if promote != Ordering::Equal {
promote
} else if self.reverse {
natord::compare(&entities[b].0, &entities[a].0)
} else {
natord::compare(&entities[a].0, &entities[b].0)
return promote;
}
let ordering = if self.sensitive {
natord::compare(&entities[a].0, &entities[b].0)
} else {
natord::compare_ignore_case(&entities[a].0, &entities[b].0)
};
if self.reverse { ordering.reverse() } else { ordering }
});
let dummy = File {