diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 1bde031f..193cbf3d 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -4,6 +4,9 @@ on: push: branches: [main] +permissions: + contents: read + jobs: publish: name: Publish Flake diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 43466367..3d363578 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,6 +10,9 @@ env: SCCACHE_GHA_ENABLED: true RUSTC_WRAPPER: sccache +permissions: + contents: read + jobs: clippy: runs-on: ubuntu-latest diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index f95b4562..4987245c 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -9,6 +9,9 @@ on: env: SCCACHE_GHA_ENABLED: true +permissions: + contents: read + jobs: build-unix: strategy: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f7776fd3..61fe3938 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,6 +4,9 @@ on: release: types: [published] +permissions: + contents: read + jobs: winget: runs-on: ubuntu-latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 17ed52e8..5072fb74 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,6 +11,9 @@ env: RUSTC_WRAPPER: sccache CARGO_TERM_COLOR: always +permissions: + contents: read + jobs: test: strategy: diff --git a/CHANGELOG.md b/CHANGELOG.md index 41a7587b..0f1dfc73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/yazi-actor/src/core/preflight.rs b/yazi-actor/src/core/preflight.rs index fbd2aac3..1c46a51c 100644 --- a/yazi-actor/src/core/preflight.rs +++ b/yazi-actor/src/core/preflight.rs @@ -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> { +impl Preflight { + pub fn act<'a>(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result> { 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(), diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index 5025bc70..72a9433f 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -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(); diff --git a/yazi-actor/src/mgr/sort.rs b/yazi-actor/src/mgr/sort.rs index d36604d0..7ad3b322 100644 --- a/yazi-actor/src/mgr/sort.rs +++ b/yazi-actor/src/mgr/sort.rs @@ -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 { + match cx.source() { + Source::Ind => Some(SparkKind::IndSort), + Source::Key => Some(SparkKind::KeySort), + _ => None, + } + } } diff --git a/yazi-actor/src/mgr/stash.rs b/yazi-actor/src/mgr/stash.rs index 33f7a3a9..afcc8597 100644 --- a/yazi-actor/src/mgr/stash.rs +++ b/yazi-actor/src/mgr/stash.rs @@ -23,8 +23,8 @@ impl Actor for Stash { fn hook(cx: &Ctx, _opt: &Self::Options) -> Option { match cx.source() { - Source::Relay => Some(SparkKind::RelayStash), Source::Ind => Some(SparkKind::IndStash), + Source::Relay => Some(SparkKind::RelayStash), _ => None, } } diff --git a/yazi-actor/src/mgr/update_files.rs b/yazi-actor/src/mgr/update_files.rs index af0cd4a5..08e8d225 100644 --- a/yazi-actor/src/mgr/update_files.rs +++ b/yazi-actor/src/mgr/update_files.rs @@ -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)?; diff --git a/yazi-dds/src/macros.rs b/yazi-dds/src/macros.rs index 97ec0a31..7cd44a8f 100644 --- a/yazi-dds/src/macros.rs +++ b/yazi-dds/src/macros.rs @@ -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::[]($body) - // } + paste::paste! { + $crate::spark::Spark::[<$layer:camel $name:camel>]($body.into()) + } }; } diff --git a/yazi-dds/src/spark/kind.rs b/yazi-dds/src/spark/kind.rs index 3cefc874..bea38725 100644 --- a/yazi-dds/src/spark/kind.rs +++ b/yazi-dds/src/spark/kind.rs @@ -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 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", } } } diff --git a/yazi-dds/src/spark/spark.rs b/yazi-dds/src/spark/spark.rs index 1eaf6e24..8aad493a 100644 --- a/yazi-dds/src/spark/spark.rs +++ b/yazi-dds/src/spark/spark.rs @@ -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), // 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 { + 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 diff --git a/yazi-parser/src/mgr/sort.rs b/yazi-parser/src/mgr/sort.rs index 0e411696..2bccb47f 100644 --- a/yazi-parser/src/mgr/sort.rs +++ b/yazi-parser/src/mgr/sort.rs @@ -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, pub reverse: Option, @@ -26,9 +27,9 @@ impl TryFrom for SortOpt { } impl FromLua for SortOpt { - fn from_lua(_: Value, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } + fn from_lua(value: Value, lua: &Lua) -> mlua::Result { lua.from_value(value) } } impl IntoLua for SortOpt { - fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } + fn into_lua(self, lua: &Lua) -> mlua::Result { lua.to_value(&self) } }