Skip to content

Commit

Permalink
feat: new ya emit and ya emit-to subcommands to emit commands to …
Browse files Browse the repository at this point in the history
…a specified instance for execution (#1979)
  • Loading branch information
sxyazi authored Dec 1, 2024
1 parent 91665b7 commit 20dc055
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 58 deletions.
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"0.2","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","Sysinfo","ffprobe","vframes","luma"],"language":"en"}
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","Sysinfo","ffprobe","vframes","luma","obase"],"version":"0.2","language":"en"}
2 changes: 1 addition & 1 deletion yazi-boot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub static BOOT: RoCell<Boot> = RoCell::new();

pub fn init() {
ARGS.with(<_>::parse);
BOOT.init(From::from(&*ARGS));
BOOT.init(<_>::from(&*ARGS));

actions::Actions::act(&ARGS);
}
Expand Down
2 changes: 2 additions & 0 deletions yazi-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ tokio = { workspace = true }
toml_edit = "0.22.22"

[build-dependencies]
yazi-shared = { path = "../yazi-shared", version = "0.3.3" }

# External build dependencies
anyhow = { workspace = true }
clap = { workspace = true }
Expand Down
95 changes: 67 additions & 28 deletions yazi-cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::borrow::Cow;

use anyhow::{Result, bail};
use clap::{Parser, Subcommand, command};
use yazi_shared::event::Cmd;

