mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: Enable the ability to sort the which key
* sort "which" window in following way: - sort_by: "key|desc|none" - sort_sensitive: true|false - sort_reverse: true|false
This commit is contained in:
parent
dc1718fcf0
commit
f6b4c923b4
11 changed files with 190 additions and 14 deletions
|
|
@ -2,6 +2,11 @@
|
||||||
# If you encounter any issues, please make an issue at https://github.com/yazi-rs/schemas.
|
# If you encounter any issues, please make an issue at https://github.com/yazi-rs/schemas.
|
||||||
"$schema" = "https://yazi-rs.github.io/schemas/yazi.json"
|
"$schema" = "https://yazi-rs.github.io/schemas/yazi.json"
|
||||||
|
|
||||||
|
[which]
|
||||||
|
sort_by = "none"
|
||||||
|
sort_sensitive = false
|
||||||
|
sort_reverse = false
|
||||||
|
|
||||||
[manager]
|
[manager]
|
||||||
ratio = [ 1, 4, 3 ]
|
ratio = [ 1, 4, 3 ]
|
||||||
sort_by = "alphabetical"
|
sort_by = "alphabetical"
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ impl Control {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ControlCow {
|
pub enum ControlCow {
|
||||||
Owned(Control),
|
Owned(Control),
|
||||||
Borrowed(&'static Control),
|
Borrowed(&'static Control),
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ mod tasks;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
mod validation;
|
mod validation;
|
||||||
mod xdg;
|
mod xdg;
|
||||||
|
pub mod which;
|
||||||
|
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
pub(crate) use pattern::*;
|
pub(crate) use pattern::*;
|
||||||
|
|
@ -43,6 +44,7 @@ pub static TASKS: RoCell<tasks::Tasks> = RoCell::new();
|
||||||
pub static THEME: RoCell<theme::Theme> = RoCell::new();
|
pub static THEME: RoCell<theme::Theme> = RoCell::new();
|
||||||
pub static INPUT: RoCell<popup::Input> = RoCell::new();
|
pub static INPUT: RoCell<popup::Input> = RoCell::new();
|
||||||
pub static SELECT: RoCell<popup::Select> = RoCell::new();
|
pub static SELECT: RoCell<popup::Select> = RoCell::new();
|
||||||
|
pub static WHICH: RoCell<which::Which> = RoCell::new();
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
ARGS.with(Default::default);
|
ARGS.with(Default::default);
|
||||||
|
|
@ -63,4 +65,5 @@ pub fn init() {
|
||||||
THEME.with(Default::default);
|
THEME.with(Default::default);
|
||||||
INPUT.with(Default::default);
|
INPUT.with(Default::default);
|
||||||
SELECT.with(Default::default);
|
SELECT.with(Default::default);
|
||||||
|
WHICH.with(Default::default);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
yazi-config/src/which/mod.rs
Normal file
5
yazi-config/src/which/mod.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
mod sorting;
|
||||||
|
mod which;
|
||||||
|
|
||||||
|
pub use sorting::*;
|
||||||
|
pub use which::*;
|
||||||
44
yazi-config/src/which/sorting.rs
Normal file
44
yazi-config/src/which/sorting.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(try_from = "String")]
|
||||||
|
pub enum SortBy {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
Key,
|
||||||
|
Desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for SortBy {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(match s {
|
||||||
|
"none" => Self::None,
|
||||||
|
"key" => Self::Key,
|
||||||
|
"desc" => Self::Desc,
|
||||||
|
_ => bail!("Invalid sort option: {s}")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for SortBy {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
|
Self::from_str(&value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for SortBy {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::None => "none",
|
||||||
|
Self::Key => "key",
|
||||||
|
Self::Desc => "desc",
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
27
yazi-config/src/which/which.rs
Normal file
27
yazi-config/src/which/which.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
use super::SortBy;
|
||||||
|
use crate::{validation::check_validation, MERGED_YAZI};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Validate)]
|
||||||
|
pub struct Which {
|
||||||
|
// Sorting
|
||||||
|
pub sort_by: SortBy,
|
||||||
|
pub sort_sensitive: bool,
|
||||||
|
pub sort_reverse: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Which {
|
||||||
|
fn default() -> Self {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Outer {
|
||||||
|
which: Which,
|
||||||
|
}
|
||||||
|
|
||||||
|
let which = toml::from_str::<Outer>(&MERGED_YAZI).unwrap().which;
|
||||||
|
|
||||||
|
check_validation(which.validate());
|
||||||
|
which
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,18 +42,21 @@ impl Which {
|
||||||
render!();
|
render!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_with(&mut self, key: &Key, layer: Layer) {
|
pub fn show_with(&mut self, key: &Key, layer: Layer) {
|
||||||
self.layer = layer;
|
self.layer = layer;
|
||||||
self.times = 1;
|
self.times = 1;
|
||||||
self.cands = KEYMAP
|
self.cands = KEYMAP
|
||||||
.get(layer)
|
.get(layer)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|c| c.on.len() > 1 && &c.on[0] == key)
|
.filter(|c| c.on.len() > 1 && &c.on[0] == key)
|
||||||
.map(|c| c.into())
|
.map(|c| c.into())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.visible = true;
|
// sort "which"
|
||||||
self.silent = false;
|
self.conf.sorter().sort(&mut self.cands);
|
||||||
render!();
|
|
||||||
}
|
self.visible = true;
|
||||||
|
self.silent = false;
|
||||||
|
render!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
41
yazi-core/src/which/config.rs
Normal file
41
yazi-core/src/which/config.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use yazi_config::{which::SortBy, WHICH};
|
||||||
|
|
||||||
|
use crate::which::WhichSorter;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
// Sorting
|
||||||
|
pub sort_by: SortBy,
|
||||||
|
pub sort_sensitive: bool,
|
||||||
|
pub sort_reverse: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
// Sorting
|
||||||
|
sort_by: WHICH.sort_by,
|
||||||
|
sort_sensitive: WHICH.sort_sensitive,
|
||||||
|
sort_reverse: WHICH.sort_reverse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
#[allow(unused)]
|
||||||
|
pub(super) fn patch<F: FnOnce(&mut Self)>(&mut self, f: F) -> bool {
|
||||||
|
let old = self.clone();
|
||||||
|
f(self);
|
||||||
|
*self != old
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn sorter(&self) -> WhichSorter {
|
||||||
|
WhichSorter {
|
||||||
|
by: self.sort_by,
|
||||||
|
sensitive: self.sort_sensitive,
|
||||||
|
reverse: self.sort_reverse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
mod commands;
|
mod commands;
|
||||||
mod which;
|
mod which;
|
||||||
|
mod config;
|
||||||
|
mod sorter;
|
||||||
|
|
||||||
pub use which::*;
|
pub use which::*;
|
||||||
|
pub use config::*;
|
||||||
|
pub use sorter::*;
|
||||||
|
|
|
||||||
39
yazi-core/src/which/sorter.rs
Normal file
39
yazi-core/src/which/sorter.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
use yazi_config::{which::SortBy, keymap::ControlCow};
|
||||||
|
use yazi_shared::natsort;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, PartialEq)]
|
||||||
|
pub struct WhichSorter {
|
||||||
|
pub by: SortBy,
|
||||||
|
pub sensitive: bool,
|
||||||
|
pub reverse: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WhichSorter {
|
||||||
|
pub(super) fn sort(&self, items: &mut Vec<ControlCow>) -> bool {
|
||||||
|
if items.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let by_alphabetical = |a: &str, b: &str| {
|
||||||
|
let ordering = natsort(a.as_bytes(), b.as_bytes(), !self.sensitive);
|
||||||
|
if self.reverse { ordering.reverse() } else { ordering }
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.by {
|
||||||
|
SortBy::None => return false,
|
||||||
|
SortBy::Key => items.sort_unstable_by(|a, b| {
|
||||||
|
let a = a.on.iter().map(|c| c.to_string()).collect::<String>();
|
||||||
|
let b = b.on.iter().map(|c| c.to_string()).collect::<String>();
|
||||||
|
by_alphabetical(&a, &b)
|
||||||
|
}),
|
||||||
|
SortBy::Desc => items.sort_unstable_by(|a, b| {
|
||||||
|
// what if description isn't present (need to check if it's mandatory or not)
|
||||||
|
// in case if it is not present, should I just panic ?
|
||||||
|
by_alphabetical(a.desc.as_ref().unwrap(), b.desc.as_ref().unwrap())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
use yazi_config::keymap::{ControlCow, Key};
|
use yazi_config::keymap::{ControlCow, Key};
|
||||||
use yazi_shared::{emit, render, Layer};
|
use yazi_shared::{emit, render, Layer};
|
||||||
|
|
||||||
#[derive(Default)]
|
use crate::which::Config;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
pub struct Which {
|
pub struct Which {
|
||||||
pub(super) layer: Layer,
|
pub(super) layer: Layer,
|
||||||
pub times: usize,
|
pub times: usize,
|
||||||
pub cands: Vec<ControlCow>,
|
pub cands: Vec<ControlCow>,
|
||||||
|
|
||||||
|
pub conf: Config,
|
||||||
|
|
||||||
pub visible: bool,
|
pub visible: bool,
|
||||||
pub silent: bool,
|
pub silent: bool,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue