Switched to using proc macros for the anyrun_plugin
crate
This allows for plugins to decide on whether or not a mutable borrow or a normal borrow is needed of the shared data. It can also now be omitted alltogether.
This commit is contained in:
21
Cargo.lock
generated
21
Cargo.lock
generated
@@ -101,6 +101,15 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"abi_stable",
|
"abi_stable",
|
||||||
"anyrun-interface",
|
"anyrun-interface",
|
||||||
|
"anyrun-plugin-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyrun-plugin-macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -135,7 +144,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.13",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -978,7 +987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2de65550b4ec230167654f367b6ec02795acf2cfd9692f05bedb10ff09e46a6e"
|
checksum = "2de65550b4ec230167654f367b6ec02795acf2cfd9692f05bedb10ff09e46a6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.13",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1740,7 +1749,7 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.13",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1762,7 +1771,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.13",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1900,9 +1909,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.13"
|
version = "2.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
|
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
members = [
|
members = [
|
||||||
"anyrun",
|
"anyrun",
|
||||||
"anyrun-plugin",
|
"anyrun-plugin",
|
||||||
|
"anyrun-plugin-macros",
|
||||||
"anyrun-interface",
|
"anyrun-interface",
|
||||||
"plugins/applications",
|
"plugins/applications",
|
||||||
"plugins/symbols",
|
"plugins/symbols",
|
||||||
|
13
anyrun-plugin-macros/Cargo.toml
Normal file
13
anyrun-plugin-macros/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "anyrun-plugin-macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.26"
|
||||||
|
syn = { version = "2.0.15", features = ["full"] }
|
209
anyrun-plugin-macros/src/lib.rs
Normal file
209
anyrun-plugin-macros/src/lib.rs
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, ReturnType, Type};
|
||||||
|
|
||||||
|
/// The function to handle the selection of an item. Takes a `Match` as its first argument, and the second argument can be one of:
|
||||||
|
/// - &T
|
||||||
|
/// - &mut T
|
||||||
|
/// - <Nothing>
|
||||||
|
/// where T is the type returned by `init`.
|
||||||
|
///
|
||||||
|
/// Should return a `HandleResult` with the appropriate action.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let function = parse_macro_input!(item as syn::ItemFn);
|
||||||
|
let fn_name = &function.sig.ident;
|
||||||
|
|
||||||
|
let data = if function.sig.inputs.len() == 2 {
|
||||||
|
if match function.sig.inputs.last() {
|
||||||
|
Some(syn::FnArg::Typed(pat)) => match &*pat.ty {
|
||||||
|
Type::Reference(reference) => {
|
||||||
|
reference.mutability.is_some()
|
||||||
|
}
|
||||||
|
_ => return quote! { compile_error!("Last argument must be either a reference to the shared data or should not be present at all.") }.into(),
|
||||||
|
},
|
||||||
|
Some(_) => return quote! { compile_error!("`self` argument, really?") }.into(),
|
||||||
|
None => unreachable!(),
|
||||||
|
} {
|
||||||
|
quote! {
|
||||||
|
ANYRUN_INTERNAL_DATA.write().unwrap().as_mut().unwrap(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
ANYRUN_INTERNAL_DATA.read().unwrap().as_ref().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[::abi_stable::sabi_extern_fn]
|
||||||
|
fn anyrun_internal_handle_selection(
|
||||||
|
selection: ::anyrun_plugin::anyrun_interface::Match,
|
||||||
|
) -> ::anyrun_plugin::anyrun_interface::HandleResult {
|
||||||
|
#function
|
||||||
|
|
||||||
|
#fn_name(
|
||||||
|
selection,
|
||||||
|
#data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function that takes the current text input as an `RString` as the first argument, and the second argument can be one of:
|
||||||
|
/// - &T
|
||||||
|
/// - &mut T
|
||||||
|
/// - <Nothing>
|
||||||
|
/// where T is the type returned by `init`.
|
||||||
|
///
|
||||||
|
/// It should return an `RVec` of `Match`es.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn get_matches(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let function = parse_macro_input!(item as syn::ItemFn);
|
||||||
|
let fn_name = &function.sig.ident;
|
||||||
|
|
||||||
|
let fn_call = if function.sig.inputs.len() == 2 {
|
||||||
|
let data = if match function.sig.inputs.last() {
|
||||||
|
Some(syn::FnArg::Typed(pat)) => match &*pat.ty {
|
||||||
|
Type::Reference(reference) => {
|
||||||
|
reference.mutability.is_some()
|
||||||
|
}
|
||||||
|
_ => return quote! { compile_error!("Last argument must be either a reference to the shared data or should not be present at all.") }.into(),
|
||||||
|
},
|
||||||
|
Some(_) => return quote! { compile_error!("`self` argument, really?") }.into(),
|
||||||
|
None => unreachable!(),
|
||||||
|
} {
|
||||||
|
quote! {
|
||||||
|
ANYRUN_INTERNAL_DATA.write().unwrap().as_mut()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
ANYRUN_INTERNAL_DATA.read().unwrap().as_ref()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
if let Some(data) = #data {
|
||||||
|
#fn_name(input, data)
|
||||||
|
} else {
|
||||||
|
::abi_stable::std_types::RVec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#fn_name(input)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[::abi_stable::sabi_extern_fn]
|
||||||
|
fn anyrun_internal_get_matches(input: ::abi_stable::std_types::RString) -> u64 {
|
||||||
|
#function
|
||||||
|
|
||||||
|
let current_id =
|
||||||
|
ANYRUN_INTERNAL_ID_COUNTER.load(::std::sync::atomic::Ordering::Relaxed);
|
||||||
|
ANYRUN_INTERNAL_ID_COUNTER
|
||||||
|
.store(current_id + 1, ::std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
let handle = ::std::thread::spawn(move || {
|
||||||
|
#fn_call
|
||||||
|
});
|
||||||
|
|
||||||
|
*ANYRUN_INTERNAL_THREAD.lock().unwrap() = Some((handle, current_id));
|
||||||
|
|
||||||
|
current_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function that returns the plugin info as a `PluginInfo` object. Takes no arguments.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn info(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let function = parse_macro_input!(item as syn::ItemFn);
|
||||||
|
let fn_name = &function.sig.ident;
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[::abi_stable::sabi_extern_fn]
|
||||||
|
fn anyrun_internal_info() -> ::anyrun_plugin::anyrun_interface::PluginInfo {
|
||||||
|
#function
|
||||||
|
|
||||||
|
#fn_name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function that takes an `RString` as the only argument, which points to the anyrun config directory. Returns the data
|
||||||
|
/// the plugin operates on. This data is accessible as both a normal borrow and a mutable borrow to `get_matches` and `handler`.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn init(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let function = parse_macro_input!(item as syn::ItemFn);
|
||||||
|
let fn_name = &function.sig.ident;
|
||||||
|
let data_type = match &function.sig.output {
|
||||||
|
ReturnType::Default => quote! {()},
|
||||||
|
ReturnType::Type(_, data_type) => quote! {#data_type},
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
static ANYRUN_INTERNAL_THREAD: ::std::sync::Mutex<
|
||||||
|
Option<(
|
||||||
|
::std::thread::JoinHandle<
|
||||||
|
::abi_stable::std_types::RVec<::anyrun_plugin::anyrun_interface::Match>,
|
||||||
|
>,
|
||||||
|
u64,
|
||||||
|
)>,
|
||||||
|
> = ::std::sync::Mutex::new(None);
|
||||||
|
static ANYRUN_INTERNAL_ID_COUNTER: ::std::sync::atomic::AtomicU64 =
|
||||||
|
::std::sync::atomic::AtomicU64::new(0);
|
||||||
|
static ANYRUN_INTERNAL_DATA: ::std::sync::RwLock<Option<#data_type>> =
|
||||||
|
::std::sync::RwLock::new(None);
|
||||||
|
|
||||||
|
#[::abi_stable::export_root_module]
|
||||||
|
fn anyrun_internal_init_root_module() -> ::anyrun_plugin::anyrun_interface::PluginRef {
|
||||||
|
use ::abi_stable::prefix_type::PrefixTypeTrait;
|
||||||
|
::anyrun_plugin::anyrun_interface::Plugin {
|
||||||
|
init: anyrun_internal_init,
|
||||||
|
info: anyrun_internal_info,
|
||||||
|
get_matches: anyrun_internal_get_matches,
|
||||||
|
poll_matches: anyrun_internal_poll_matches,
|
||||||
|
handle_selection: anyrun_internal_handle_selection,
|
||||||
|
}
|
||||||
|
.leak_into_prefix()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[::abi_stable::sabi_extern_fn]
|
||||||
|
fn anyrun_internal_poll_matches(id: u64) -> ::anyrun_plugin::anyrun_interface::PollResult {
|
||||||
|
match ANYRUN_INTERNAL_THREAD.try_lock() {
|
||||||
|
Ok(thread) => match thread.as_ref() {
|
||||||
|
Some((thread, task_id)) => {
|
||||||
|
if *task_id == id {
|
||||||
|
if !thread.is_finished() {
|
||||||
|
return ::anyrun_plugin::anyrun_interface::PollResult::Pending;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ::anyrun_plugin::anyrun_interface::PollResult::Cancelled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return ::anyrun_plugin::anyrun_interface::PollResult::Cancelled,
|
||||||
|
},
|
||||||
|
Err(_) => return ::anyrun_plugin::anyrun_interface::PollResult::Pending,
|
||||||
|
}
|
||||||
|
|
||||||
|
let (thread, _) = ANYRUN_INTERNAL_THREAD.lock().unwrap().take().unwrap();
|
||||||
|
::anyrun_plugin::anyrun_interface::PollResult::Ready(thread.join().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[::abi_stable::sabi_extern_fn]
|
||||||
|
fn anyrun_internal_init(config_dir: ::abi_stable::std_types::RString) {
|
||||||
|
#function
|
||||||
|
|
||||||
|
::std::thread::spawn(|| {
|
||||||
|
*ANYRUN_INTERNAL_DATA.write().unwrap() = Some(#fn_name(config_dir));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
@@ -8,3 +8,4 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
abi_stable = "0.11.1"
|
abi_stable = "0.11.1"
|
||||||
anyrun-interface = { path = "../anyrun-interface" }
|
anyrun-interface = { path = "../anyrun-interface" }
|
||||||
|
anyrun-plugin-macros = { path = "../anyrun-plugin-macros" }
|
||||||
|
@@ -1,115 +1,19 @@
|
|||||||
pub use anyrun_interface::{self, Match, PluginInfo};
|
/*!
|
||||||
|
The crate for building plugins for Anyrun.
|
||||||
|
|
||||||
/**
|
Each plugin needs 4 functions defined, `init`, `info`, `get_matches` and the `handler`. Documentation
|
||||||
|
on what each of these should be is found in their respective attribute macros.
|
||||||
|
!*/
|
||||||
|
|
||||||
|
pub use anyrun_interface::{self, HandleResult, Match, PluginInfo};
|
||||||
|
pub use anyrun_plugin_macros::*;
|
||||||
|
|
||||||
|
/*
|
||||||
The macro to create a plugin, handles asynchronous execution of getting the matches and the boilerplate
|
The macro to create a plugin, handles asynchronous execution of getting the matches and the boilerplate
|
||||||
for integrating with `stable_abi`.
|
for integrating with `stable_abi`.
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
|
|
||||||
* `$init`: Function that takes an `RString` as the only argument, which points to the anyrun config directory. Returns the data
|
|
||||||
the plugin operates on.
|
|
||||||
|
|
||||||
* `$info`: Function that returns the plugin info as a `PluginInfo` object. Takes no arguments.
|
|
||||||
|
|
||||||
* `$get_matches`: Function that takes the current text input as an `RString` as the only argument, and returns an `RVec<Match>`.
|
|
||||||
This is run asynchronously automatically.
|
|
||||||
|
|
||||||
* `$handler`: The function to handle the selection of an item. Takes a `Match` as it's only argument and returns a `HandleResult` with
|
|
||||||
the appropriate action.
|
|
||||||
|
|
||||||
* `$type`: The type of the shared data to be provided to various functions.
|
* `$type`: The type of the shared data to be provided to various functions.
|
||||||
**/
|
*/
|
||||||
#[macro_export]
|
|
||||||
macro_rules! plugin {
|
|
||||||
($init:ident, $info:ident, $get_matches:ident, $handler:ident, $type:ty) => {
|
|
||||||
static ANYRUN_INTERNAL_THREAD: ::std::sync::Mutex<
|
|
||||||
Option<(
|
|
||||||
::std::thread::JoinHandle<
|
|
||||||
::abi_stable::std_types::RVec<::anyrun_plugin::anyrun_interface::Match>,
|
|
||||||
>,
|
|
||||||
u64,
|
|
||||||
)>,
|
|
||||||
> = ::std::sync::Mutex::new(None);
|
|
||||||
static ANYRUN_INTERNAL_ID_COUNTER: ::std::sync::atomic::AtomicU64 =
|
|
||||||
::std::sync::atomic::AtomicU64::new(0);
|
|
||||||
static ANYRUN_INTERNAL_DATA: ::std::sync::RwLock<Option<$type>> =
|
|
||||||
::std::sync::RwLock::new(None);
|
|
||||||
|
|
||||||
#[::abi_stable::export_root_module]
|
|
||||||
fn anyrun_internal_init_root_module() -> ::anyrun_plugin::anyrun_interface::PluginRef {
|
|
||||||
use ::abi_stable::prefix_type::PrefixTypeTrait;
|
|
||||||
::anyrun_plugin::anyrun_interface::Plugin {
|
|
||||||
init: anyrun_internal_init,
|
|
||||||
info: anyrun_internal_info,
|
|
||||||
get_matches: anyrun_internal_get_matches,
|
|
||||||
poll_matches: anyrun_internal_poll_matches,
|
|
||||||
handle_selection: anyrun_internal_handle_selection,
|
|
||||||
}
|
|
||||||
.leak_into_prefix()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[::abi_stable::sabi_extern_fn]
|
|
||||||
fn anyrun_internal_init(config_dir: ::abi_stable::std_types::RString) {
|
|
||||||
::std::thread::spawn(|| {
|
|
||||||
*ANYRUN_INTERNAL_DATA.write().unwrap() = Some($init(config_dir));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[::abi_stable::sabi_extern_fn]
|
|
||||||
fn anyrun_internal_info() -> ::anyrun_plugin::anyrun_interface::PluginInfo {
|
|
||||||
$info()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[::abi_stable::sabi_extern_fn]
|
|
||||||
fn anyrun_internal_get_matches(input: ::abi_stable::std_types::RString) -> u64 {
|
|
||||||
let current_id =
|
|
||||||
ANYRUN_INTERNAL_ID_COUNTER.load(::std::sync::atomic::Ordering::Relaxed);
|
|
||||||
ANYRUN_INTERNAL_ID_COUNTER
|
|
||||||
.store(current_id + 1, ::std::sync::atomic::Ordering::Relaxed);
|
|
||||||
|
|
||||||
let handle = ::std::thread::spawn(move || {
|
|
||||||
if let Some(data) = ANYRUN_INTERNAL_DATA.read().unwrap().as_ref() {
|
|
||||||
$get_matches(input, data)
|
|
||||||
} else {
|
|
||||||
::abi_stable::std_types::RVec::new()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
*ANYRUN_INTERNAL_THREAD.lock().unwrap() = Some((handle, current_id));
|
|
||||||
|
|
||||||
current_id
|
|
||||||
}
|
|
||||||
|
|
||||||
#[::abi_stable::sabi_extern_fn]
|
|
||||||
fn anyrun_internal_poll_matches(id: u64) -> ::anyrun_plugin::anyrun_interface::PollResult {
|
|
||||||
match ANYRUN_INTERNAL_THREAD.try_lock() {
|
|
||||||
Ok(thread) => match thread.as_ref() {
|
|
||||||
Some((thread, task_id)) => {
|
|
||||||
if *task_id == id {
|
|
||||||
if !thread.is_finished() {
|
|
||||||
return ::anyrun_plugin::anyrun_interface::PollResult::Pending;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ::anyrun_plugin::anyrun_interface::PollResult::Cancelled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => return ::anyrun_plugin::anyrun_interface::PollResult::Cancelled,
|
|
||||||
},
|
|
||||||
Err(_) => return ::anyrun_plugin::anyrun_interface::PollResult::Pending,
|
|
||||||
}
|
|
||||||
|
|
||||||
let (thread, _) = ANYRUN_INTERNAL_THREAD.lock().unwrap().take().unwrap();
|
|
||||||
::anyrun_plugin::anyrun_interface::PollResult::Ready(thread.join().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[::abi_stable::sabi_extern_fn]
|
|
||||||
fn anyrun_internal_handle_selection(
|
|
||||||
selection: ::anyrun_plugin::anyrun_interface::Match,
|
|
||||||
) -> ::anyrun_plugin::anyrun_interface::HandleResult {
|
|
||||||
$handler(
|
|
||||||
selection,
|
|
||||||
ANYRUN_INTERNAL_DATA.write().unwrap().as_mut().unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@@ -12,7 +12,8 @@ pub struct Config {
|
|||||||
|
|
||||||
mod scrubber;
|
mod scrubber;
|
||||||
|
|
||||||
pub fn handler(selection: Match, entries: &mut Vec<(DesktopEntry, u64)>) -> HandleResult {
|
#[handler]
|
||||||
|
pub fn handler(selection: Match, entries: &Vec<(DesktopEntry, u64)>) -> HandleResult {
|
||||||
let entry = entries
|
let entry = entries
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(entry, id)| {
|
.find_map(|(entry, id)| {
|
||||||
@@ -31,6 +32,7 @@ pub fn handler(selection: Match, entries: &mut Vec<(DesktopEntry, u64)>) -> Hand
|
|||||||
HandleResult::Close
|
HandleResult::Close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
||||||
let config: Config = match fs::read_to_string(format!("{}/applications.ron", config_dir)) {
|
let config: Config = match fs::read_to_string(format!("{}/applications.ron", config_dir)) {
|
||||||
Ok(content) => ron::from_str(&content).unwrap_or_else(|why| {
|
Ok(content) => ron::from_str(&content).unwrap_or_else(|why| {
|
||||||
@@ -49,6 +51,7 @@ pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
pub fn get_matches(input: RString, entries: &Vec<(DesktopEntry, u64)>) -> RVec<Match> {
|
pub fn get_matches(input: RString, entries: &Vec<(DesktopEntry, u64)>) -> RVec<Match> {
|
||||||
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
||||||
let mut entries = entries
|
let mut entries = entries
|
||||||
@@ -81,11 +84,10 @@ pub fn get_matches(input: RString, entries: &Vec<(DesktopEntry, u64)>) -> RVec<M
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
pub fn info() -> PluginInfo {
|
pub fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Applications".into(),
|
name: "Applications".into(),
|
||||||
icon: "application-x-executable".into(),
|
icon: "application-x-executable".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, Vec<(DesktopEntry, u64)>);
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ApiResponse {
|
struct ApiResponse {
|
||||||
word: String,
|
word: String,
|
||||||
@@ -11,6 +12,7 @@ struct ApiResponse {
|
|||||||
meanings: Vec<Meaning>,
|
meanings: Vec<Meaning>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Phonetic {
|
struct Phonetic {
|
||||||
text: String,
|
text: String,
|
||||||
@@ -24,6 +26,7 @@ struct Meaning {
|
|||||||
definitions: Vec<Definition>,
|
definitions: Vec<Definition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Definition {
|
struct Definition {
|
||||||
definition: String,
|
definition: String,
|
||||||
@@ -32,13 +35,16 @@ struct Definition {
|
|||||||
antonyms: Vec<String>,
|
antonyms: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
pub fn init(_config_dir: RString) {}
|
pub fn init(_config_dir: RString) {}
|
||||||
|
|
||||||
pub fn handler(_match: Match, _: &mut ()) -> HandleResult {
|
#[handler]
|
||||||
|
pub fn handler(_match: Match) -> HandleResult {
|
||||||
HandleResult::Copy(_match.title.into_bytes())
|
HandleResult::Copy(_match.title.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_matches(input: RString, _: &()) -> RVec<Match> {
|
#[get_matches]
|
||||||
|
pub fn get_matches(input: RString) -> RVec<Match> {
|
||||||
if !input.starts_with(":def") {
|
if !input.starts_with(":def") {
|
||||||
return RVec::new();
|
return RVec::new();
|
||||||
}
|
}
|
||||||
@@ -87,11 +93,10 @@ pub fn get_matches(input: RString, _: &()) -> RVec<Match> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn info() -> PluginInfo {
|
fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Dictionary".into(),
|
name: "Dictionary".into(),
|
||||||
icon: "accessories-dictionary".into(),
|
icon: "accessories-dictionary".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, ());
|
|
||||||
|
@@ -26,6 +26,7 @@ impl From<u64> for IndexAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[handler]
|
||||||
pub fn handler(selection: Match, state: &mut State) -> HandleResult {
|
pub fn handler(selection: Match, state: &mut State) -> HandleResult {
|
||||||
match &state.selection {
|
match &state.selection {
|
||||||
Some(index_entry) => match selection.id.unwrap().into() {
|
Some(index_entry) => match selection.id.unwrap().into() {
|
||||||
@@ -56,6 +57,7 @@ pub fn handler(selection: Match, state: &mut State) -> HandleResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
pub fn init(_config_dir: RString) -> State {
|
pub fn init(_config_dir: RString) -> State {
|
||||||
State {
|
State {
|
||||||
index: match kidex_common::util::get_index(None) {
|
index: match kidex_common::util::get_index(None) {
|
||||||
@@ -69,6 +71,7 @@ pub fn init(_config_dir: RString) -> State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
||||||
match &state.selection {
|
match &state.selection {
|
||||||
Some(index_entry) => {
|
Some(index_entry) => {
|
||||||
@@ -140,11 +143,10 @@ pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
pub fn info() -> PluginInfo {
|
pub fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Kidex".into(),
|
name: "Kidex".into(),
|
||||||
icon: "folder".into(),
|
icon: "folder".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, State);
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
use randr::{dummy::Dummy, hyprland::Hyprland, Configure, Monitor, Randr};
|
use randr::{dummy::Dummy, hyprland::Hyprland, Configure, Monitor, Randr};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -32,6 +32,7 @@ pub struct State {
|
|||||||
inner: InnerState,
|
inner: InnerState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
pub fn init(config_dir: RString) -> State {
|
pub fn init(config_dir: RString) -> State {
|
||||||
// Determine which Randr implementation should be used
|
// Determine which Randr implementation should be used
|
||||||
let randr: Box<dyn Randr + Send + Sync> = if env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() {
|
let randr: Box<dyn Randr + Send + Sync> = if env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() {
|
||||||
@@ -53,6 +54,7 @@ pub fn init(config_dir: RString) -> State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
pub fn info() -> PluginInfo {
|
pub fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Randr".into(),
|
name: "Randr".into(),
|
||||||
@@ -60,6 +62,7 @@ pub fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[handler]
|
||||||
pub fn handler(_match: Match, state: &mut State) -> HandleResult {
|
pub fn handler(_match: Match, state: &mut State) -> HandleResult {
|
||||||
match &state.inner {
|
match &state.inner {
|
||||||
InnerState::None => {
|
InnerState::None => {
|
||||||
@@ -98,6 +101,7 @@ pub fn handler(_match: Match, state: &mut State) -> HandleResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
||||||
if !input.starts_with(&state.config.prefix) {
|
if !input.starts_with(&state.config.prefix) {
|
||||||
return RVec::new();
|
return RVec::new();
|
||||||
@@ -187,5 +191,3 @@ pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
|||||||
|
|
||||||
vec.into_iter().map(|(_match, _)| _match).collect()
|
vec.into_iter().map(|(_match, _)| _match).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, State);
|
|
||||||
|
@@ -1,15 +1,10 @@
|
|||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
|
use rink_core::{ast, date, gnu_units, CURRENCY_FILE};
|
||||||
|
|
||||||
fn init(_config_dir: RString) {
|
#[init]
|
||||||
// Currently broken due to limitations with the declarative macro anyrun_plugin crate.
|
fn init(_config_dir: RString) -> rink_core::Context {
|
||||||
// For any plugin that does something relatively time intensive like fetching something
|
let mut ctx = rink_core::Context::new();
|
||||||
// from the internet, the internal Mutex would block making requests way too long when typed rapidly.
|
|
||||||
|
|
||||||
// TODO: Redesign the anyrun_plugin crate to allow for both mutable and non mutable borrows of the
|
|
||||||
// shared data for functions
|
|
||||||
|
|
||||||
/*let mut ctx = rink_core::Context::new();
|
|
||||||
|
|
||||||
let units = gnu_units::parse_str(rink_core::DEFAULT_FILE.unwrap());
|
let units = gnu_units::parse_str(rink_core::DEFAULT_FILE.unwrap());
|
||||||
let dates = date::parse_datefile(rink_core::DATES_FILE);
|
let dates = date::parse_datefile(rink_core::DATES_FILE);
|
||||||
@@ -34,9 +29,10 @@ fn init(_config_dir: RString) {
|
|||||||
});
|
});
|
||||||
ctx.load_dates(dates);
|
ctx.load_dates(dates);
|
||||||
|
|
||||||
ctx*/
|
ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn info() -> PluginInfo {
|
fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Rink".into(),
|
name: "Rink".into(),
|
||||||
@@ -44,11 +40,9 @@ fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_matches(input: RString, _: &()) -> RVec<Match> {
|
#[get_matches]
|
||||||
match rink_core::one_line(
|
fn get_matches(input: RString, ctx: &mut rink_core::Context) -> RVec<Match> {
|
||||||
&mut rink_core::simple_context().expect("Failed to create rink context"),
|
match rink_core::one_line(ctx, &input) {
|
||||||
&input,
|
|
||||||
) {
|
|
||||||
Ok(result) => vec![Match {
|
Ok(result) => vec![Match {
|
||||||
title: result.into(),
|
title: result.into(),
|
||||||
description: ROption::RNone,
|
description: ROption::RNone,
|
||||||
@@ -61,8 +55,7 @@ fn get_matches(input: RString, _: &()) -> RVec<Match> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(selection: Match, _: &mut ()) -> HandleResult {
|
#[handler]
|
||||||
|
fn handler(selection: Match) -> HandleResult {
|
||||||
HandleResult::Copy(selection.title.into_bytes())
|
HandleResult::Copy(selection.title.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, ());
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::{env, fs, process::Command};
|
use std::{env, fs, process::Command};
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@@ -19,6 +19,7 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
fn init(config_dir: RString) -> Config {
|
fn init(config_dir: RString) -> Config {
|
||||||
match fs::read_to_string(format!("{}/shell.ron", config_dir)) {
|
match fs::read_to_string(format!("{}/shell.ron", config_dir)) {
|
||||||
Ok(content) => ron::from_str(&content).unwrap_or_default(),
|
Ok(content) => ron::from_str(&content).unwrap_or_default(),
|
||||||
@@ -26,6 +27,7 @@ fn init(config_dir: RString) -> Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn info() -> PluginInfo {
|
fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Shell".into(),
|
name: "Shell".into(),
|
||||||
@@ -33,6 +35,7 @@ fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
fn get_matches(input: RString, config: &Config) -> RVec<Match> {
|
fn get_matches(input: RString, config: &Config) -> RVec<Match> {
|
||||||
if input.starts_with(&config.prefix) {
|
if input.starts_with(&config.prefix) {
|
||||||
let (_, command) = input.split_once(&config.prefix).unwrap();
|
let (_, command) = input.split_once(&config.prefix).unwrap();
|
||||||
@@ -63,7 +66,8 @@ fn get_matches(input: RString, config: &Config) -> RVec<Match> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(selection: Match, _config: &mut Config) -> HandleResult {
|
#[handler]
|
||||||
|
fn handler(selection: Match) -> HandleResult {
|
||||||
if let Err(why) = Command::new(selection.description.unwrap().as_str())
|
if let Err(why) = Command::new(selection.description.unwrap().as_str())
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(selection.title.as_str())
|
.arg(selection.title.as_str())
|
||||||
@@ -74,5 +78,3 @@ fn handler(selection: Match, _config: &mut Config) -> HandleResult {
|
|||||||
|
|
||||||
HandleResult::Close
|
HandleResult::Close
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, Config);
|
|
||||||
|
@@ -1,17 +1,20 @@
|
|||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
|
|
||||||
|
#[init]
|
||||||
fn init(_config_dir: RString) -> Vec<String> {
|
fn init(_config_dir: RString) -> Vec<String> {
|
||||||
stdin().lines().filter_map(|line| line.ok()).collect()
|
stdin().lines().filter_map(|line| line.ok()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(_match: Match, _lines: &mut Vec<String>) -> HandleResult {
|
#[handler]
|
||||||
|
fn handler(_match: Match) -> HandleResult {
|
||||||
HandleResult::Stdout(_match.title.into_bytes())
|
HandleResult::Stdout(_match.title.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
fn get_matches(input: RString, lines: &Vec<String>) -> RVec<Match> {
|
fn get_matches(input: RString, lines: &Vec<String>) -> RVec<Match> {
|
||||||
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
||||||
|
|
||||||
@@ -42,11 +45,10 @@ fn get_matches(input: RString, lines: &Vec<String>) -> RVec<Match> {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn plugin_info() -> PluginInfo {
|
fn plugin_info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Stdin".into(),
|
name: "Stdin".into(),
|
||||||
icon: "format-indent-more".into(),
|
icon: "format-indent-more".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, plugin_info, get_matches, handler, Vec<String>);
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::{collections::HashMap, fs};
|
use std::{collections::HashMap, fs};
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ struct Config {
|
|||||||
symbols: HashMap<String, String>,
|
symbols: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
fn init(config_dir: RString) -> Vec<Symbol> {
|
fn init(config_dir: RString) -> Vec<Symbol> {
|
||||||
// Try to load the config file, if it does not exist only use the static unicode characters
|
// Try to load the config file, if it does not exist only use the static unicode characters
|
||||||
if let Ok(content) = fs::read_to_string(format!("{}/symbols.ron", config_dir)) {
|
if let Ok(content) = fs::read_to_string(format!("{}/symbols.ron", config_dir)) {
|
||||||
@@ -46,6 +47,7 @@ fn init(config_dir: RString) -> Vec<Symbol> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn info() -> PluginInfo {
|
fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Symbols".into(),
|
name: "Symbols".into(),
|
||||||
@@ -53,6 +55,7 @@ fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
fn get_matches(input: RString, symbols: &Vec<Symbol>) -> RVec<Match> {
|
fn get_matches(input: RString, symbols: &Vec<Symbol>) -> RVec<Match> {
|
||||||
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().ignore_case();
|
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().ignore_case();
|
||||||
let mut symbols = symbols
|
let mut symbols = symbols
|
||||||
@@ -82,8 +85,7 @@ fn get_matches(input: RString, symbols: &Vec<Symbol>) -> RVec<Match> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(selection: Match, _symbols: &mut Vec<Symbol>) -> HandleResult {
|
#[handler]
|
||||||
|
fn handler(selection: Match) -> HandleResult {
|
||||||
HandleResult::Copy(selection.title.into_bytes())
|
HandleResult::Copy(selection.title.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, Vec<Symbol>);
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::{anyrun_interface::HandleResult, plugin, Match, PluginInfo};
|
use anyrun_plugin::*;
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ struct State {
|
|||||||
langs: Vec<(&'static str, &'static str)>,
|
langs: Vec<(&'static str, &'static str)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
fn init(config_dir: RString) -> State {
|
fn init(config_dir: RString) -> State {
|
||||||
State {
|
State {
|
||||||
config: match fs::read_to_string(format!("{}/translate.ron", config_dir)) {
|
config: match fs::read_to_string(format!("{}/translate.ron", config_dir)) {
|
||||||
@@ -138,6 +139,7 @@ fn init(config_dir: RString) -> State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[info]
|
||||||
fn info() -> PluginInfo {
|
fn info() -> PluginInfo {
|
||||||
PluginInfo {
|
PluginInfo {
|
||||||
name: "Translate".into(),
|
name: "Translate".into(),
|
||||||
@@ -145,6 +147,7 @@ fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get_matches]
|
||||||
fn get_matches(input: RString, data: &State) -> RVec<Match> {
|
fn get_matches(input: RString, data: &State) -> RVec<Match> {
|
||||||
if !input.starts_with(&data.config.prefix) {
|
if !input.starts_with(&data.config.prefix) {
|
||||||
return RVec::new();
|
return RVec::new();
|
||||||
@@ -227,8 +230,7 @@ fn get_matches(input: RString, data: &State) -> RVec<Match> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handler(selection: Match, _data: &mut State) -> HandleResult {
|
#[handler]
|
||||||
|
fn handler(selection: Match) -> HandleResult {
|
||||||
HandleResult::Copy(selection.title.into_bytes())
|
HandleResult::Copy(selection.title.into_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin!(init, info, get_matches, handler, State);
|
|
||||||
|
Reference in New Issue
Block a user