Added ability to immediately display results, switched to clap for argument parsing

This commit is contained in:
Kirottu
2023-05-11 10:23:14 +03:00
parent c52d0d02e5
commit 7f29aa8224
4 changed files with 383 additions and 235 deletions

270
Cargo.lock generated
View File

@@ -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"

View File

@@ -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));
});
}
}

View File

@@ -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"] }

View File

@@ -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<usize>,
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<Vec<String>>,
/// Override the path to the config directory
#[arg(short, long)]
config_dir: Option<String>,
/// Override plugin selection
#[arg(short, long, value_delimiter = ' ', num_args = 1..)]
override_plugins: Option<Vec<PathBuf>>,
}
#[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<PluginView>,
plugins: Vec<PluginView>,
@@ -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<RefCell<Option<RuntimeData>>> = 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::<Vec<String>>("override-plugins").unwrap();
let config_dir = dict.lookup::<String>("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<RefCell<RuntimeData>> = 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::<String>(&[]);
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>>>) {
fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<RuntimeData>>) {
// Create the main window
let window = gtk::ApplicationWindow::builder()
.application(app)
@@ -250,19 +238,13 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
// 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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
};
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
.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(
&gtk::Separator::builder()
@@ -416,9 +356,12 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
})
.collect::<Vec<PluginView>>();
// 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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
// 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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
.collect::<Vec<(gtk::ListBoxRow, gtk::ListBox)>>();
// 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::<&gtk::ListBoxRow>);
@@ -559,8 +496,6 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
}
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
// 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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
// 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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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(
&gtk::Label::builder()
.label(&format!(
r#"<span foreground="red">{}</span>"#,
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
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<RefCell<Option<RuntimeData>>>) {
for plugin_view in runtime_data.borrow().as_ref().unwrap().plugins.iter() {
fn refresh_matches(input: String, runtime_data: Rc<RefCell<RuntimeData>>) {
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<RefCell<Option<RuntimeData>>>
/// Handle the asynchronously running match task
fn async_match(
plugin_view: PluginView,
runtime_data: Rc<RefCell<Option<RuntimeData>>>,
runtime_data: Rc<RefCell<RuntimeData>>,
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),