mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: invalid UTF-8 support to Command:arg() and Command:env() APIs (#2895)
This commit is contained in:
parent
750ca0c0d4
commit
1a6abae974
4 changed files with 56 additions and 42 deletions
|
|
@ -139,7 +139,7 @@ impl UserData for Url {
|
|||
});
|
||||
|
||||
methods.add_function_mut("into_search", |_, (ud, frag): (AnyUserData, mlua::String)| {
|
||||
Ok(Self::new(ud.take::<Self>()?.inner.into_search(frag.as_bytes().as_ref().into_os_str()?)))
|
||||
Ok(Self::new(ud.take::<Self>()?.inner.into_search(frag.as_bytes().into_os_str()?)))
|
||||
});
|
||||
|
||||
methods.add_meta_method(MetaMethod::Eq, |_, me, other: UrlRef| Ok(me.inner == other.inner));
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
use std::{borrow::Cow, collections::HashMap};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use tracing::error;
|
||||
use yazi_macro::render;
|
||||
use yazi_shared::{event::CmdCow, url::Url};
|
||||
use yazi_shared::event::{CmdCow, Data, DataKey};
|
||||
|
||||
use crate::{mgr::{LINKED, Mgr}, tasks::Tasks};
|
||||
|
||||
pub struct Opt {
|
||||
updates: HashMap<Cow<'static, str>, Cow<'static, str>>,
|
||||
updates: HashMap<DataKey, Data>,
|
||||
}
|
||||
|
||||
impl TryFrom<CmdCow> for Opt {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(mut c: CmdCow) -> Result<Self, Self::Error> {
|
||||
Ok(Self { updates: c.try_take("updates").ok_or(())?.into_dict_string() })
|
||||
Ok(Self { updates: c.try_take("updates").and_then(Data::into_dict).ok_or(())? })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ impl Mgr {
|
|||
let updates = opt
|
||||
.updates
|
||||
.into_iter()
|
||||
.flat_map(|(url, mime)| Url::try_from(url.as_ref()).map(|u| (u, mime)))
|
||||
.flat_map(|(key, value)| key.into_url().zip(value.into_string()))
|
||||
.filter(|(url, mime)| self.mimetype.by_url(url) != Some(mime))
|
||||
.fold(HashMap::new(), |mut map, (u, m)| {
|
||||
for u in linked.from_file(&u) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::{any::TypeId, io, process::Stdio};
|
|||
use mlua::{AnyUserData, ExternalError, IntoLuaMulti, Lua, MetaMethod, Table, UserData, Value};
|
||||
use tokio::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
use yazi_binding::Error;
|
||||
use yazi_shared::IntoOsStr;
|
||||
|
||||
use super::{Child, output::Output};
|
||||
use crate::process::Status;
|
||||
|
|
@ -143,11 +144,11 @@ impl UserData for Command {
|
|||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
match arg {
|
||||
Value::String(s) => {
|
||||
me.inner.arg(String::from_utf8_lossy(&s.as_bytes()).as_ref());
|
||||
me.inner.arg(s.as_bytes().into_os_str()?);
|
||||
}
|
||||
Value::Table(t) => {
|
||||
for s in t.sequence_values::<mlua::String>() {
|
||||
me.inner.arg(String::from_utf8_lossy(&s?.as_bytes()).as_ref());
|
||||
me.inner.arg(s?.as_bytes().into_os_str()?);
|
||||
}
|
||||
}
|
||||
_ => return Err("arg must be a string or table of strings".into_lua_err()),
|
||||
|
|
@ -162,10 +163,9 @@ impl UserData for Command {
|
|||
methods.add_function_mut(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.env(
|
||||
String::from_utf8_lossy(&key.as_bytes()).as_ref(),
|
||||
String::from_utf8_lossy(&value.as_bytes()).as_ref(),
|
||||
);
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(key.as_bytes().into_os_str()?, value.as_bytes().into_os_str()?);
|
||||
Ok(ud)
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,32 @@ impl Data {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_string(self) -> Option<Cow<'static, str>> {
|
||||
match self {
|
||||
Self::String(s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_dict(self) -> Option<HashMap<DataKey, Data>> {
|
||||
match self {
|
||||
Self::Dict(d) => Some(d),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_url(self) -> Option<Url> {
|
||||
match self {
|
||||
Self::String(s) => Url::try_from(s.as_ref()).ok(),
|
||||
Self::Url(u) => Some(u),
|
||||
Self::Bytes(b) => Url::try_from(b.as_slice()).ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_any<T: 'static>(self) -> Option<T> {
|
||||
match self {
|
||||
|
|
@ -54,34 +80,12 @@ impl Data {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_url(self) -> Option<Url> {
|
||||
match self {
|
||||
Data::String(s) => Url::try_from(s.as_ref()).ok(),
|
||||
Data::Url(u) => Some(u),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_dict_string(self) -> HashMap<Cow<'static, str>, Cow<'static, str>> {
|
||||
let Self::Dict(dict) = self else {
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
let mut map = HashMap::with_capacity(dict.len());
|
||||
for pair in dict {
|
||||
if let (DataKey::String(k), Self::String(v)) = pair {
|
||||
map.insert(k, v);
|
||||
}
|
||||
}
|
||||
map
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_url(&self) -> Option<Url> {
|
||||
match self {
|
||||
Self::String(s) => Url::try_from(s.as_ref()).ok(),
|
||||
Self::Url(u) => Some(u.clone()),
|
||||
Self::Bytes(b) => Url::try_from(b.as_slice()).ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -158,6 +162,16 @@ impl DataKey {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_url(self) -> Option<Url> {
|
||||
match self {
|
||||
Self::String(s) => Url::try_from(s.as_ref()).ok(),
|
||||
Self::Url(u) => Some(u),
|
||||
Self::Bytes(b) => Url::try_from(b.as_slice()).ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_integer<'de, D>(deserializer: D) -> Result<i64, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
|
|
@ -204,9 +218,9 @@ macro_rules! impl_as_integer {
|
|||
#[inline]
|
||||
pub fn $name(&self) -> Option<$t> {
|
||||
match self {
|
||||
Data::Integer(i) => <$t>::try_from(*i).ok(),
|
||||
Data::String(s) => s.parse().ok(),
|
||||
Data::Id(i) => <$t>::try_from(i.get()).ok(),
|
||||
Self::Integer(i) => <$t>::try_from(*i).ok(),
|
||||
Self::String(s) => s.parse().ok(),
|
||||
Self::Id(i) => <$t>::try_from(i.get()).ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -220,10 +234,10 @@ macro_rules! impl_as_number {
|
|||
#[inline]
|
||||
pub fn $name(&self) -> Option<$t> {
|
||||
match self {
|
||||
Data::Integer(i) if *i == (*i as $t as _) => Some(*i as $t),
|
||||
Data::Number(n) => <$t>::try_from(*n).ok(),
|
||||
Data::String(s) => s.parse().ok(),
|
||||
Data::Id(i) if i.0 == (i.0 as $t as _) => Some(i.0 as $t),
|
||||
Self::Integer(i) if *i == (*i as $t as _) => Some(*i as $t),
|
||||
Self::Number(n) => <$t>::try_from(*n).ok(),
|
||||
Self::String(s) => s.parse().ok(),
|
||||
Self::Id(i) if i.0 == (i.0 as $t as _) => Some(i.0 as $t),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue