feat: add sort_dir_first option (#49)

This commit is contained in:
Yifan Song 2023-08-12 23:08:39 +08:00 committed by GitHub
parent 9d937fe376
commit 1e3b17e58c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 23 deletions

View file

@ -126,9 +126,10 @@ impl Executor {
// Sorting
"sort" => {
let b = cx.manager.current_mut().files.set_sort(FilesSort {
by: SortBy::try_from(exec.args.get(0).cloned().unwrap_or_default())
by: SortBy::try_from(exec.args.get(0).cloned().unwrap_or_default())
.unwrap_or_default(),
reverse: exec.named.contains_key("reverse"),
reverse: exec.named.contains_key("reverse"),
dir_first: exec.named.contains_key("dir_first"),
});
cx.tasks.precache_size(&cx.manager.current().files);
b

View file

@ -14,6 +14,11 @@
- `true`: Reverse order
- `false`: Normal order
- sort_dir_first: Display directories first
- `true`: Directories first
- `false`: Respects `sort_by` and `sort_reverse` only
- show_hidden: Show hidden files
- `true`: Show

View file

@ -1,7 +1,8 @@
[manager]
sort_by = "modified"
sort_reverse = true
show_hidden = false
sort_by = "modified"
sort_reverse = true
sort_dir_first = true
show_hidden = false
[preview]
tab_size = 2

View file

@ -6,8 +6,9 @@ use crate::MERGED_YAZI;
#[derive(Debug, Deserialize)]
pub struct Manager {
// Sorting
pub sort_by: SortBy,
pub sort_reverse: bool,
pub sort_by: SortBy,
pub sort_reverse: bool,
pub sort_dir_first: bool,
// Display
pub show_hidden: bool,

View file

@ -1,4 +1,4 @@
use std::{collections::BTreeMap, ops::{Deref, DerefMut}, path::{Path, PathBuf}};
use std::{cmp::Ordering, collections::BTreeMap, ops::{Deref, DerefMut}, path::{Path, PathBuf}};
use anyhow::Result;
use config::{manager::SortBy, MANAGER};
@ -116,28 +116,42 @@ impl Files {
return false;
}
fn cmp<T: Ord>(a: T, b: T, reverse: bool) -> std::cmp::Ordering {
if reverse { b.cmp(&a) } else { a.cmp(&b) }
#[inline]
#[allow(clippy::collapsible_else_if)]
fn cmp<T: Ord>(a: T, b: T, reverse: bool, promote: Ordering) -> Ordering {
if promote != Ordering::Equal {
promote
} else {
if reverse { b.cmp(&a) } else { a.cmp(&b) }
}
}
#[inline]
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 }
}
let reverse = self.sort.reverse;
let dir_first = self.sort.dir_first;
match self.sort.by {
SortBy::Alphabetical => self.items.sort_by(|_, a, _, b| cmp(&a.path, &b.path, reverse)),
SortBy::Alphabetical => {
self.items.sort_by(|_, a, _, b| cmp(&a.path, &b.path, reverse, promote(a, b, dir_first)))
}
SortBy::Created => self.items.sort_by(|_, a, _, b| {
if let (Ok(a), Ok(b)) = (a.meta.created(), b.meta.created()) {
return cmp(a, b, reverse);
if let (Ok(aa), Ok(bb)) = (a.meta.created(), b.meta.created()) {
return cmp(aa, bb, reverse, promote(a, b, dir_first));
}
std::cmp::Ordering::Equal
Ordering::Equal
}),
SortBy::Modified => self.items.sort_by(|_, a, _, b| {
if let (Ok(a), Ok(b)) = (a.meta.modified(), b.meta.modified()) {
return cmp(a, b, reverse);
if let (Ok(aa), Ok(bb)) = (a.meta.modified(), b.meta.modified()) {
return cmp(aa, bb, reverse, promote(a, b, dir_first));
}
std::cmp::Ordering::Equal
Ordering::Equal
}),
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))
}),
SortBy::Size => {
self.items.sort_by(|_, a, _, b| cmp(a.length.unwrap_or(0), b.length.unwrap_or(0), reverse))
}
}
true
}
@ -155,12 +169,19 @@ impl DerefMut for Files {
#[derive(PartialEq)]
pub struct FilesSort {
pub by: SortBy,
pub reverse: bool,
pub by: SortBy,
pub reverse: bool,
pub dir_first: bool,
}
impl Default for FilesSort {
fn default() -> Self { Self { by: MANAGER.sort_by, reverse: MANAGER.sort_reverse } }
fn default() -> Self {
Self {
by: MANAGER.sort_by,
reverse: MANAGER.sort_reverse,
dir_first: MANAGER.sort_dir_first,
}
}
}
#[derive(Debug)]