From f0080559ddcb49fb37058d8d4520406cedf1de48 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Tue, 26 Apr 2022 22:18:21 +0530 Subject: [PATCH] refactor: use clipboard-master for events --- Cargo.lock | 140 ++++++++++++++++++++++++++++++++++------------- Cargo.toml | 3 +- deny.toml | 3 + src/clipboard.rs | 53 ++++++++++++++++++ src/main.rs | 51 ++--------------- 5 files changed, 164 insertions(+), 86 deletions(-) create mode 100644 src/clipboard.rs diff --git a/Cargo.lock b/Cargo.lock index 098cdcd..cff9e18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,15 +68,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clipboard" -version = "0.5.0" +name = "clipboard-master" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7" +checksum = "459887701008d8ee21f8de7f45f0f0707417c7eea3311973f6e67222bd686b7a" dependencies = [ - "clipboard-win", "objc", "objc-foundation", "objc_id", + "winapi", + "windows-win", "x11-clipboard", ] @@ -86,7 +87,8 @@ version = "0.4.6" dependencies = [ "anyhow", "assay", - "clipboard", + "clipboard-master", + "copypasta", "dirs", "regex", "serde", @@ -99,18 +101,32 @@ dependencies = [ [[package]] name = "clipboard-win" -version = "2.2.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" +checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342" dependencies = [ + "lazy-bytes-cast", "winapi", ] +[[package]] +name = "copypasta" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4423d79fed83ebd9ab81ec21fa97144300a961782158287dc9bf7eddac37ff0b" +dependencies = [ + "clipboard-win", + "objc", + "objc-foundation", + "objc_id", + "x11-clipboard", +] + [[package]] name = "ctor" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ "quote", "syn", @@ -133,9 +149,9 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -159,9 +175,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "getrandom" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", @@ -186,6 +202,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "lazy-bytes-cast" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" + [[package]] name = "lazy_static" version = "1.4.0" @@ -194,15 +216,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.119" +version = "0.2.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" [[package]] name = "log" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if", ] @@ -287,15 +309,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pretty_assertions" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d5b548b725018ab5496482b45cb8bef21e9fed1858a6d674e3a8a0f0bb5d50" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" dependencies = [ "ansi_term", "ctor", @@ -305,9 +327,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ "unicode-xid", ] @@ -318,32 +340,42 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-xml" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" +dependencies = [ + "memchr", +] + [[package]] name = "quote" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] @@ -427,9 +459,9 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "syn" -version = "1.0.86" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" dependencies = [ "proc-macro2", "quote", @@ -450,6 +482,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -503,9 +555,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", "valuable", @@ -524,9 +576,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", @@ -600,21 +652,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-win" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4243ec23afe4e9b4e668b3c0a0e973f1b8265f6a46223cfcbc16fd267480c0" +dependencies = [ + "winapi", +] + [[package]] name = "x11-clipboard" -version = "0.3.3" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea" +checksum = "473068b7b80ac86a18328824f1054e5e007898c47b5bbc281bd7abe32bc3653c" dependencies = [ "xcb", ] [[package]] name = "xcb" -version = "0.8.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" +checksum = "771e2b996df720cd1c6dd9ff90f62d91698fd3610cc078388d0564bdd6622a9c" dependencies = [ "libc", "log", + "quick-xml", ] diff --git a/Cargo.toml b/Cargo.toml index 6a054c1..9d814a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,8 @@ include = ["src/**/*", "LICENSE-*", "README.md"] [dependencies] anyhow = "1.0.57" -clipboard = "0.5.0" +clipboard-master = "3.1.3" +copypasta = { version = "0.7.1", default-features = false, features = ["x11"] } dirs = "4.0.0" regex = "1.5.5" serde = "1.0.136" diff --git a/deny.toml b/deny.toml index 7e62a6c..a06b6b7 100644 --- a/deny.toml +++ b/deny.toml @@ -29,6 +29,9 @@ copyleft = "allow" allow-osi-fsf-free = "neither" default = "deny" confidence-threshold = 0.8 +exceptions = [ + { allow = ["BSL-1.0"], name = "lazy-bytes-cast", version = ">=5.0.1" }, +] [licenses.private] ignore = false diff --git a/src/clipboard.rs b/src/clipboard.rs new file mode 100644 index 0000000..2a9aaa1 --- /dev/null +++ b/src/clipboard.rs @@ -0,0 +1,53 @@ +use std::io; +use std::ops::Not; + +use clipboard_master::{CallbackResult, ClipboardHandler, Master}; +use copypasta::{ClipboardContext, ClipboardProvider}; +use tracing::{debug, error}; + +use crate::config::{Act, Match, Replacements}; + +struct Handler<'a> { + ctx: ClipboardContext, + config: Replacements<'a>, +} + +impl<'a> ClipboardHandler for Handler<'a> { + fn on_clipboard_change(&mut self) -> CallbackResult { + if let Ok(contents) = self.ctx.get_contents() { + if let Some(subst) = self + .config + .substitutors + .iter() + .find(|subst| subst.matcher.check_match(&contents)) + { + if subst.name.is_empty().not() { + debug!("{}: matched on {}...", &subst.name, truncate(&contents, 40)); + } + let result = subst.action.apply_action(&contents); + if let Err(e) = self.ctx.set_contents(result.to_owned()) { + error!("{e}"); + } + }; + } + CallbackResult::Next + } + + fn on_clipboard_error(&mut self, error: io::Error) -> CallbackResult { + error!("Error: {}", error); + CallbackResult::Next + } +} + +fn truncate(s: &str, max_chars: usize) -> &str { + match s.char_indices().nth(max_chars) { + None => s, + Some((idx, _)) => &s[..idx], + } +} + +pub fn monitor_clipboard<'a>(config: Replacements<'a>) { + let ctx = ClipboardContext::new().expect("Failed to acquire clipboard"); + let handler = Handler { ctx, config }; + let _ = Master::new(handler).run(); +} diff --git a/src/main.rs b/src/main.rs index c2f4809..9675d81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,16 @@ +mod clipboard; mod config; #[cfg(test)] mod test; -use std::error::Error; -use std::ops::{Deref, Not}; +use std::ops::Deref; use std::path::PathBuf; use anyhow::{anyhow, Result}; -use clipboard::{ClipboardContext, ClipboardProvider}; use dirs::config_dir; -use tracing::{debug, error}; -use crate::config::{Act, Match, Replacements}; +use crate::clipboard::monitor_clipboard; +use crate::config::Replacements; const VERSION_ARGS: [&str; 3] = ["version", "-v", "--version"]; @@ -24,7 +23,7 @@ fn main() -> Result<()> { let config_str = std::fs::read_to_string(config_path.as_path()).unwrap_or_default(); let config: Replacements<'_> = toml::from_str(&config_str)?; - loop_clipboard(config); + monitor_clipboard(config); Ok(()) } @@ -79,43 +78,3 @@ fn get_config_path() -> Result { config_path.set_extension("toml"); Ok(config_path) } - -fn loop_clipboard(config: Replacements<'_>) { - let mut clipboard: ClipboardContext = - ClipboardProvider::new().expect("Failed to get clipboard"); - let mut clipboard_contents = get_clipboard_contents(&mut clipboard); - while let Ok(contents) = clipboard_contents.as_deref() { - if let Some(subst) = config - .substitutors - .iter() - .find(|subst| subst.matcher.check_match(contents)) - { - if subst.name.is_empty().not() { - debug!("{}: matched on {}...", &subst.name, truncate(contents, 40)); - } - let result = subst.action.apply_action(contents); - if let Err(e) = clipboard.set_contents(result.to_owned()) { - error!("{e}"); - } - }; - while let Ok(new_contents) = get_clipboard_contents(&mut clipboard) { - if new_contents != contents { - clipboard_contents = Ok(new_contents); - break; - }; - } - } -} - -fn get_clipboard_contents( - clipboard: &mut ClipboardContext, -) -> Result> { - clipboard.get_contents() -} - -fn truncate(s: &str, max_chars: usize) -> &str { - match s.char_indices().nth(max_chars) { - None => s, - Some((idx, _)) => &s[..idx], - } -}