mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: split ya send into ya pub and ya pub-static to make it more ergonomic (#933)
This commit is contained in:
parent
55da9e342c
commit
68da8998aa
10 changed files with 129 additions and 56 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2734,6 +2734,7 @@ dependencies = [
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"clap_complete_fig",
|
"clap_complete_fig",
|
||||||
"clap_complete_nushell",
|
"clap_complete_nushell",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
"yazi-dds",
|
"yazi-dds",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,18 @@ pub struct Args {
|
||||||
pub chooser_file: Option<PathBuf>,
|
pub chooser_file: Option<PathBuf>,
|
||||||
|
|
||||||
/// Clear the cache directory
|
/// Clear the cache directory
|
||||||
#[arg(long, action)]
|
#[arg(long)]
|
||||||
pub clear_cache: bool,
|
pub clear_cache: bool,
|
||||||
|
|
||||||
/// Report the specified local events to stdout
|
/// Report the specified local events to stdout
|
||||||
#[arg(long, action)]
|
#[arg(long)]
|
||||||
pub local_events: Option<String>,
|
pub local_events: Option<String>,
|
||||||
/// Report the specified remote events to stdout
|
/// Report the specified remote events to stdout
|
||||||
#[arg(long, action)]
|
#[arg(long)]
|
||||||
pub remote_events: Option<String>,
|
pub remote_events: Option<String>,
|
||||||
|
|
||||||
/// Print debug information
|
/// Print debug information
|
||||||
#[arg(long, action)]
|
#[arg(long)]
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
|
|
||||||
/// Print version
|
/// Print version
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,18 @@ repository = "https://github.com/sxyazi/yazi"
|
||||||
yazi-dds = { path = "../yazi-dds", version = "0.2.4" }
|
yazi-dds = { path = "../yazi-dds", version = "0.2.4" }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = "1.0.82"
|
anyhow = "1.0.82"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
tokio = { version = "1.37.0", features = [ "full" ] }
|
serde_json = "1.0.116"
|
||||||
|
tokio = { version = "1.37.0", features = [ "full" ] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
anyhow = "1.0.82"
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
clap_complete = "4.5.2"
|
clap_complete = "4.5.2"
|
||||||
clap_complete_nushell = "4.5.1"
|
|
||||||
clap_complete_fig = "4.5.0"
|
clap_complete_fig = "4.5.0"
|
||||||
|
clap_complete_nushell = "4.5.1"
|
||||||
|
serde_json = "1.0.116"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "ya"
|
name = "ya"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use anyhow::{bail, Result};
|
||||||
use clap::{command, Parser, Subcommand};
|
use clap::{command, Parser, Subcommand};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "ya",version, about, long_about = None)]
|
#[command(name = "ya", version, about, long_about = None)]
|
||||||
#[command(propagate_version = true)]
|
#[command(propagate_version = true)]
|
||||||
pub(super) struct Args {
|
pub(super) struct Args {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
|
|
@ -10,11 +13,66 @@ pub(super) struct Args {
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub(super) enum Command {
|
pub(super) enum Command {
|
||||||
/// Send a message to remote instances.
|
/// Publish a message to remote instance(s).
|
||||||
Send(CommandSend),
|
Pub(CommandPub),
|
||||||
|
/// Publish a static message to all remote instances.
|
||||||
|
PubStatic(CommandPubStatic),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
pub(super) struct CommandSend {
|
pub(super) struct CommandPub {
|
||||||
pub(super) message: String,
|
/// The receiver ID.
|
||||||
|
#[arg(index = 1)]
|
||||||
|
pub(super) receiver: u64,
|
||||||
|
/// The kind of message.
|
||||||
|
#[arg(index = 2)]
|
||||||
|
pub(super) kind: String,
|
||||||
|
/// Send the message with a string body.
|
||||||
|
#[arg(long)]
|
||||||
|
pub(super) str: Option<String>,
|
||||||
|
/// Send the message with a JSON body.
|
||||||
|
#[arg(long)]
|
||||||
|
pub(super) json: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandPub {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(super) fn body(&self) -> Result<Cow<str>> {
|
||||||
|
if let Some(json) = &self.json {
|
||||||
|
Ok(json.into())
|
||||||
|
} else if let Some(str) = &self.str {
|
||||||
|
Ok(serde_json::to_string(str)?.into())
|
||||||
|
} else {
|
||||||
|
bail!("No body provided");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
pub(super) struct CommandPubStatic {
|
||||||
|
/// The severity of the message.
|
||||||
|
#[arg(index = 1)]
|
||||||
|
pub(super) severity: u16,
|
||||||
|
/// The kind of message.
|
||||||
|
#[arg(index = 2)]
|
||||||
|
pub(super) kind: String,
|
||||||
|
/// Send the message with a string body.
|
||||||
|
#[arg(long)]
|
||||||
|
pub(super) str: Option<String>,
|
||||||
|
/// Send the message with a JSON body.
|
||||||
|
#[arg(long)]
|
||||||
|
pub(super) json: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandPubStatic {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(super) fn body(&self) -> Result<Cow<str>> {
|
||||||
|
if let Some(json) = &self.json {
|
||||||
|
Ok(json.into())
|
||||||
|
} else if let Some(str) = &self.str {
|
||||||
|
Ok(serde_json::to_string(str)?.into())
|
||||||
|
} else {
|
||||||
|
bail!("No body provided");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,16 @@ async fn main() -> anyhow::Result<()> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
match &args.command {
|
match &args.command {
|
||||||
Command::Send(cmd) => {
|
Command::Pub(cmd) => {
|
||||||
yazi_dds::init();
|
yazi_dds::init();
|
||||||
if let Err(e) = yazi_dds::Client::shot(&cmd.message).await {
|
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, cmd.receiver, None, &cmd.body()?).await {
|
||||||
|
eprintln!("Cannot send message: {e}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command::PubStatic(cmd) => {
|
||||||
|
yazi_dds::init();
|
||||||
|
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, 0, Some(cmd.severity), &cmd.body()?).await {
|
||||||
eprintln!("Cannot send message: {e}");
|
eprintln!("Cannot send message: {e}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ tab_width = 1
|
||||||
# Count
|
# Count
|
||||||
count_copied = { fg = "white", bg = "green" }
|
count_copied = { fg = "white", bg = "green" }
|
||||||
count_cut = { fg = "white", bg = "red" }
|
count_cut = { fg = "white", bg = "red" }
|
||||||
count_selected = { fg = "white", bg = "blue" }
|
count_selected = { fg = "white", bg = "yellow" }
|
||||||
|
|
||||||
# Border
|
# Border
|
||||||
border_symbol = "│"
|
border_symbol = "│"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use mlua::{ExternalResult, IntoLua, Lua, Value};
|
use mlua::{ExternalResult, IntoLua, Lua, Value};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
|
@ -40,15 +40,9 @@ impl Body<'static> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_lua(kind: &str, value: Value) -> Result<Self> {
|
pub fn from_lua(kind: &str, value: Value) -> mlua::Result<Self> {
|
||||||
Ok(match kind {
|
Self::validate(kind).into_lua_err()?;
|
||||||
"hi" | "hey" | "bye" | "cd" | "hover" | "rename" | "bulk" | "yank" | "move" | "trash"
|
BodyCustom::from_lua(kind, value)
|
||||||
| "delete" => Err("Cannot construct system event").into_lua_err()?,
|
|
||||||
_ if !kind.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-') => {
|
|
||||||
Err("Kind must be alphanumeric with dashes").into_lua_err()?
|
|
||||||
}
|
|
||||||
_ => BodyCustom::from_lua(kind, value)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tab(kind: &str, body: &str) -> usize {
|
pub fn tab(kind: &str, body: &str) -> usize {
|
||||||
|
|
@ -65,6 +59,27 @@ impl Body<'static> {
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validate(kind: &str) -> Result<()> {
|
||||||
|
if matches!(
|
||||||
|
kind,
|
||||||
|
"hi"
|
||||||
|
| "hey" | "bye"
|
||||||
|
| "cd" | "hover"
|
||||||
|
| "rename"
|
||||||
|
| "bulk" | "yank"
|
||||||
|
| "move" | "trash"
|
||||||
|
| "delete"
|
||||||
|
) {
|
||||||
|
bail!("Cannot construct system event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if !kind.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'-') {
|
||||||
|
bail!("Kind must be alphanumeric with dashes");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Body<'a> {
|
impl<'a> Body<'a> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{collections::{HashMap, HashSet}, mem, str::FromStr};
|
use std::{collections::{HashMap, HashSet}, mem, str::FromStr};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::{io::AsyncWriteExt, select, sync::mpsc, task::JoinHandle, time};
|
use tokio::{io::AsyncWriteExt, select, sync::mpsc, task::JoinHandle, time};
|
||||||
|
|
@ -62,16 +62,13 @@ impl Client {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn shot(s: &str) -> Result<()> {
|
pub async fn shot(kind: &str, receiver: u64, severity: Option<u16>, body: &str) -> Result<()> {
|
||||||
let (kind, receiver, sender, body) = Payload::split(s)?;
|
Body::validate(kind)?;
|
||||||
if receiver != 0 && sender <= u16::MAX as u64 {
|
|
||||||
bail!("Sender must be greater than 65535 if receiver is non-zero");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let sender = severity.map(Into::into).unwrap_or(*ID);
|
||||||
let payload = format!(
|
let payload = format!(
|
||||||
"{}\n{kind},{receiver},{sender},{}\n{}\n",
|
"{}\n{kind},{receiver},{sender},{body}\n{}\n",
|
||||||
Payload::new(BodyHi::borrowed(Default::default())),
|
Payload::new(BodyHi::borrowed(Default::default())),
|
||||||
serde_json::to_string(body)?,
|
|
||||||
Payload::new(BodyBye::borrowed())
|
Payload::new(BodyBye::borrowed())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -81,7 +78,7 @@ impl Client {
|
||||||
drop(writer);
|
drop(writer);
|
||||||
|
|
||||||
while let Ok(Some(s)) = lines.next_line().await {
|
while let Ok(Some(s)) = lines.next_line().await {
|
||||||
if matches!(Payload::split(&s), Ok((kind, ..)) if kind == "bye") {
|
if matches!(s.split(',').next(), Some(kind) if kind == "bye") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,16 @@ impl<'a> Payload<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Payload<'static> {
|
impl Payload<'static> {
|
||||||
pub fn split(s: &str) -> Result<(&str, u64, u64, &str)> {
|
pub(super) fn emit(self) {
|
||||||
|
self.try_flush();
|
||||||
|
emit!(Call(Cmd::new("accept_payload").with_any("payload", self), Layer::App));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Payload<'static> {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut parts = s.splitn(4, ',');
|
let mut parts = s.splitn(4, ',');
|
||||||
|
|
||||||
let kind = parts.next().ok_or_else(|| anyhow!("empty kind"))?;
|
let kind = parts.next().ok_or_else(|| anyhow!("empty kind"))?;
|
||||||
|
|
@ -62,20 +71,6 @@ impl Payload<'static> {
|
||||||
|
|
||||||
let body = parts.next().ok_or_else(|| anyhow!("empty body"))?;
|
let body = parts.next().ok_or_else(|| anyhow!("empty body"))?;
|
||||||
|
|
||||||
Ok((kind, receiver, sender, body))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn emit(self) {
|
|
||||||
self.try_flush();
|
|
||||||
emit!(Call(Cmd::new("accept_payload").with_any("payload", self), Layer::App));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Payload<'static> {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let (kind, receiver, sender, body) = Self::split(s)?;
|
|
||||||
Ok(Self { receiver, sender, body: Body::from_str(kind, body)? })
|
Ok(Self { receiver, sender, body: Body::from_str(kind, body)? })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ impl Pubsub {
|
||||||
ps.raw_set(
|
ps.raw_set(
|
||||||
"pub",
|
"pub",
|
||||||
lua.create_function(|_, (kind, value): (mlua::String, Value)| {
|
lua.create_function(|_, (kind, value): (mlua::String, Value)| {
|
||||||
yazi_dds::Pubsub::pub_(Body::from_lua(kind.to_str()?, value).into_lua_err()?);
|
yazi_dds::Pubsub::pub_(Body::from_lua(kind.to_str()?, value)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?,
|
})?,
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -20,7 +20,7 @@ impl Pubsub {
|
||||||
ps.raw_set(
|
ps.raw_set(
|
||||||
"pub_to",
|
"pub_to",
|
||||||
lua.create_function(|_, (receiver, kind, value): (u64, mlua::String, Value)| {
|
lua.create_function(|_, (receiver, kind, value): (u64, mlua::String, Value)| {
|
||||||
yazi_dds::Pubsub::pub_to(receiver, Body::from_lua(kind.to_str()?, value).into_lua_err()?);
|
yazi_dds::Pubsub::pub_to(receiver, Body::from_lua(kind.to_str()?, value)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?,
|
})?,
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -28,10 +28,7 @@ impl Pubsub {
|
||||||
ps.raw_set(
|
ps.raw_set(
|
||||||
"pub_static",
|
"pub_static",
|
||||||
lua.create_function(|_, (severity, kind, value): (u16, mlua::String, Value)| {
|
lua.create_function(|_, (severity, kind, value): (u16, mlua::String, Value)| {
|
||||||
yazi_dds::Pubsub::pub_static(
|
yazi_dds::Pubsub::pub_static(severity, Body::from_lua(kind.to_str()?, value)?);
|
||||||
severity,
|
|
||||||
Body::from_lua(kind.to_str()?, value).into_lua_err()?,
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?,
|
})?,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue