feat: add random option to the sort command

This commit is contained in:
zooeywm 2024-07-13 22:06:54 +08:00
parent f5598ebb8a
commit 8b6f28f187
3 changed files with 34 additions and 1 deletions

View file

@ -119,6 +119,8 @@ keymap = [
{ on = [ ",", "N" ], run = "sort natural --reverse", desc = "Sort naturally (reverse)" },
{ on = [ ",", "s" ], run = "sort size --reverse=no", desc = "Sort by size" },
{ on = [ ",", "S" ], run = "sort size --reverse", desc = "Sort by size (reverse)" },
{ on = [ ",", "r" ], run = "sort random --reverse=no", desc = "Sort randomly" },
{ on = [ ",", "R" ], run = "sort random --reverse", desc = "Sort randomly (reverse)" },
# Tabs
{ on = "t", run = "tab_create --current", desc = "Create a new tab with CWD" },

View file

@ -14,6 +14,7 @@ pub enum SortBy {
Alphabetical,
Natural,
Size,
Random,
}
impl FromStr for SortBy {
@ -28,6 +29,7 @@ impl FromStr for SortBy {
"alphabetical" => Self::Alphabetical,
"natural" => Self::Natural,
"size" => Self::Size,
"random" => Self::Random,
_ => bail!("invalid sort_by value: {s}"),
})
}
@ -49,6 +51,7 @@ impl Display for SortBy {
Self::Alphabetical => "alphabetical",
Self::Natural => "natural",
Self::Size => "size",
Self::Random => "random",
})
}
}

View file

@ -1,8 +1,25 @@
use std::{cmp::Ordering, collections::HashMap, mem};
use std::{cmp::Ordering, collections::HashMap, mem, time::{SystemTime, UNIX_EPOCH}};
use yazi_config::manager::SortBy;
use yazi_shared::{fs::{File, Url}, natsort, Transliterator};
struct LcgRng {
seed: u64,
}
impl LcgRng {
const A: u64 = 6364136223846793005;
const C: u64 = 1;
const M: u64 = u64::MAX;
fn new(seed: u64) -> Self { LcgRng { seed } }
fn next(&mut self) -> u64 {
self.seed = (Self::A.wrapping_mul(self.seed).wrapping_add(Self::C)) % Self::M;
self.seed
}
}
#[derive(Clone, Copy, Default, PartialEq)]
pub struct FilesSorter {
pub by: SortBy,
@ -60,6 +77,17 @@ impl FilesSorter {
let ord = self.cmp(aa.unwrap_or(a.len), bb.unwrap_or(b.len), self.promote(a, b));
if ord == Ordering::Equal { by_alphabetical(a, b) } else { ord }
}),
SortBy::Random => {
let start = SystemTime::now();
let since_epoch = start.duration_since(UNIX_EPOCH).expect("Time went backwards");
let seed = since_epoch.as_secs() ^ since_epoch.subsec_nanos() as u64;
let mut rng = LcgRng::new(seed);
items.sort_unstable_by(|a, b| {
let aa = rng.next();
let bb = rng.next();
self.cmp(aa, bb, self.promote(a, b))
})
}
}
}