From 8b6f28f187ecbe0dc0608f054e0c05ad402014ca Mon Sep 17 00:00:00 2001 From: zooeywm Date: Sat, 13 Jul 2024 22:06:54 +0800 Subject: [PATCH] feat: add `random` option to the `sort` command --- yazi-config/preset/keymap.toml | 2 ++ yazi-config/src/manager/sorting.rs | 3 +++ yazi-core/src/folder/sorter.rs | 30 +++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/yazi-config/preset/keymap.toml b/yazi-config/preset/keymap.toml index daa6b442..f3bec02b 100644 --- a/yazi-config/preset/keymap.toml +++ b/yazi-config/preset/keymap.toml @@ -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" }, diff --git a/yazi-config/src/manager/sorting.rs b/yazi-config/src/manager/sorting.rs index 6d060090..648efb87 100644 --- a/yazi-config/src/manager/sorting.rs +++ b/yazi-config/src/manager/sorting.rs @@ -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", }) } } diff --git a/yazi-core/src/folder/sorter.rs b/yazi-core/src/folder/sorter.rs index eb7079b7..284038ae 100644 --- a/yazi-core/src/folder/sorter.rs +++ b/yazi-core/src/folder/sorter.rs @@ -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)) + }) + } } }