mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new gait for input backward and forward actions (#4012)
This commit is contained in:
parent
e892bf7d90
commit
8e80798984
19 changed files with 145 additions and 150 deletions
|
|
@ -23,6 +23,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
- Rename `<BackTab>` to `<S-Tab>` ([#3989])
|
||||
- Remove Legacy Console Mode on Windows ([#3989])
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecate `backward --far` and `forward --far` in favor of `backward wide` and `forward wide`, respectively ([#4012])
|
||||
|
||||
## [v26.5.6]
|
||||
|
||||
### Added
|
||||
|
|
@ -1731,3 +1735,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
|||
[#3989]: https://github.com/sxyazi/yazi/pull/3989
|
||||
[#3990]: https://github.com/sxyazi/yazi/pull/3990
|
||||
[#4005]: https://github.com/sxyazi/yazi/pull/4005
|
||||
[#4012]: https://github.com/sxyazi/yazi/pull/4012
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::io::Write;
|
|||
|
||||
use mlua::{BorrowedBytes, ExternalError, IntoLuaMulti, Lua, MultiValue, Table, UserData, UserDataMethods};
|
||||
use yazi_shim::mlua::{ByteString, LuaTableExt};
|
||||
use yazi_term::sequence::{ConfirmDrag, ConfirmDrop, FinishDrop, PresentDrag, PresentDragIcon, StartDrag, StartDrop};
|
||||
use yazi_term::sequence::{AgreeDrag, AgreeDrop, FinishDrop, PresentDrag, PresentDragIcon, StartDrag, StartDrop};
|
||||
use yazi_tty::TTY;
|
||||
|
||||
use crate::Error;
|
||||
|
|
@ -14,22 +14,22 @@ impl Tty {
|
|||
let mut w = TTY.writer();
|
||||
|
||||
let result = match kind {
|
||||
b"ConfirmDrag" => {
|
||||
b"AgreeDrag" => {
|
||||
let it = t.raw_get::<Table>("mimes")?.sequence_iter::<ByteString>(lua).flatten();
|
||||
write!(w, "{}", match &*t.raw_get::<BorrowedBytes>("type")? {
|
||||
b"copy" => ConfirmDrag::Copy(it),
|
||||
b"move" => ConfirmDrag::Move(it),
|
||||
b"either" => ConfirmDrag::Either(it),
|
||||
_ => return Err("invalid ConfirmDrag type".into_lua_err()),
|
||||
b"copy" => AgreeDrag::Copy(it),
|
||||
b"move" => AgreeDrag::Move(it),
|
||||
b"either" => AgreeDrag::Either(it),
|
||||
_ => return Err("invalid AgreeDrag type".into_lua_err()),
|
||||
})
|
||||
}
|
||||
b"ConfirmDrop" => {
|
||||
b"AgreeDrop" => {
|
||||
let it = t.raw_get::<Table>("mimes")?.sequence_iter::<ByteString>(lua).flatten();
|
||||
write!(w, "{}", match &*t.raw_get::<BorrowedBytes>("type")? {
|
||||
b"reject" => ConfirmDrop::Reject,
|
||||
b"copy" => ConfirmDrop::Copy(it),
|
||||
b"move" => ConfirmDrop::Move(it),
|
||||
_ => return Err("invalid ConfirmDrop type".into_lua_err()),
|
||||
b"reject" => AgreeDrop::Reject,
|
||||
b"copy" => AgreeDrop::Copy(it),
|
||||
b"move" => AgreeDrop::Move(it),
|
||||
_ => return Err("invalid AgreeDrop type".into_lua_err()),
|
||||
})
|
||||
}
|
||||
b"StartDrag" => write!(w, "{StartDrag}"),
|
||||
|
|
|
|||
|
|
@ -258,15 +258,15 @@ keymap = [
|
|||
|
||||
# Word-wise movement
|
||||
{ on = "b", run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "B", run = "backward --far", desc = "Move back to the start of the current or previous WORD" },
|
||||
{ on = "B", run = "backward wide", desc = "Move back to the start of the current or previous WORD" },
|
||||
{ on = "w", run = "forward", desc = "Move forward to the start of the next word" },
|
||||
{ on = "W", run = "forward --far", desc = "Move forward to the start of the next WORD" },
|
||||
{ on = "W", run = "forward wide", desc = "Move forward to the start of the next WORD" },
|
||||
{ on = "e", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "E", run = "forward --far --end-of-word", desc = "Move forward to the end of the current or next WORD" },
|
||||
{ on = "<A-b>", run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "<A-f>", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "<C-Left>", run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "<C-Right>", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "E", run = "forward wide --end-of-word", desc = "Move forward to the end of the current or next WORD" },
|
||||
{ on = "<A-b>", run = "backward lean", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "<A-f>", run = "forward lean --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "<C-Left>", run = "backward lean", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "<C-Right>", run = "forward lean --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
|
||||
# Line-wise movement
|
||||
{ on = "0", run = "move bol", desc = "Move to the BOL" },
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ function Current:drop(event)
|
|||
if Current._dragging then
|
||||
return
|
||||
elseif event.type == "enter" then
|
||||
rt.tty:queue("ConfirmDrop", { type = "move", mimes = { "text/uri-list" } })
|
||||
rt.tty:queue("AgreeDrop", { type = "move", mimes = { "text/uri-list" } })
|
||||
elseif event.type == "ready" then
|
||||
rt.tty:queue("StartDrop", { idx = 1 })
|
||||
elseif event.type == "arrive" then
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ function M.offer_uri_list()
|
|||
end
|
||||
|
||||
local icon = string.format("%d selected file(s)", #list)
|
||||
rt.tty:queue("ConfirmDrag", { type = "either", mimes = { "text/uri-list" } })
|
||||
rt.tty:queue("AgreeDrag", { type = "either", mimes = { "text/uri-list" } })
|
||||
rt.tty:queue("PresentDrag", { idx = 0, data = table.concat(list, "\r\n") })
|
||||
rt.tty:queue("PresentDragIcon", { format = 0, opacity = 0, width = 6, height = 4, data = icon })
|
||||
rt.tty:queue("StartDrag", {})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use mlua::{ExternalError, Function, IntoLua, IntoLuaMulti, Lua, Table, Value};
|
||||
use yazi_binding::{Cha, Composer, ComposerGet, ComposerSet, Error, File, SizeCalculator, Url, UrlRef, deprecate};
|
||||
use yazi_binding::{Cha, Composer, ComposerGet, ComposerSet, Error, File, SizeCalculator, Url, UrlRef};
|
||||
use yazi_config::Pattern;
|
||||
use yazi_fs::{mounts::PARTITIONS, provider::{Attrs, DirReader, FileHolder}};
|
||||
use yazi_shared::url::{UrlCow, UrlLike};
|
||||
|
|
@ -23,7 +23,6 @@ pub fn compose() -> Composer<ComposerGet, ComposerSet> {
|
|||
b"remove" => remove(lua)?,
|
||||
b"rename" => rename(lua)?,
|
||||
b"unique" => unique(lua)?,
|
||||
b"unique_name" => unique_name(lua)?,
|
||||
b"write" => write(lua)?,
|
||||
_ => return Ok(Value::Nil),
|
||||
}
|
||||
|
|
@ -231,16 +230,6 @@ fn unique(lua: &Lua) -> mlua::Result<Function> {
|
|||
})
|
||||
}
|
||||
|
||||
fn unique_name(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, url: UrlRef| async move {
|
||||
deprecate!(lua, "`fs.unique_name()` is deprecated, use `fs.unique()` instead, in your {}\nSee #3677 for more details: https://github.com/sxyazi/yazi/pull/3677");
|
||||
match yazi_vfs::unique_name(url.clone(), async { false }).await {
|
||||
Ok(u) => Url::new(u).into_lua_multi(&lua),
|
||||
Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn write(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (url, data): (UrlRef, mlua::String)| async move {
|
||||
match provider::write(&*url, data.as_bytes()).await {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use mlua::{ExternalError, Function, Lua, Table};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_binding::deprecate;
|
||||
use yazi_dds::Sendable;
|
||||
use yazi_macro::emit;
|
||||
use yazi_shared::{Layer, Source, event::{Action, Cmd}};
|
||||
use yazi_shared::{Layer, Source, event::Action};
|
||||
|
||||
use super::Utils;
|
||||
|
||||
|
|
@ -16,18 +15,6 @@ impl Utils {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn mgr_emit(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|lua, (name, args): (String, Table)| {
|
||||
deprecate!(lua, "ya.mgr_emit() has been deprecated since v25.5.28 and will soon-to-be removed in a future release. \n\nUse ya.emit() in your {} instead, see #2653 for details: https://github.com/sxyazi/yazi/pull/2653");
|
||||
emit!(Call(Action {
|
||||
cmd: Cmd { name: name.into(), args: Sendable::table_to_args(lua, args)? },
|
||||
layer: Layer::Mgr,
|
||||
source: Source::Emit,
|
||||
}));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn exec(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, (name, args): (String, Table)| async move {
|
||||
let mut action = Action::new(name, Source::Emit, Layer::Mgr)?;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ pub fn compose(
|
|||
|
||||
// Call
|
||||
b"emit" => Utils::emit(lua)?,
|
||||
b"mgr_emit" => Utils::mgr_emit(lua)?,
|
||||
b"exec" => Utils::exec(lua)?,
|
||||
|
||||
// Image
|
||||
|
|
|
|||
|
|
@ -1,29 +1,6 @@
|
|||
use core::str;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CharKind {
|
||||
Space,
|
||||
Punct,
|
||||
Other,
|
||||
}
|
||||
|
||||
impl CharKind {
|
||||
pub fn new(c: char) -> Self {
|
||||
if c.is_whitespace() {
|
||||
Self::Space
|
||||
} else if c.is_ascii_punctuation() {
|
||||
Self::Punct
|
||||
} else {
|
||||
Self::Other
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vary(self, other: Self, far: bool) -> bool {
|
||||
if far { (self == Self::Space) != (other == Self::Space) } else { self != other }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn strip_trailing_newline(mut s: String) -> String {
|
||||
while s.ends_with('\n') || s.ends_with('\r') {
|
||||
s.pop();
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ impl Display for DisableDrop {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("\x1b]72;t=A\x1b\\") }
|
||||
}
|
||||
|
||||
/// Confirm drag: `OSC 72 ; t=o:o=operation ST`
|
||||
pub enum ConfirmDrag<M> {
|
||||
/// Agree drag: `OSC 72 ; t=o:o=operation ST`
|
||||
pub enum AgreeDrag<M> {
|
||||
Copy(M),
|
||||
Move(M),
|
||||
Either(M),
|
||||
}
|
||||
|
||||
impl<M: Mimelist> Display for ConfirmDrag<M> {
|
||||
impl<M: Mimelist> Display for AgreeDrag<M> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Copy(mimes) => write!(f, "\x1b]72;t=o:o=1;{}\x1b\\", ListDndMimes(mimes.clone())),
|
||||
|
|
@ -54,14 +54,14 @@ impl<M: Mimelist> Display for ConfirmDrag<M> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Confirm dropped data: `OSC 72 ; t=m:o=O ; MIME list ST`
|
||||
pub enum ConfirmDrop<M> {
|
||||
/// Agree drop: `OSC 72 ; t=m:o=O ; MIME list ST`
|
||||
pub enum AgreeDrop<M> {
|
||||
Reject,
|
||||
Copy(M),
|
||||
Move(M),
|
||||
}
|
||||
|
||||
impl<M: Mimelist> Display for ConfirmDrop<M> {
|
||||
impl<M: Mimelist> Display for AgreeDrop<M> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Reject => write!(f, "\x1b]72;t=m:o=0\x1b\\"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::{self};
|
||||
|
||||
use yazi_macro::ok_or_not_found;
|
||||
use yazi_shared::{strand::{StrandBuf, StrandLike}, url::{AsUrl, UrlBuf, UrlLike}};
|
||||
|
||||
use crate::provider;
|
||||
|
|
@ -12,53 +11,6 @@ pub async fn maybe_exists(url: impl AsUrl) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: deprecate
|
||||
pub async fn unique_name<F>(u: UrlBuf, append: F) -> io::Result<UrlBuf>
|
||||
where
|
||||
F: Future<Output = bool>,
|
||||
{
|
||||
match provider::symlink_metadata(&u).await {
|
||||
Ok(_) => _unique_name(u, append.await).await,
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(u),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
async fn _unique_name(mut url: UrlBuf, append: bool) -> io::Result<UrlBuf> {
|
||||
let Some(stem) = url.stem().map(|s| s.to_owned()) else {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidInput, "empty file stem"));
|
||||
};
|
||||
|
||||
let dot_ext = match url.ext() {
|
||||
Some(e) => {
|
||||
let mut s = StrandBuf::with_capacity(url.kind(), e.len() + 1);
|
||||
s.push_str(".");
|
||||
s.try_push(e)?;
|
||||
s
|
||||
}
|
||||
None => StrandBuf::default(),
|
||||
};
|
||||
|
||||
let mut name = StrandBuf::with_capacity(url.kind(), stem.len() + dot_ext.len() + 5);
|
||||
for i in 1u64.. {
|
||||
name.clear();
|
||||
name.try_push(&stem)?;
|
||||
|
||||
if append {
|
||||
name.try_push(&dot_ext)?;
|
||||
name.push_str(format!("_{i}"));
|
||||
} else {
|
||||
name.push_str(format!("_{i}"));
|
||||
name.try_push(&dot_ext)?;
|
||||
}
|
||||
|
||||
url.try_set_name(&name)?;
|
||||
ok_or_not_found!(provider::symlink_metadata(&url).await, break);
|
||||
}
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
pub async fn unique_file(u: UrlBuf, is_dir: bool) -> io::Result<UrlBuf> {
|
||||
let result = if is_dir {
|
||||
provider::create_dir(&u).await
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_shared::{CharKind, data::Data};
|
||||
use yazi_macro::act;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::input::{Input, parser::BackwardOpt};
|
||||
use crate::input::{CharKind, Input, parser::BackwardOpt};
|
||||
|
||||
impl Input {
|
||||
pub fn backward(&mut self, opt: BackwardOpt) -> Result<Data> {
|
||||
|
|
@ -16,15 +16,12 @@ impl Input {
|
|||
let mut prev = CharKind::new(it.next().unwrap().1);
|
||||
for (i, c) in it {
|
||||
let k = CharKind::new(c);
|
||||
if prev != CharKind::Space && prev.vary(k, opt.far) {
|
||||
if prev != CharKind::Space && prev.vary(k, opt.gait) {
|
||||
return act!(r#move, self, -(i as isize));
|
||||
}
|
||||
prev = k;
|
||||
}
|
||||
|
||||
if prev != CharKind::Space {
|
||||
act!(r#move, self, -(snap.len() as isize))?;
|
||||
}
|
||||
succ!();
|
||||
act!(r#move, self, -(snap.len() as isize))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::act;
|
||||
use yazi_shared::{CharKind, data::Data};
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::input::{Input, op::InputOp, parser::ForwardOpt};
|
||||
use crate::input::{CharKind, Input, op::InputOp, parser::ForwardOpt};
|
||||
|
||||
impl Input {
|
||||
pub fn forward(&mut self, opt: ForwardOpt) -> Result<Data> {
|
||||
|
|
@ -16,9 +16,9 @@ impl Input {
|
|||
for (i, c) in it {
|
||||
let k = CharKind::new(c);
|
||||
let b = if opt.end_of_word {
|
||||
prev != CharKind::Space && prev.vary(k, opt.far) && i != 1
|
||||
prev != CharKind::Space && prev.vary(k, opt.gait) && i != 1
|
||||
} else {
|
||||
k != CharKind::Space && k.vary(prev, opt.far)
|
||||
k != CharKind::Space && k.vary(prev, opt.gait)
|
||||
};
|
||||
if b && !matches!(snap.op, InputOp::None | InputOp::Select(_)) {
|
||||
return act!(r#move, self, i as isize);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use std::ops::RangeBounds;
|
|||
|
||||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_shared::{CharKind, data::Data};
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::input::{Input, parser::KillOpt};
|
||||
use crate::input::{CharKind, Input, parser::KillOpt};
|
||||
|
||||
impl Input {
|
||||
pub fn kill(&mut self, opt: KillOpt) -> Result<Data> {
|
||||
|
|
|
|||
37
yazi-widgets/src/input/chars.rs
Normal file
37
yazi-widgets/src/input/chars.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use crate::input::Gait;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub(crate) enum CharKind {
|
||||
Space,
|
||||
Punct,
|
||||
Other,
|
||||
}
|
||||
|
||||
impl CharKind {
|
||||
pub(crate) fn new(c: char) -> Self {
|
||||
if c.is_whitespace() {
|
||||
Self::Space
|
||||
} else if Self::is_punct(c) {
|
||||
Self::Punct
|
||||
} else {
|
||||
Self::Other
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn vary(self, other: Self, gait: Gait) -> bool {
|
||||
match gait {
|
||||
Gait::Fine => self != other,
|
||||
Gait::Lean => self == Self::Other && other != Self::Other,
|
||||
Gait::Wide => (self == Self::Space) != (other == Self::Space),
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_punct(c: char) -> bool {
|
||||
match c {
|
||||
'_' => false,
|
||||
c if c.is_ascii_punctuation() => true,
|
||||
'!' | ',' | ';' | '?' => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
10
yazi-widgets/src/input/gait.rs
Normal file
10
yazi-widgets/src/input/gait.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum Gait {
|
||||
#[default]
|
||||
Fine,
|
||||
Lean,
|
||||
Wide,
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
yazi_macro::mod_pub!(actor parser);
|
||||
|
||||
yazi_macro::mod_flat!(event input mode op option snap snaps widget);
|
||||
yazi_macro::mod_flat!(chars event gait input mode op option snap snaps widget);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,33 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
use crate::input::Gait;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BackwardOpt {
|
||||
pub far: bool,
|
||||
#[serde(alias = "0", default)]
|
||||
pub gait: Gait,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for BackwardOpt {
|
||||
fn from(a: ActionCow) -> Self { Self { far: a.bool("far") } }
|
||||
impl TryFrom<ActionCow> for BackwardOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
|
||||
// TODO: remove
|
||||
if a.bool("far") {
|
||||
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
if !WARNED.swap(true, std::sync::atomic::Ordering::Relaxed) {
|
||||
yazi_macro::emit!(Call(yazi_shared::event::Action::new_relay("app:deprecate").with(
|
||||
"content",
|
||||
"`backward --far` is deprecated, use `backward wide` under `[input]` instead".to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
return Ok(Self { gait: Gait::Wide });
|
||||
}
|
||||
Ok(a.deserialize()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for BackwardOpt {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,36 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
|
||||
use serde::Deserialize;
|
||||
use yazi_shared::event::ActionCow;
|
||||
|
||||
#[derive(Debug)]
|
||||
use crate::input::Gait;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct ForwardOpt {
|
||||
pub far: bool,
|
||||
#[serde(alias = "0", default)]
|
||||
pub gait: Gait,
|
||||
#[serde(default)]
|
||||
pub end_of_word: bool,
|
||||
}
|
||||
|
||||
impl From<ActionCow> for ForwardOpt {
|
||||
fn from(a: ActionCow) -> Self { Self { far: a.bool("far"), end_of_word: a.bool("end-of-word") } }
|
||||
impl TryFrom<ActionCow> for ForwardOpt {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(a: ActionCow) -> Result<Self, Self::Error> {
|
||||
// TODO: remove
|
||||
if a.bool("far") {
|
||||
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
if !WARNED.swap(true, std::sync::atomic::Ordering::Relaxed) {
|
||||
yazi_macro::emit!(Call(yazi_shared::event::Action::new_relay("app:deprecate").with(
|
||||
"content",
|
||||
"`forward --far` is deprecated, use `forward wide` under `[input]` instead".to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
return Ok(Self { gait: Gait::Wide, end_of_word: a.bool("end-of-word") });
|
||||
}
|
||||
Ok(a.deserialize()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromLua for ForwardOpt {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue