diff --git a/Cargo.lock b/Cargo.lock index d04abec..e25d153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,6 +68,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.68" @@ -80,6 +129,7 @@ version = "0.1.0" dependencies = [ "abi_stable", "anyrun-interface", + "clap", "gtk", "gtk-layer-shell", "nix 0.26.1", @@ -299,6 +349,48 @@ dependencies = [ "parse-zoneinfo", ] +[[package]] +name = "clap" +version = "4.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -309,6 +401,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "const_panic" version = "0.2.7" @@ -461,6 +559,27 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -881,6 +1000,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" @@ -1044,12 +1169,35 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e" +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itoa" version = "1.0.5" @@ -1096,9 +1244,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -1119,6 +1267,12 @@ dependencies = [ "cc", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" + [[package]] name = "lock_api" version = "0.4.9" @@ -1174,7 +1328,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1296,7 +1450,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -1313,7 +1467,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" dependencies = [ "pathdiff", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1323,7 +1477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6a252f1f8c11e84b3ab59d7a488e48e4478a93937e027076638c49536204639" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1372,7 +1526,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1657,6 +1811,20 @@ dependencies = [ "semver 1.0.16", ] +[[package]] +name = "rustix" +version = "0.37.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.20.8" @@ -2030,7 +2198,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2210,6 +2378,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version-compare" version = "0.1.1" @@ -2435,13 +2609,37 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.0", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm 0.42.0", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -2450,42 +2648,84 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "winreg" version = "0.10.1" diff --git a/anyrun-plugin-macros/src/lib.rs b/anyrun-plugin-macros/src/lib.rs index 49e8793..a0ef535 100644 --- a/anyrun-plugin-macros/src/lib.rs +++ b/anyrun-plugin-macros/src/lib.rs @@ -201,7 +201,8 @@ pub fn init(_attr: TokenStream, item: TokenStream) -> TokenStream { #function ::std::thread::spawn(|| { - *ANYRUN_INTERNAL_DATA.write().unwrap() = Some(#fn_name(config_dir)); + let mut lock = ANYRUN_INTERNAL_DATA.write().unwrap(); + *lock = Some(#fn_name(config_dir)); }); } } diff --git a/anyrun/Cargo.toml b/anyrun/Cargo.toml index 9828d2a..c4918ca 100644 --- a/anyrun/Cargo.toml +++ b/anyrun/Cargo.toml @@ -14,3 +14,4 @@ serde = { version = "1.0.151", features = ["derive"] } anyrun-interface = { path = "../anyrun-interface" } wl-clipboard-rs = "0.7.0" nix = { version = "0.26.1", default-features = false, features = ["process"] } +clap = { version = "4.2.7", features = ["derive"] } diff --git a/anyrun/src/main.rs b/anyrun/src/main.rs index 425a842..f43d0f6 100644 --- a/anyrun/src/main.rs +++ b/anyrun/src/main.rs @@ -10,6 +10,7 @@ use std::{ use abi_stable::std_types::{ROption, RVec}; use anyrun_interface::{HandleResult, Match, PluginInfo, PluginRef, PollResult}; +use clap::Parser; use gtk::{gdk, gdk_pixbuf, glib, prelude::*}; use nix::unistd; use serde::Deserialize; @@ -25,6 +26,7 @@ struct Config { hide_plugin_info: bool, ignore_exclusive_zones: bool, close_on_click: bool, + show_results_immediately: bool, max_entries: Option, layer: Layer, } @@ -45,6 +47,7 @@ impl Default for Config { hide_plugin_info: false, ignore_exclusive_zones: false, close_on_click: false, + show_results_immediately: false, max_entries: None, layer: Layer::Overlay, } @@ -74,8 +77,14 @@ struct PluginView { list: gtk::ListBox, } +#[derive(Parser)] struct Args { - override_plugins: Option>, + /// Override the path to the config directory + #[arg(short, long)] + config_dir: Option, + /// Override plugin selection + #[arg(short, long, value_delimiter = ' ', num_args = 1..)] + override_plugins: Option>, } #[derive(Deserialize)] @@ -92,7 +101,6 @@ enum PostRunAction { /// Some data that needs to be shared between various parts struct RuntimeData { - args: Args, /// A plugin may request exclusivity which is set with this exclusive: Option, plugins: Vec, @@ -128,87 +136,67 @@ pub const DEFAULT_CONFIG_DIR: &str = "/etc/anyrun"; fn main() { let app = gtk::Application::new(Some("com.kirottu.anyrun"), Default::default()); - let runtime_data: Rc>> = Rc::new(RefCell::new(None)); - // Add the launch options to the GTK Application - app.add_main_option( - "override-plugins", - glib::Char('o' as i8), - glib::OptionFlags::IN_MAIN, - glib::OptionArg::StringArray, - "Override plugins. Provide paths in same format as in the config file", - None, + let args = Args::parse(); + + // Figure out the config dir + let user_dir = format!( + "{}/.config/anyrun", + env::var("HOME").expect("Could not determine home directory! Is $HOME set?") ); - app.add_main_option( - "config-dir", - glib::Char('c' as i8), - glib::OptionFlags::IN_MAIN, - glib::OptionArg::String, - "Override the config directory from the default (~/.config/anyrun/)", - None, - ); - - let runtime_data_clone = runtime_data.clone(); - app.connect_handle_local_options(move |_app, dict| { - let override_plugins = dict.lookup::>("override-plugins").unwrap(); - let config_dir = dict.lookup::("config-dir").unwrap(); - - // Figure out the config dir - let user_dir = format!( - "{}/.config/anyrun", - env::var("HOME").expect("Could not determine home directory! Is $HOME set?") - ); - let config_dir = config_dir.unwrap_or_else(|| { - if PathBuf::from(&user_dir).exists() { - user_dir - } else { - DEFAULT_CONFIG_DIR.to_string() - } - }); - - // Load config, if unable to then read default config. If an error occurs the message will be displayed. - let (config, error_label) = match fs::read_to_string(format!("{}/config.ron", config_dir)) { - Ok(content) => ron::from_str(&content) - .map(|config| (config, String::new())) - .unwrap_or_else(|why| { - ( - Config::default(), - format!( - "Failed to parse Anyrun config file, using default config: {}", - why - ), - ) - }), - Err(why) => ( - Config::default(), - format!( - "Failed to read Anyrun config file, using default config: {}", - why - ), - ), - }; - - *runtime_data_clone.borrow_mut() = Some(RuntimeData { - args: Args { override_plugins }, - exclusive: None, - plugins: Vec::new(), - post_run_action: PostRunAction::None, - error_label, - config, - config_dir, - }); - -1 // Magic GTK number to continue running + let config_dir = args.config_dir.unwrap_or_else(|| { + if PathBuf::from(&user_dir).exists() { + user_dir + } else { + DEFAULT_CONFIG_DIR.to_string() + } }); + // Load config, if unable to then read default config. If an error occurs the message will be displayed. + let (mut config, error_label) = match fs::read_to_string(format!("{}/config.ron", config_dir)) { + Ok(content) => ron::from_str(&content) + .map(|config| (config, String::new())) + .unwrap_or_else(|why| { + ( + Config::default(), + format!( + "Failed to parse Anyrun config file, using default config: {}", + why + ), + ) + }), + Err(why) => ( + Config::default(), + format!( + "Failed to read Anyrun config file, using default config: {}", + why + ), + ), + }; + + if let Some(override_plugins) = args.override_plugins { + config.plugins = override_plugins; + } + + let runtime_data: Rc> = Rc::new(RefCell::new(RuntimeData { + exclusive: None, + plugins: Vec::new(), + post_run_action: PostRunAction::None, + config, + error_label, + config_dir, + })); + let runtime_data_clone = runtime_data.clone(); app.connect_activate(move |app| activate(app, runtime_data_clone.clone())); - app.run(); + // Run with no args to make sure only clap is used + app.run_with_args::(&[]); - let runtime_data = runtime_data.borrow_mut().take().unwrap(); + let runtime_data = runtime_data.borrow_mut(); // Perform a post run action if one is set - match runtime_data.post_run_action { + match &runtime_data.post_run_action { PostRunAction::Copy(bytes) => match unsafe { unistd::fork() } { // The parent process just exits and prints that out Ok(unistd::ForkResult::Parent { .. }) => { @@ -219,7 +207,7 @@ fn main() { let mut opts = copy::Options::new(); opts.foreground(true); opts.copy( - copy::Source::Bytes(bytes.into_boxed_slice()), + copy::Source::Bytes(bytes.clone().into_boxed_slice()), copy::MimeType::Autodetect, ) .expect("Failed to serve copy bytes"); @@ -232,7 +220,7 @@ fn main() { } } -fn activate(app: >k::Application, runtime_data: Rc>>) { +fn activate(app: >k::Application, runtime_data: Rc>) { // Create the main window let window = gtk::ApplicationWindow::builder() .application(app) @@ -250,19 +238,13 @@ fn activate(app: >k::Application, runtime_data: Rc gtk_layer_shell::set_namespace(&window, "anyrun"); - if runtime_data - .borrow() - .as_ref() - .unwrap() - .config - .ignore_exclusive_zones - { + if runtime_data.borrow().config.ignore_exclusive_zones { gtk_layer_shell::set_exclusive_zone(&window, -1); } gtk_layer_shell::set_keyboard_mode(&window, gtk_layer_shell::KeyboardMode::Exclusive); - match runtime_data.borrow().as_ref().unwrap().config.layer { + match runtime_data.borrow().config.layer { Layer::Background => { gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background) } @@ -273,10 +255,9 @@ fn activate(app: >k::Application, runtime_data: Rc // Try to load custom CSS, if it fails load the default CSS let provider = gtk::CssProvider::new(); - if let Err(why) = provider.load_from_path(&format!( - "{}/style.css", - runtime_data.borrow().as_ref().unwrap().config_dir - )) { + if let Err(why) = + provider.load_from_path(&format!("{}/style.css", runtime_data.borrow().config_dir)) + { eprintln!("Failed to load custom CSS: {}", why); provider .load_from_data(include_bytes!("../res/style.css")) @@ -288,30 +269,6 @@ fn activate(app: >k::Application, runtime_data: Rc gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, ); - // Use the plugins in the config file, or the plugins specified with the override - let plugins = match &runtime_data - .borrow() - .as_ref() - .unwrap() - .args - .override_plugins - { - Some(plugins) => plugins.iter().map(PathBuf::from).collect(), - None => runtime_data - .borrow() - .as_ref() - .unwrap() - .config - .plugins - .clone(), - }; - - // Make sure at least one plugin is specified - if plugins.is_empty() { - eprintln!("At least one plugin needs to be enabled!"); - app.quit(); - } - // Create the main list of plugin views let main_list = gtk::ListBox::builder() .selection_mode(gtk::SelectionMode::None) @@ -325,23 +282,20 @@ fn activate(app: >k::Application, runtime_data: Rc }; plugin_paths.append(&mut vec![ - format!( - "{}/plugins", - runtime_data.borrow().as_ref().unwrap().config_dir - ) - .into(), + format!("{}/plugins", runtime_data.borrow().config_dir).into(), format!("{}/plugins", DEFAULT_CONFIG_DIR).into(), ]); // Load plugins from the paths specified in the config file - runtime_data.borrow_mut().as_mut().unwrap().plugins = plugins + let plugins = runtime_data + .borrow() + .config + .plugins .iter() .map(|plugin_path| { // Load the plugin's dynamic library. - let mut user_path = PathBuf::from(&format!( - "{}/plugins", - runtime_data.borrow().as_ref().unwrap().config_dir - )); + let mut user_path = + PathBuf::from(&format!("{}/plugins", runtime_data.borrow().config_dir)); let mut global_path = PathBuf::from("/etc/anyrun/plugins"); user_path.extend(plugin_path.iter()); global_path.extend(plugin_path.iter()); @@ -367,31 +321,17 @@ fn activate(app: >k::Application, runtime_data: Rc .expect("Failed to load plugin"); // Run the plugin's init code to init static resources etc. - plugin.init()( - runtime_data - .borrow() - .as_ref() - .unwrap() - .config_dir - .clone() - .into(), - ); + plugin.init()(runtime_data.borrow().config_dir.clone().into()); let plugin_box = gtk::Box::builder() .orientation(gtk::Orientation::Horizontal) .spacing(10) .name(style_names::PLUGIN) .build(); - if !runtime_data - .borrow() - .as_ref() - .unwrap() - .config - .hide_plugin_info - { + if !runtime_data.borrow().config.hide_plugin_info { plugin_box.add(&create_info_box( &plugin.info()(), - runtime_data.borrow().as_ref().unwrap().config.hide_icons, + runtime_data.borrow().config.hide_icons, )); plugin_box.add( >k::Separator::builder() @@ -416,9 +356,12 @@ fn activate(app: >k::Application, runtime_data: Rc }) .collect::>(); + // Assign the plugins here to avoid multiple mutable/immutable borrows + runtime_data.borrow_mut().plugins = plugins; + // Connect selection events to avoid completely messing up selection logic - for plugin_view in runtime_data.borrow().as_ref().unwrap().plugins.iter() { - let plugins_clone = runtime_data.borrow().as_ref().unwrap().plugins.clone(); + for plugin_view in runtime_data.borrow().plugins.iter() { + let plugins_clone = runtime_data.borrow().plugins.clone(); plugin_view.list.connect_row_selected(move |list, row| { if row.is_some() { let combined_matches = plugins_clone @@ -472,8 +415,6 @@ fn activate(app: >k::Application, runtime_data: Rc // Combine all of the matches into a `Vec` to allow for easier handling of the selection let combined_matches = runtime_data_clone .borrow() - .as_ref() - .unwrap() .plugins .iter() .flat_map(|view| { @@ -488,33 +429,29 @@ fn activate(app: >k::Application, runtime_data: Rc .collect::>(); // Get the selected match - let (selected_match, selected_list) = match runtime_data_clone - .borrow() - .as_ref() - .unwrap() - .plugins - .iter() - .find_map(|view| view.list.selected_row().map(|row| (row, view.list.clone()))) - { - Some(selected) => selected, - None => { - // If nothing is selected select either the top or bottom match based on the input - if !combined_matches.is_empty() { - match event.keyval() { - constants::Down | constants::Tab => combined_matches[0] - .1 - .select_row(Some(&combined_matches[0].0)), - constants::Up => combined_matches[combined_matches.len() - 1] - .1 - .select_row(Some( - &combined_matches[combined_matches.len() - 1].0, - )), - _ => unreachable!(), + let (selected_match, selected_list) = + match runtime_data_clone.borrow().plugins.iter().find_map(|view| { + view.list.selected_row().map(|row| (row, view.list.clone())) + }) { + Some(selected) => selected, + None => { + // If nothing is selected select either the top or bottom match based on the input + if !combined_matches.is_empty() { + match event.keyval() { + constants::Down | constants::Tab => combined_matches[0] + .1 + .select_row(Some(&combined_matches[0].0)), + constants::Up => { + combined_matches[combined_matches.len() - 1].1.select_row( + Some(&combined_matches[combined_matches.len() - 1].0), + ) + } + _ => unreachable!(), + } } + return Inhibit(true); } - return Inhibit(true); - } - }; + }; // Clear the previous selection selected_list.select_row(None::<>k::ListBoxRow>); @@ -559,8 +496,6 @@ fn activate(app: >k::Application, runtime_data: Rc let mut _runtime_data_clone = runtime_data_clone.borrow_mut(); let (selected_match, plugin_view) = match _runtime_data_clone - .as_ref() - .unwrap() .plugins .iter() .find_map(|view| view.list.selected_row().map(|row| (row, view))) @@ -581,18 +516,16 @@ fn activate(app: >k::Application, runtime_data: Rc } HandleResult::Refresh(exclusive) => { if exclusive { - _runtime_data_clone.as_mut().unwrap().exclusive = - Some(plugin_view.clone()); + _runtime_data_clone.exclusive = Some(plugin_view.clone()); } else { - _runtime_data_clone.as_mut().unwrap().exclusive = None; + _runtime_data_clone.exclusive = None; } mem::drop(_runtime_data_clone); // Drop the mutable borrow refresh_matches(entry_clone.text().into(), runtime_data_clone.clone()); Inhibit(false) } HandleResult::Copy(bytes) => { - _runtime_data_clone.as_mut().unwrap().post_run_action = - PostRunAction::Copy(bytes.into()); + _runtime_data_clone.post_run_action = PostRunAction::Copy(bytes.into()); window.close(); Inhibit(true) } @@ -611,13 +544,7 @@ fn activate(app: >k::Application, runtime_data: Rc // If the option is enabled, close the window when any click is received // that is outside the bounds of the main box - if runtime_data - .borrow() - .as_ref() - .unwrap() - .config - .close_on_click - { + if runtime_data.borrow().config.close_on_click { window.connect_button_press_event(move |window, event| { if event.window() == window.window() { window.close(); @@ -630,7 +557,7 @@ fn activate(app: >k::Application, runtime_data: Rc // Create widgets here for proper positioning window.connect_configure_event(move |window, event| { - let width = match runtime_data.borrow().as_ref().unwrap().config.width { + let width = match runtime_data.borrow().config.width { RelativeNum::Absolute(width) => width, RelativeNum::Fraction(fraction) => (event.size().0 as f32 * fraction) as i32, }; @@ -646,31 +573,19 @@ fn activate(app: >k::Application, runtime_data: Rc main_vbox.add(&entry); // Display the error message - if !runtime_data - .borrow() - .as_ref() - .unwrap() - .error_label - .is_empty() - { + if !runtime_data.borrow().error_label.is_empty() { main_vbox.add( >k::Label::builder() .label(&format!( r#"{}"#, - runtime_data.borrow().as_ref().unwrap().error_label + runtime_data.borrow().error_label )) .use_markup(true) .build(), ); } - let vertical_offset = match runtime_data - .borrow() - .as_ref() - .unwrap() - .config - .vertical_offset - { + let vertical_offset = match runtime_data.borrow().config.vertical_offset { RelativeNum::Absolute(offset) => offset, RelativeNum::Fraction(fraction) => (event.size().1 as f32 * fraction) as i32, }; @@ -678,7 +593,7 @@ fn activate(app: >k::Application, runtime_data: Rc fixed.put( &main_vbox, (event.size().0 as i32 - width) / 2, - match runtime_data.borrow().as_ref().unwrap().config.position { + match runtime_data.borrow().config.position { Position::Top => vertical_offset, Position::Center => { (event.size().1 as i32 - entry.allocated_height()) / 2 + vertical_offset @@ -692,6 +607,12 @@ fn activate(app: >k::Application, runtime_data: Rc main_vbox.add(&main_list); main_list.show(); entry.grab_focus(); // Grab the focus so typing is immediately accepted by the entry box + + if runtime_data.borrow().config.show_results_immediately { + // Get initial matches + refresh_matches(String::new(), runtime_data.clone()); + } + false }); @@ -871,30 +792,19 @@ fn create_info_box(info: &PluginInfo, hide_icons: bool) -> gtk::Box { } /// Refresh the matches from the plugins -fn refresh_matches(input: String, runtime_data: Rc>>) { - for plugin_view in runtime_data.borrow().as_ref().unwrap().plugins.iter() { +fn refresh_matches(input: String, runtime_data: Rc>) { + for plugin_view in runtime_data.borrow().plugins.iter() { let id = plugin_view.plugin.get_matches()(input.clone().into()); let plugin_view = plugin_view.clone(); let runtime_data_clone = runtime_data.clone(); - // If the input is empty, skip getting matches and just clear everything out. - if input.is_empty() { - handle_matches( - plugin_view, - runtime_data.borrow().as_ref().unwrap(), - RVec::new(), - ); // If a plugin has requested exclusivity, respect it - } else if let Some(exclusive) = &runtime_data.borrow().as_ref().unwrap().exclusive { + if let Some(exclusive) = &runtime_data.borrow().exclusive { if plugin_view.plugin.info() == exclusive.plugin.info() { glib::timeout_add_local(Duration::from_micros(1000), move || { async_match(plugin_view.clone(), runtime_data_clone.clone(), id) }); } else { - handle_matches( - plugin_view.clone(), - runtime_data.borrow().as_ref().unwrap(), - RVec::new(), - ); + handle_matches(plugin_view.clone(), &runtime_data.borrow(), RVec::new()); } } else { glib::timeout_add_local(Duration::from_micros(1000), move || { @@ -907,16 +817,12 @@ fn refresh_matches(input: String, runtime_data: Rc>> /// Handle the asynchronously running match task fn async_match( plugin_view: PluginView, - runtime_data: Rc>>, + runtime_data: Rc>, id: u64, ) -> glib::Continue { match plugin_view.plugin.poll_matches()(id) { PollResult::Ready(matches) => { - handle_matches( - plugin_view, - runtime_data.borrow().as_ref().unwrap(), - matches, - ); + handle_matches(plugin_view, &runtime_data.borrow(), matches); glib::Continue(false) } PollResult::Pending => glib::Continue(true),