This commit is contained in:
sxyazi 2024-04-19 13:40:10 +08:00
parent 79d61248dd
commit 0ebba0f628
No known key found for this signature in database
16 changed files with 97 additions and 111 deletions

View file

@ -10,21 +10,24 @@ where
{
struct RunVisitor;
#[allow(clippy::explicit_counter_loop)]
fn parse(s: &str) -> Result<Cmd> {
let mut args = shell_words::split(s)?;
if args.is_empty() {
bail!("`run` cannot be empty");
}
let mut cmd = Cmd { name: mem::take(&mut args[0]), ..Default::default() };
for (i, arg) in args.into_iter().skip(1).enumerate() {
if !arg.starts_with("--") {
let mut i = 0usize;
for arg in args.into_iter().skip(1) {
let Some(arg) = arg.strip_prefix("--") else {
cmd.args.insert(i.to_string(), Data::String(arg));
i += 1;
continue;
}
};
let mut parts = arg.splitn(2, '=');
let key = parts.next().unwrap().trim_start_matches('-').to_owned();
let Some(key) = parts.next().map(|s| s.to_owned()) else {
bail!("invalid argument: {arg}");
};
if let Some(val) = parts.next() {
cmd.args.insert(key, Data::String(val.to_owned()));
} else {

View file

@ -16,9 +16,7 @@ pub struct Opt {
impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
// cache: mem::take(&mut c.args),
// TODO: Fix this
cache: vec![],
cache: c.take_any("cache").unwrap_or_default(),
cache_name: c.take_str("cache-name").unwrap_or_default(),
word: c.take_str("word").unwrap_or_default(),
ticket: c.take_str("ticket").and_then(|v| v.parse().ok()).unwrap_or(0),
@ -65,7 +63,7 @@ impl Completion {
}
if !opt.cache.is_empty() {
self.caches.insert(opt.cache_name.to_owned(), opt.cache.clone());
self.caches.insert(opt.cache_name.to_owned(), opt.cache);
}
let Some(cache) = self.caches.get(&opt.cache_name) else {
return;

View file

@ -57,7 +57,8 @@ impl Completion {
if !cache.is_empty() {
emit!(Call(
Cmd::args("show", cache)
Cmd::new("show")
.with_any("cache", cache)
.with("cache-name", parent)
.with("word", child)
.with("ticket", ticket),

View file

@ -1,10 +1,24 @@
use yazi_proxy::options::InputOpt;
use yazi_shared::render;
use tokio::sync::mpsc;
use yazi_config::popup::InputCfg;
use yazi_shared::{event::Cmd, render, InputError};
use crate::input::Input;
pub struct Opt {
cfg: InputCfg,
tx: mpsc::UnboundedSender<Result<String, InputError>>,
}
impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { cfg: c.take_any("cfg").ok_or(())?, tx: c.take_any("tx").ok_or(())? })
}
}
impl Input {
pub fn show(&mut self, opt: impl TryInto<InputOpt>) {
pub fn show(&mut self, opt: impl TryInto<Opt>) {
let Ok(opt) = opt.try_into() else { return };
self.close(false);

View file

@ -1,10 +1,24 @@
use yazi_proxy::options::SelectOpt;
use yazi_shared::render;
use tokio::sync::oneshot;
use yazi_config::popup::SelectCfg;
use yazi_shared::{event::Cmd, render};
use crate::select::Select;
pub struct Opt {
cfg: SelectCfg,
tx: oneshot::Sender<anyhow::Result<usize>>,
}
impl TryFrom<Cmd> for Opt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> {
Ok(Self { cfg: c.take_any("cfg").ok_or(())?, tx: c.take_any("tx").ok_or(())? })
}
}
impl Select {
pub fn show(&mut self, opt: impl TryInto<SelectOpt>) {
pub fn show(&mut self, opt: impl TryInto<Opt>) {
let Ok(opt) = opt.try_into() else {
return;
};

View file

@ -15,7 +15,7 @@ impl Sendable {
Value::Number(n) => Data::Number(n),
Value::String(s) => Data::String(s.to_str()?.to_owned()),
Value::Table(t) => {
let mut map = HashMap::with_capacity(t.len().map(|l| l as usize)?);
let mut map = HashMap::with_capacity(t.raw_len());
for result in t.pairs::<Value, Value>() {
let (k, v) = result?;
map.insert(Self::value_to_key(k)?, Self::value_to_data(v)?);
@ -98,7 +98,13 @@ impl Sendable {
Value::Table(_) => Err("table is not supported".into_lua_err())?,
Value::Function(_) => Err("function is not supported".into_lua_err())?,
Value::Thread(_) => Err("thread is not supported".into_lua_err())?,
Value::UserData(_) => Err("userdata is not supported".into_lua_err())?,
Value::UserData(ud) => {
if let Ok(t) = ud.take::<yazi_shared::fs::Url>() {
DataKey::Url(t)
} else {
Err("unsupported userdata included".into_lua_err())?
}
}
Value::Error(_) => Err("error is not supported".into_lua_err())?,
})
}
@ -110,6 +116,7 @@ impl Sendable {
DataKey::Integer(k) => Value::Integer(k),
DataKey::Number(k) => Value::Number(k.get()),
DataKey::String(k) => Value::String(lua.create_string(k)?),
DataKey::Url(k) => Value::UserData(lua.create_any_userdata(k)?),
})
}
}

View file

@ -26,7 +26,7 @@ impl TryFrom<Cmd> for Opt {
c.take_any::<Vec<Data>>("args").unwrap_or_default()
};
Ok(Self { name, sync: c.get_bool("sync"), args, cb: c.take_any::<OptCallback>("callback") })
Ok(Self { name, sync: c.get_bool("sync"), args, cb: c.take_any("callback") })
}
}

View file

@ -1,54 +1,27 @@
use std::collections::HashMap;
use mlua::{ExternalError, Lua, Table, Value};
use yazi_shared::{emit, event::Cmd, render, Layer};
use yazi_dds::Sendable;
use yazi_shared::{emit, event::{Cmd, Data}, render, Layer};
use super::Utils;
impl Utils {
fn parse_args(t: Table) -> mlua::Result<(Vec<String>, HashMap<String, String>)> {
let mut args = vec![];
let mut named = HashMap::new();
for result in t.pairs::<Value, Value>() {
let (k, v) = result?;
fn parse_args(t: Table) -> mlua::Result<HashMap<String, Data>> {
let mut args = HashMap::with_capacity(t.raw_len());
for pair in t.pairs::<Value, Value>() {
let (k, v) = pair?;
match k {
Value::Integer(_) => {
args.push(match v {
Value::Integer(i) => i.to_string(),
Value::Number(n) => n.to_string(),
Value::String(s) => s.to_string_lossy().into_owned(),
_ => return Err("invalid value in cmd".into_lua_err()),
});
Value::Integer(i) if i > 0 => {
args.insert((i - 1).to_string(), Sendable::value_to_data(v)?);
}
Value::String(s) => {
let v = match v {
Value::Boolean(b) if b => String::new(),
Value::Boolean(b) if !b => continue,
Value::Integer(i) => i.to_string(),
Value::Number(n) => n.to_string(),
Value::String(s) => s.to_string_lossy().into_owned(),
_ => return Err("invalid value in cmd".into_lua_err()),
};
named.insert(s.to_str()?.replace('_', "-"), v);
args.insert(s.to_str()?.replace('_', "-"), Sendable::value_to_data(v)?);
}
_ => return Err("invalid key in cmd".into_lua_err()),
}
}
Ok((args, named))
}
#[inline]
fn create_cmd(name: String, args: Value) -> mlua::Result<Cmd> {
// TODO: Fix this
return Ok(Cmd { name, args: Default::default() });
// let (args, named) = Self::parse_args(table)?;
// let mut cmd = Cmd { name, args, named, ..Default::default() };
// if let Some(data) = data.and_then(|v| ValueSendable::try_from(v).ok()) {
// cmd = cmd.with_data(data);
// }
// Ok(cmd)
Ok(args)
}
pub(super) fn call(lua: &Lua, ya: &Table) -> mlua::Result<()> {
@ -62,16 +35,16 @@ impl Utils {
ya.raw_set(
"app_emit",
lua.create_function(|_, (name, args): (String, Value)| {
emit!(Call(Self::create_cmd(name, args)?, Layer::App));
lua.create_function(|_, (name, args): (String, Table)| {
emit!(Call(Cmd { name, args: Self::parse_args(args)? }, Layer::App));
Ok(())
})?,
)?;
ya.raw_set(
"manager_emit",
lua.create_function(|_, (name, args): (String, Value)| {
emit!(Call(Self::create_cmd(name, args)?, Layer::Manager));
lua.create_function(|_, (name, args): (String, Table)| {
emit!(Call(Cmd { name, args: Self::parse_args(args)? }, Layer::Manager));
Ok(())
})?,
)?;

View file

@ -46,8 +46,8 @@ impl Utils {
emit!(Call(
Cmd::new("show")
.with("layer", Layer::Which)
.with_bool("silent", t.raw_get("silent").unwrap_or_default())
.with_any("candidates", cands),
.with_any("candidates", cands)
.with_bool("silent", t.raw_get("silent").unwrap_or_default()),
Layer::Which
));

View file

@ -2,15 +2,13 @@ use tokio::sync::mpsc;
use yazi_config::popup::InputCfg;
use yazi_shared::{emit, event::Cmd, InputError, Layer};
use crate::options::InputOpt;
pub struct InputProxy;
impl InputProxy {
#[inline]
pub fn show(cfg: InputCfg) -> mpsc::UnboundedReceiver<Result<String, InputError>> {
let (tx, rx) = mpsc::unbounded_channel();
emit!(Call(Cmd::new("show").with_any("option", InputOpt { cfg, tx }), Layer::Input));
emit!(Call(Cmd::new("show").with_any("tx", tx).with_any("cfg", cfg), Layer::Input));
rx
}

View file

@ -1,14 +0,0 @@
use tokio::sync::mpsc;
use yazi_config::popup::InputCfg;
use yazi_shared::{event::Cmd, InputError};
pub struct InputOpt {
pub cfg: InputCfg,
pub tx: mpsc::UnboundedSender<Result<String, InputError>>,
}
impl TryFrom<Cmd> for InputOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -1,11 +1,7 @@
mod input;
mod notify;
mod open;
mod process;
mod select;
pub use input::*;
pub use notify::*;
pub use open::*;
pub use process::*;
pub use select::*;

View file

@ -1,14 +0,0 @@
use tokio::sync::oneshot;
use yazi_config::popup::SelectCfg;
use yazi_shared::event::Cmd;
pub struct SelectOpt {
pub cfg: SelectCfg,
pub tx: oneshot::Sender<anyhow::Result<usize>>,
}
impl TryFrom<Cmd> for SelectOpt {
type Error = ();
fn try_from(mut c: Cmd) -> Result<Self, Self::Error> { c.take_any("option").ok_or(()) }
}

View file

@ -2,15 +2,13 @@ use tokio::sync::oneshot;
use yazi_config::popup::SelectCfg;
use yazi_shared::{emit, event::Cmd, Layer};
use crate::options::SelectOpt;
pub struct SelectProxy;
impl SelectProxy {
#[inline]
pub async fn show(cfg: SelectCfg) -> anyhow::Result<usize> {
let (tx, rx) = oneshot::channel();
emit!(Call(Cmd::new("show").with_any("option", SelectOpt { cfg, tx }), Layer::Select));
emit!(Call(Cmd::new("show").with_any("tx", tx).with_any("cfg", cfg), Layer::Select));
rx.await?
}
}

View file

@ -71,13 +71,14 @@ impl Cmd {
}
pub fn shallow_clone(&self) -> Self {
let args = self
.args
.iter()
.filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), Data::String(s.to_owned()))))
.collect();
Self { name: self.name.clone(), args }
Self {
name: self.name.clone(),
args: self
.args
.iter()
.filter_map(|(k, v)| v.shallow_clone().map(|v| (k.clone(), v)))
.collect(),
}
}
}

View file

@ -48,7 +48,7 @@ impl Data {
#[inline]
pub fn into_any<T: 'static>(self) -> Option<T> {
match self {
Data::Any(b) => b.downcast::<T>().ok().map(|b| *b),
Self::Any(b) => b.downcast::<T>().ok().map(|b| *b),
_ => None,
}
}
@ -66,6 +66,15 @@ impl Data {
}
map
}
#[inline]
pub fn shallow_clone(&self) -> Option<Self> {
match self {
Self::Boolean(b) => Some(Self::Boolean(*b)),
Self::String(s) => Some(Self::String(s.clone())),
_ => None,
}
}
}
// --- Key
@ -77,6 +86,8 @@ pub enum DataKey {
Integer(i64),
Number(OrderedFloat),
String(String),
#[serde(skip)]
Url(Url),
}
impl DataKey {