mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: add toggle support for sort boolean flags
This commit is contained in:
parent
a246e9c7c0
commit
d67dc26990
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_fs::{FilesSorter, FolderStage};
|
||||
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 crate::{Actor, Ctx};
|
||||
|
|
@ -18,10 +18,10 @@ impl Actor for Sort {
|
|||
fn act(cx: &mut Ctx, opt: Self::Options) -> Result<Data> {
|
||||
let pref = &mut cx.tab_mut().pref;
|
||||
pref.sort_by = opt.by.unwrap_or(pref.sort_by);
|
||||
pref.sort_reverse = opt.reverse.unwrap_or(pref.sort_reverse);
|
||||
pref.sort_dir_first = opt.dir_first.unwrap_or(pref.sort_dir_first);
|
||||
pref.sort_reverse = opt.reverse.unwrap_or_default().bool(pref.sort_reverse);
|
||||
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_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);
|
||||
|
||||
let sorter = FilesSorter::from(&*pref);
|
||||
|
|
@ -59,7 +59,15 @@ impl Actor for Sort {
|
|||
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() {
|
||||
Source::Ind => Some(SparkKind::IndSort),
|
||||
Source::Key => Some(SparkKind::KeySort),
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::bail;
|
||||
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_binding::SER_OPT;
|
||||
use yazi_fs::{SortBy, SortFallback};
|
||||
use yazi_shared::event::ActionCow;
|
||||
use yazi_shared::{data::Data, event::ActionCow};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct SortOpt {
|
||||
pub by: Option<SortBy>,
|
||||
pub reverse: Option<bool>,
|
||||
pub dir_first: Option<bool>,
|
||||
pub reverse: Option<SortBoolState>,
|
||||
pub dir_first: Option<SortBoolState>,
|
||||
pub sensitive: Option<bool>,
|
||||
pub translit: Option<bool>,
|
||||
pub translit: Option<SortBoolState>,
|
||||
pub fallback: Option<SortFallback>,
|
||||
}
|
||||
|
||||
|
|
@ -36,3 +39,91 @@ impl FromLua for SortOpt {
|
|||
impl IntoLua for SortOpt {
|
||||
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