#[derive(Parser)]
#[command(name = "Ya", about, long_about = None)]
Expand All @@ -16,14 +17,55 @@ pub(super) struct Args {

#[derive(Subcommand)]
pub(super) enum Command {
/// Emit a command to be executed by the current instance.
Emit(CommandEmit),
/// Emit a command to be executed by the specified instance.
EmitTo(CommandEmitTo),
/// Manage packages.
Pack(CommandPack),
/// Publish a message to the current instance.
Pub(CommandPub),
/// Publish a message to the specified instance.
PubTo(CommandPubTo),
/// Subscribe to messages from all remote instances.
Sub(CommandSub),
/// Manage packages.
Pack(CommandPack),
}

#[derive(clap::Args)]
pub(super) struct CommandEmit {
/// The name of the command.
pub(super) name: String,
/// The arguments of the command.
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
pub(super) args: Vec<String>,
}

#[derive(clap::Args)]
pub(super) struct CommandEmitTo {
/// The receiver ID.
pub(super) receiver: u64,
/// The name of the command.
pub(super) name: String,
/// The arguments of the command.
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
pub(super) args: Vec<String>,
}

#[derive(clap::Args)]
#[command(arg_required_else_help = true)]
pub(super) struct CommandPack {
/// Add a package.
#[arg(short = 'a', long)]
pub(super) add: Option<String>,
/// Install all packages.
#[arg(short = 'i', long)]
pub(super) install: bool,
/// List all packages.
#[arg(short = 'l', long)]
pub(super) list: bool,
/// Upgrade all packages.
#[arg(short = 'u', long)]
pub(super) upgrade: bool,
}

#[derive(clap::Args)]
Expand All @@ -44,7 +86,7 @@ pub(super) struct CommandPub {

impl CommandPub {
#[allow(dead_code)]
pub(super) fn receiver(&self) -> Result<u64> {
pub(super) fn receiver() -> Result<u64> {
if let Some(s) = std::env::var("YAZI_PID").ok().filter(|s| !s.is_empty()) {
Ok(s.parse()?)
} else {
Expand Down Expand Up @@ -79,42 +121,39 @@ pub(super) struct CommandSub {
pub(super) kinds: String,
}

#[derive(clap::Args)]
#[command(arg_required_else_help = true)]
pub(super) struct CommandPack {
/// Add a package.
#[arg(short = 'a', long)]
pub(super) add: Option<String>,
/// Install all packages.
#[arg(short = 'i', long)]
pub(super) install: bool,
/// List all packages.
#[arg(short = 'l', long)]
pub(super) list: bool,
/// Upgrade all packages.
#[arg(short = 'u', long)]
pub(super) upgrade: bool,
// --- Macros
macro_rules! impl_emit_body {
($name:ident) => {
impl $name {
#[allow(dead_code)]
pub(super) fn body(self) -> Result<String> {
Ok(serde_json::to_string(&(self.name, Cmd::parse_args(self.args.into_iter(), false)?))?)
}
}
};
}

// --- Macros
macro_rules! impl_body {
macro_rules! impl_pub_body {
($name:ident) => {
impl $name {
#[allow(dead_code)]
pub(super) fn body(&self) -> Result<Cow<str>> {
if let Some(json) = &self.json {
Ok(json.into())
Ok(if let Some(json) = &self.json {
json.into()
} else if let Some(str) = &self.str {
Ok(serde_json::to_string(str)?.into())
serde_json::to_string(str)?.into()
} else if !self.list.is_empty() {
Ok(serde_json::to_string(&self.list)?.into())
serde_json::to_string(&self.list)?.into()
} else {
Ok("".into())
}
"".into()
})
}
}
};
}

impl_body!(CommandPub);
impl_body!(CommandPubTo);
impl_emit_body!(CommandEmit);
impl_emit_body!(CommandEmitTo);

impl_pub_body!(CommandPub);
impl_pub_body!(CommandPubTo);
49 changes: 35 additions & 14 deletions yazi-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,26 @@ async fn main() -> anyhow::Result<()> {
}

match Args::parse().command {
Command::Pub(cmd) => {
Command::Emit(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, cmd.receiver()?, &cmd.body()?).await {
eprintln!("Cannot send message: {e}");
if let Err(e) =
yazi_dds::Client::shot("dds-emit", CommandPub::receiver()?, &cmd.body()?).await
{
eprintln!("Cannot emit command: {e}");
std::process::exit(1);
}
}

Command::PubTo(cmd) => {
Command::EmitTo(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, cmd.receiver, &cmd.body()?).await {
eprintln!("Cannot send message: {e}");
if let Err(e) = yazi_dds::Client::shot("dds-emit", cmd.receiver, &cmd.body()?).await {
eprintln!("Cannot emit command: {e}");
std::process::exit(1);
}
}

Command::Sub(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
yazi_dds::Client::draw(cmd.kinds.split(',').collect()).await?;

tokio::signal::ctrl_c().await?;
}

Command::Pack(cmd) => {
package::init()?;
if cmd.install {
Expand All @@ -60,6 +54,33 @@ async fn main() -> anyhow::Result<()> {
package::Package::add_to_config(&repo).await?;
}
}

Command::Pub(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, CommandPub::receiver()?, &cmd.body()?).await
{
eprintln!("Cannot send message: {e}");
std::process::exit(1);
}
}

Command::PubTo(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
if let Err(e) = yazi_dds::Client::shot(&cmd.kind, cmd.receiver, &cmd.body()?).await {
eprintln!("Cannot send message: {e}");
std::process::exit(1);
}
}

Command::Sub(cmd) => {
yazi_boot::init_default();
yazi_dds::init();
yazi_dds::Client::draw(cmd.kinds.split(',').collect()).await?;

tokio::signal::ctrl_c().await?;
}
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion yazi-config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ keymap = [

# Toggle
{ on = "<Space>", run = [ "toggle", "arrow 1" ], desc = "Toggle the current selection state" },
{ on = "<C-a>", run = "toggle_all on", desc = "Select all files" },
{ on = "<C-a>", run = "toggle_all --state=on", desc = "Select all files" },
{ on = "<C-r>", run = "toggle_all", desc = "Invert selection of all files" },

# Visual mode
Expand Down
8 changes: 5 additions & 3 deletions yazi-core/src/tab/commands/toggle.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use yazi_macro::render_and;
use yazi_proxy::AppProxy;
use yazi_shared::event::CmdCow;
use yazi_shared::{event::CmdCow, fs::Url};

use crate::tab::Tab;

struct Opt {
url: Option<Url>,
state: Option<bool>,
}

impl From<CmdCow> for Opt {
fn from(mut c: CmdCow) -> Self {
Self {
state: match c.take_first_str().as_deref() {
url: c.take_first_url(),
state: match c.str("state") {
Some("on") => Some(true),
Some("off") => Some(false),
_ => None,
Expand All @@ -23,7 +25,7 @@ impl From<CmdCow> for Opt {
impl Tab {
#[yazi_codegen::command]
pub fn toggle(&mut self, opt: Opt) {
let Some(url) = self.current.hovered().map(|h| &h.url) else {
let Some(url) = opt.url.as_ref().or(self.current.hovered().map(|h| &h.url)) else {
return;
};

Expand Down
4 changes: 2 additions & 2 deletions yazi-core/src/tab/commands/toggle_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ struct Opt {
}

impl From<CmdCow> for Opt {
fn from(mut c: CmdCow) -> Self {
fn from(c: CmdCow) -> Self {
Self {
state: match c.take_first_str().as_deref() {
state: match c.str("state") {
Some("on") => Some(true),
Some("off") => Some(false),
_ => None,
Expand Down
17 changes: 16 additions & 1 deletion yazi-plugin/preset/plugins/dds.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
local M = {}

function M:setup()
ps.sub_remote("dds-cd", function(url) ya.manager_emit("cd", { url }) end)
-- TODO: remove this
local b = false
ps.sub_remote("dds-cd", function(url)
if not b then
b = true
ya.notify {
title = "Deprecated DDS Event",
content = "The `dds-cd` event is deprecated, please use `ya emit cd /your/path` instead of `ya pub dds-cd --str /your/path`\n\nSee #1979 for details: https://github.com/sxyazi/yazi/pull/1979",
timeout = 20,
level = "warn",
}
end
ya.manager_emit("cd", { url })
end)

ps.sub_remote("dds-emit", function(cmd) ya.manager_emit(cmd[1], cmd[2]) end)
end

return M
2 changes: 1 addition & 1 deletion yazi-proxy/src/options/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl TryFrom<CmdCow> for PluginOpt {

let (args, _old_args) = if let Some(s) = c.str("args") {
(
Cmd::parse_args(shell_words::split(s)?.into_iter())?,
Cmd::parse_args(shell_words::split(s)?.into_iter(), true)?,
shell_words::split(s)?.into_iter().map(Data::String).collect(),
)
} else {
Expand Down
12 changes: 9 additions & 3 deletions yazi-shared/src/event/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,17 @@ impl Cmd {
}

// Parse
pub fn parse_args(words: impl Iterator<Item = String>) -> Result<HashMap<DataKey, Data>> {
pub fn parse_args(
words: impl Iterator<Item = String>,
obase: bool,
) -> Result<HashMap<DataKey, Data>> {
let mut i = 0i64;
words
.into_iter()
.map(|word| {
let Some(arg) = word.strip_prefix("--") else {
i += 1;
return Ok((DataKey::Integer(i - 1), Data::String(word)));
return Ok((DataKey::Integer(i - obase as i64), Data::String(word)));
};

let mut parts = arg.splitn(2, '=');
Expand Down Expand Up @@ -167,7 +170,10 @@ impl FromStr for Cmd {
bail!("command name cannot be empty");
}

Ok(Cmd { name: mem::take(&mut args[0]), args: Cmd::parse_args(args.into_iter().skip(1))? })
Ok(Cmd {
name: mem::take(&mut args[0]),
args: Cmd::parse_args(args.into_iter().skip(1), true)?,
})
}
}

Expand Down
Loading

0 comments on commit 20dc055

Please sign in to comment.