mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Merge d67dc26990 into 2514725e56
This commit is contained in:
commit
e41db8936d
2 changed files with 108 additions and 9 deletions
|
|
@ -3,7 +3,7 @@ use yazi_core::tab::Folder;
|
||||||
use yazi_dds::spark::SparkKind;
|
use yazi_dds::spark::SparkKind;
|
||||||
use yazi_fs::{FilesSorter, FolderStage};
|
use yazi_fs::{FilesSorter, FolderStage};
|
||||||
use yazi_macro::{act, render, render_and, succ};
|
use yazi_macro::{act, render, render_and, succ};
|
||||||
use yazi_parser::mgr::SortOpt;
|
use yazi_parser::mgr::{SortBoolState, SortOpt};
|
||||||
use yazi_shared::{Source, data::Data};
|
use yazi_shared::{Source, data::Data};
|
||||||
|
|
||||||
use crate::{Actor, Ctx};
|
use crate::{Actor, Ctx};
|
||||||
|
|
@ -18,10 +18,10 @@ impl Actor for Sort {
|
||||||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||||
let pref = &mut cx.tab_mut().pref;
|
let pref = &mut cx.tab_mut().pref;
|
||||||
pref.sort_by = opt.by.unwrap_or(pref.sort_by);
|
pref.sort_by = opt.by.unwrap_or(pref.sort_by);
|
||||||
pref.sort_reverse = opt.reverse.unwrap_or(pref.sort_reverse);
|
pref.sort_reverse = opt.reverse.unwrap_or_default().bool(pref.sort_reverse);
|
||||||
pref.sort_dir_first = opt.dir_first.unwrap_or(pref.sort_dir_first);
|
pref.sort_dir_first = opt.dir_first.unwrap_or_default().bool(pref.sort_dir_first);
|
||||||
pref.sort_sensitive = opt.sensitive.unwrap_or(pref.sort_sensitive);
|
pref.sort_sensitive = opt.sensitive.unwrap_or(pref.sort_sensitive);
|
||||||
pref.sort_translit = opt.translit.unwrap_or(pref.sort_translit);
|
pref.sort_translit = opt.translit.unwrap_or_default().bool(pref.sort_translit);
|
||||||
pref.sort_fallback = opt.fallback.unwrap_or(pref.sort_fallback);
|
pref.sort_fallback = opt.fallback.unwrap_or(pref.sort_fallback);
|
||||||
|
|
||||||
let sorter = FilesSorter::from(&*pref);
|
let sorter = FilesSorter::from(&*pref);
|
||||||
|
|
@ -59,7 +59,15 @@ impl Actor for Sort {
|
||||||
succ!();
|
succ!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hook(cx: &Ctx, _: &Self::Options) -> Option<SparkKind> {
|
fn hook(cx: &Ctx, opt: &Self::Options) -> Option<SparkKind> {
|
||||||
|
let has_toggle = [opt.reverse, opt.dir_first, opt.translit]
|
||||||
|
.iter()
|
||||||
|
.any(|f| matches!(f, Some(SortBoolState::Toggle)));
|
||||||
|
|
||||||
|
if has_toggle {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
match cx.source() {
|
match cx.source() {
|
||||||
Source::Ind => Some(SparkKind::IndSort),
|
Source::Ind => Some(SparkKind::IndSort),
|
||||||
Source::Key => Some(SparkKind::KeySort),
|
Source::Key => Some(SparkKind::KeySort),
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use yazi_binding::SER_OPT;
|
use yazi_binding::SER_OPT;
|
||||||
use yazi_fs::{SortBy, SortFallback};
|
use yazi_fs::{SortBy, SortFallback};
|
||||||
use yazi_shared::event::ActionCow;
|
use yazi_shared::{data::Data, event::ActionCow};
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
pub struct SortOpt {
|
pub struct SortOpt {
|
||||||
pub by: Option<SortBy>,
|
pub by: Option<SortBy>,
|
||||||
pub reverse: Option<bool>,
|
pub reverse: Option<SortBoolState>,
|
||||||
pub dir_first: Option<bool>,
|
pub dir_first: Option<SortBoolState>,
|
||||||
pub sensitive: Option<bool>,
|
pub sensitive: Option<bool>,
|
||||||
pub translit: Option<bool>,
|
pub translit: Option<SortBoolState>,
|
||||||
pub fallback: Option<SortFallback>,
|
pub fallback: Option<SortFallback>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,3 +39,91 @@ impl FromLua for SortOpt {
|
||||||
impl IntoLua for SortOpt {
|
impl IntoLua for SortOpt {
|
||||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value_with(&self, SER_OPT) }
|
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value_with(&self, SER_OPT) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- State
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||||
|
pub enum SortBoolState {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
On,
|
||||||
|
Off,
|
||||||
|
Toggle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl serde::Serialize for SortBoolState {
|
||||||
|
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
match self {
|
||||||
|
Self::On => serializer.serialize_bool(true),
|
||||||
|
Self::Off => serializer.serialize_bool(false),
|
||||||
|
Self::Toggle => serializer.serialize_str("toggle"),
|
||||||
|
Self::None => serializer.serialize_str("none"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for SortBoolState {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"yes" => Ok(Self::On),
|
||||||
|
"no" => Ok(Self::Off),
|
||||||
|
"toggle" => Ok(Self::Toggle),
|
||||||
|
_ => bail!("unknown sort bool state: {s:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> serde::Deserialize<'de> for SortBoolState {
|
||||||
|
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
use serde::de::{self, Visitor};
|
||||||
|
|
||||||
|
struct V;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for V {
|
||||||
|
type Value = SortBoolState;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
f.write_str(r#"a boolean or one of "yes", "no", "toggle""#)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bool<E: de::Error>(self, v: bool) -> Result<Self::Value, E> {
|
||||||
|
Ok(if v { SortBoolState::On } else { SortBoolState::Off })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||||
|
v.parse().map_err(de::Error::custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
|
||||||
|
self.visit_str(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_any(V)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SortBoolState {
|
||||||
|
pub fn bool(self, old: bool) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::None => old,
|
||||||
|
Self::On => true,
|
||||||
|
Self::Off => false,
|
||||||
|
Self::Toggle => !old,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Data> for SortBoolState {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: &Data) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
Data::Boolean(true) => Ok(Self::On),
|
||||||
|
Data::Boolean(false) => Ok(Self::Off),
|
||||||
|
Data::String(s) => s.parse(),
|
||||||
|
_ => bail!("not a valid bool state"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue