feat: new ind-sort and key-sort DDS events to change sorting in Lua (#3391)

This commit is contained in:
三咲雅 misaki masa 2025-12-01 10:51:27 +08:00 committed by GitHub
parent 0fb652d2ec
commit d0adb9c015
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 101 additions and 29 deletions

View file

@ -4,6 +4,9 @@ on:
push:
branches: [main]
permissions:
contents: read
jobs:
publish:
name: Publish Flake

View file

@ -10,6 +10,9 @@ env:
SCCACHE_GHA_ENABLED: true
RUSTC_WRAPPER: sccache
permissions:
contents: read
jobs:
clippy:
runs-on: ubuntu-latest

View file

@ -9,6 +9,9 @@ on:
env:
SCCACHE_GHA_ENABLED: true
permissions:
contents: read
jobs:
build-unix:
strategy:

View file

@ -4,6 +4,9 @@ on:
release:
types: [published]
permissions:
contents: read
jobs:
winget:
runs-on: ubuntu-latest

View file

@ -11,6 +11,9 @@ env:
RUSTC_WRAPPER: sccache
CARGO_TERM_COLOR: always
permissions:
contents: read
jobs:
test:
strategy:

View file

@ -33,9 +33,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
- Support invalid UTF-8 paths throughout the codebase ([#2884], [#2889], [#2890], [#2895], [#3023], [#3290], [#3369])
- Allow upgrading only specific packages with `ya pkg` ([#2841])
- Respect the user's `image_filter` setting in the preset ImageMagick previewer ([#3286])
- New `ind-sort` and `key-sort` DDS events to change sorting in Lua ([#3391])
- Allow custom mouse click behavior for individual files ([#2925])
- Display newlines in input as spaces to improve readability ([#2932])
- Fill in error messages if preview fails ([#2917])
- Fill in error messages if preview fails ([#2917], [#3383], [#3387])
- Search view shares file selection and yank state ([#2855])
- Offload mimetype fetching on opening files to the task scheduler ([#3141])
- Increase terminal response timeout to better tolerate slow SSH network environments ([#2843])
@ -1543,4 +1544,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
[#3360]: https://github.com/sxyazi/yazi/pull/3360
[#3364]: https://github.com/sxyazi/yazi/pull/3364
[#3369]: https://github.com/sxyazi/yazi/pull/3369
[#3383]: https://github.com/sxyazi/yazi/pull/3383
[#3385]: https://github.com/sxyazi/yazi/pull/3385
[#3387]: https://github.com/sxyazi/yazi/pull/3387
[#3391]: https://github.com/sxyazi/yazi/pull/3391

View file

@ -1,5 +1,3 @@
use std::marker::PhantomData;
use anyhow::Result;
use mlua::{ErrorContext, ExternalError, IntoLua, Value};
use yazi_binding::runtime_mut;
@ -8,12 +6,10 @@ use yazi_plugin::LUA;
use crate::{Ctx, lives::Lives};
pub struct Preflight<'a> {
_lifetime: PhantomData<&'a ()>,
}
pub struct Preflight;
impl<'a> Preflight<'a> {
pub fn act(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result<Spark<'a>> {
impl Preflight {
pub fn act<'a>(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result<Spark<'a>> {
let kind = opt.0;
let Some(handlers) = LOCAL.read().get(kind.as_ref()).filter(|&m| !m.is_empty()).cloned() else {
return Ok(opt.1);
@ -27,10 +23,9 @@ impl<'a> Preflight<'a> {
runtime_mut!(LUA)?.pop();
match result {
Ok(Value::Nil) => Err(
format!("Cancelled by `{kind}` event handler in `{id}` plugin on preflight")
.into_lua_err(),
)?,
Ok(Value::Nil) => {
Err(format!("`{kind}` event cancelled by `{id}` plugin on preflight").into_lua_err())?
}
Ok(v) => body = v,
Err(e) => Err(
format!("Failed to run `{kind}` event handler in `{id}` plugin: {e}").into_lua_err(),

View file

@ -50,7 +50,7 @@ impl Actor for Cd {
err!(Pubsub::pub_after_cd(tab.id, tab.cwd()));
act!(mgr:displace, cx)?;
act!(mgr:hidden, cx)?;
act!(mgr:sort, cx)?;
act!(mgr:sort, cx).ok();
act!(mgr:hover, cx)?;
act!(mgr:refresh, cx)?;
act!(mgr:stash, cx, opt).ok();

View file

@ -1,9 +1,10 @@
use anyhow::Result;
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_shared::data::Data;
use yazi_shared::{Source, data::Data};
use crate::{Actor, Ctx};
@ -56,4 +57,12 @@ impl Actor for Sort {
succ!();
}
fn hook(cx: &Ctx, _: &Self::Options) -> Option<SparkKind> {
match cx.source() {
Source::Ind => Some(SparkKind::IndSort),
Source::Key => Some(SparkKind::KeySort),
_ => None,
}
}
}

View file

@ -23,8 +23,8 @@ impl Actor for Stash {
fn hook(cx: &Ctx, _opt: &Self::Options) -> Option<SparkKind> {
match cx.source() {
Source::Relay => Some(SparkKind::RelayStash),
Source::Ind => Some(SparkKind::IndStash),
Source::Relay => Some(SparkKind::RelayStash),
_ => None,
}
}

View file

@ -26,7 +26,7 @@ impl Actor for UpdateFiles {
render!(cx.mgr.yanked.catchup_revision(false));
act!(mgr:hidden, cx)?;
act!(mgr:sort, cx)?;
act!(mgr:sort, cx).ok();
if revision != cx.current().files.revision {
act!(mgr:hover, cx)?;

View file

@ -6,10 +6,9 @@ macro_rules! spark {
}
};
($layer:ident : $name:ident, $body:expr) => {
$crate::spark::Spark::Void(yazi_parser::VoidOpt)
// paste::paste! {
// $crate::body::Body::[<Key $layer:camel $name:camel>]($body)
// }
paste::paste! {
$crate::spark::Spark::[<$layer:camel $name:camel>]($body.into())
}
};
}

View file

@ -2,17 +2,27 @@ use std::fmt::Display;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SparkKind {
// Sort
KeySort,
IndSort,
// Stash
IndStash,
KeyQuit,
RelayStash,
// Quit
KeyQuit,
}
impl AsRef<str> for SparkKind {
fn as_ref(&self) -> &str {
match self {
// Sort
Self::KeySort => "key-sort",
Self::IndSort => "ind-sort",
// Stash
Self::IndStash => "ind-stash",
Self::KeyQuit => "key-quit",
Self::RelayStash => "relay-stash",
// Quit
Self::KeyQuit => "key-quit",
}
}
}

View file

@ -76,15 +76,20 @@ pub enum Spark<'a> {
Yank(yazi_parser::mgr::YankOpt),
// Cmp
CmpArrow(yazi_parser::ArrowOpt),
CmpClose(yazi_parser::cmp::CloseOpt),
CmpShow(yazi_parser::cmp::ShowOpt),
CmpTrigger(yazi_parser::cmp::TriggerOpt),
// Confirm
ConfirmArrow(yazi_parser::ArrowOpt),
ConfirmClose(yazi_parser::confirm::CloseOpt),
ConfirmShow(Box<yazi_parser::confirm::ShowOpt>),
// Help
HelpArrow(yazi_parser::ArrowOpt),
HelpEscape(yazi_parser::VoidOpt),
HelpFilter(yazi_parser::VoidOpt),
HelpToggle(yazi_parser::help::ToggleOpt),
// Input
@ -93,6 +98,7 @@ pub enum Spark<'a> {
InputClose(yazi_parser::input::CloseOpt),
InputComplete(yazi_parser::input::CompleteOpt),
InputDelete(yazi_parser::input::DeleteOpt),
InputEscape(yazi_parser::VoidOpt),
InputForward(yazi_parser::input::ForwardOpt),
InputInsert(yazi_parser::input::InsertOpt),
InputKill(yazi_parser::input::KillOpt),
@ -104,14 +110,24 @@ pub enum Spark<'a> {
NotifyTick(yazi_parser::notify::TickOpt),
// Pick
PickArrow(yazi_parser::ArrowOpt),
PickClose(yazi_parser::pick::CloseOpt),
PickShow(yazi_parser::pick::ShowOpt),
// Spot
SpotArrow(yazi_parser::ArrowOpt),
SpotClose(yazi_parser::VoidOpt),
SpotCopy(yazi_parser::spot::CopyOpt),
SpotSwipe(yazi_parser::ArrowOpt),
// Tasks
TasksArrow(yazi_parser::ArrowOpt),
TasksCancel(yazi_parser::VoidOpt),
TasksClose(yazi_parser::VoidOpt),
TasksInspect(yazi_parser::VoidOpt),
TasksOpenShellCompat(yazi_parser::tasks::ProcessOpenOpt),
TasksProcessOpen(yazi_parser::tasks::ProcessOpenOpt),
TasksShow(yazi_parser::VoidOpt),
TasksUpdateSucceed(yazi_parser::tasks::UpdateSucceedOpt),
// Which
@ -121,10 +137,17 @@ pub enum Spark<'a> {
impl<'a> Spark<'a> {
pub fn from_lua(lua: &Lua, kind: SparkKind, value: Value) -> mlua::Result<Self> {
use SparkKind::*;
Ok(match kind {
SparkKind::IndStash => Self::Stash(<_>::from_lua(value, lua)?),
SparkKind::KeyQuit => Self::Quit(<_>::from_lua(value, lua)?),
SparkKind::RelayStash => Self::Stash(<_>::from_lua(value, lua)?),
// Sort
KeySort => Self::Sort(<_>::from_lua(value, lua)?),
IndSort => Self::Sort(<_>::from_lua(value, lua)?),
// Stash
IndStash => Self::Stash(<_>::from_lua(value, lua)?),
RelayStash => Self::Stash(<_>::from_lua(value, lua)?),
// Quit
KeyQuit => Self::Quit(<_>::from_lua(value, lua)?),
})
}
}
@ -204,15 +227,20 @@ impl<'a> IntoLua for Spark<'a> {
Self::Yank(b) => b.into_lua(lua),
// Cmp
Self::CmpArrow(b) => b.into_lua(lua),
Self::CmpClose(b) => b.into_lua(lua),
Self::CmpShow(b) => b.into_lua(lua),
Self::CmpTrigger(b) => b.into_lua(lua),
// Confirm
Self::ConfirmArrow(b) => b.into_lua(lua),
Self::ConfirmClose(b) => b.into_lua(lua),
Self::ConfirmShow(b) => b.into_lua(lua),
// Help
Self::HelpArrow(b) => b.into_lua(lua),
Self::HelpEscape(b) => b.into_lua(lua),
Self::HelpFilter(b) => b.into_lua(lua),
Self::HelpToggle(b) => b.into_lua(lua),
// Input
@ -221,6 +249,7 @@ impl<'a> IntoLua for Spark<'a> {
Self::InputClose(b) => b.into_lua(lua),
Self::InputComplete(b) => b.into_lua(lua),
Self::InputDelete(b) => b.into_lua(lua),
Self::InputEscape(b) => b.into_lua(lua),
Self::InputForward(b) => b.into_lua(lua),
Self::InputInsert(b) => b.into_lua(lua),
Self::InputKill(b) => b.into_lua(lua),
@ -232,14 +261,24 @@ impl<'a> IntoLua for Spark<'a> {
Self::NotifyTick(b) => b.into_lua(lua),
// Pick
Self::PickArrow(b) => b.into_lua(lua),
Self::PickClose(b) => b.into_lua(lua),
Self::PickShow(b) => b.into_lua(lua),
// Spot
Self::SpotArrow(b) => b.into_lua(lua),
Self::SpotClose(b) => b.into_lua(lua),
Self::SpotCopy(b) => b.into_lua(lua),
Self::SpotSwipe(b) => b.into_lua(lua),
// Tasks
Self::TasksArrow(b) => b.into_lua(lua),
Self::TasksCancel(b) => b.into_lua(lua),
Self::TasksClose(b) => b.into_lua(lua),
Self::TasksInspect(b) => b.into_lua(lua),
Self::TasksOpenShellCompat(b) => b.into_lua(lua),
Self::TasksProcessOpen(b) => b.into_lua(lua),
Self::TasksShow(b) => b.into_lua(lua),
Self::TasksUpdateSucceed(b) => b.into_lua(lua),
// Which

View file

@ -1,8 +1,9 @@
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
use mlua::{FromLua, IntoLua, Lua, LuaSerdeExt, Value};
use serde::{Deserialize, Serialize};
use yazi_fs::SortBy;
use yazi_shared::event::CmdCow;
#[derive(Debug, Default)]
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct SortOpt {
pub by: Option<SortBy>,
pub reverse: Option<bool>,
@ -26,9 +27,9 @@ impl TryFrom<CmdCow> for SortOpt {
}
impl FromLua for SortOpt {
fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
fn from_lua(value: Value, lua: &Lua) -> mlua::Result<Self> { lua.from_value(value) }
}
impl IntoLua for SortOpt {
fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value(&self) }
}