Add max_entries config to plugins (#19)
This commit is contained in:

committed by
GitHub

parent
90ecba8261
commit
0aabb332c9
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -436,6 +436,7 @@ dependencies = [
|
|||||||
"abi_stable",
|
"abi_stable",
|
||||||
"anyrun-plugin",
|
"anyrun-plugin",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1073,6 +1074,8 @@ dependencies = [
|
|||||||
"fuzzy-matcher",
|
"fuzzy-matcher",
|
||||||
"kidex-common",
|
"kidex-common",
|
||||||
"open",
|
"open",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@@ -5,16 +5,32 @@ use scrubber::DesktopEntry;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{fs, process::Command};
|
use std::{fs, process::Command};
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
desktop_actions: bool,
|
desktop_actions: bool,
|
||||||
|
max_entries: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
desktop_actions: false,
|
||||||
|
max_entries: 5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
config: Config,
|
||||||
|
entries: Vec<(DesktopEntry, u64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod scrubber;
|
mod scrubber;
|
||||||
|
|
||||||
#[handler]
|
#[handler]
|
||||||
pub fn handler(selection: Match, entries: &Vec<(DesktopEntry, u64)>) -> HandleResult {
|
pub fn handler(selection: Match, state: &State) -> HandleResult {
|
||||||
let entry = entries
|
let entry = state
|
||||||
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(entry, id)| {
|
.find_map(|(entry, id)| {
|
||||||
if *id == selection.id.unwrap() {
|
if *id == selection.id.unwrap() {
|
||||||
@@ -33,7 +49,7 @@ pub fn handler(selection: Match, entries: &Vec<(DesktopEntry, u64)>) -> HandleRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
pub fn init(config_dir: RString) -> State {
|
||||||
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| {
|
||||||
eprintln!("Error parsing applications plugin config: {}", why);
|
eprintln!("Error parsing applications plugin config: {}", why);
|
||||||
@@ -45,24 +61,26 @@ pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
scrubber::scrubber(config).unwrap_or_else(|why| {
|
let entries = scrubber::scrubber(&config).unwrap_or_else(|why| {
|
||||||
eprintln!("Failed to load desktop entries: {}", why);
|
eprintln!("Failed to load desktop entries: {}", why);
|
||||||
Vec::new()
|
Vec::new()
|
||||||
})
|
});
|
||||||
|
|
||||||
|
State { config, entries }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get_matches]
|
#[get_matches]
|
||||||
pub fn get_matches(input: RString, entries: &Vec<(DesktopEntry, u64)>) -> RVec<Match> {
|
pub fn get_matches(input: RString, state: &State) -> 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 = state
|
||||||
.clone()
|
.entries
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|(entry, id)| {
|
.filter_map(|(entry, id)| {
|
||||||
let score = matcher.fuzzy_match(&entry.name, &input).unwrap_or(0)
|
let score = matcher.fuzzy_match(&entry.name, &input).unwrap_or(0)
|
||||||
+ matcher.fuzzy_match(&entry.exec, &input).unwrap_or(0);
|
+ matcher.fuzzy_match(&entry.exec, &input).unwrap_or(0);
|
||||||
|
|
||||||
if score > 0 {
|
if score > 0 {
|
||||||
Some((entry, id, score))
|
Some((entry, *id, score))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -71,14 +89,14 @@ pub fn get_matches(input: RString, entries: &Vec<(DesktopEntry, u64)>) -> RVec<M
|
|||||||
|
|
||||||
entries.sort_by(|a, b| b.2.cmp(&a.2));
|
entries.sort_by(|a, b| b.2.cmp(&a.2));
|
||||||
|
|
||||||
entries.truncate(5);
|
entries.truncate(state.config.max_entries);
|
||||||
entries
|
entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(entry, id, _)| Match {
|
.map(|(entry, id, _)| Match {
|
||||||
title: entry.name.into(),
|
title: entry.name.clone().into(),
|
||||||
description: entry.desc.map(|desc| desc.into()).into(),
|
description: entry.desc.clone().map(|desc| desc.into()).into(),
|
||||||
use_pango: false,
|
use_pango: false,
|
||||||
icon: ROption::RSome(entry.icon.into()),
|
icon: ROption::RSome(entry.icon.clone().into()),
|
||||||
id: ROption::RSome(id),
|
id: ROption::RSome(id),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@@ -132,7 +132,7 @@ impl DesktopEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scrubber(config: Config) -> Result<Vec<(DesktopEntry, u64)>, Box<dyn std::error::Error>> {
|
pub fn scrubber(config: &Config) -> Result<Vec<(DesktopEntry, u64)>, Box<dyn std::error::Error>> {
|
||||||
// Create iterator over all the files in the XDG_DATA_DIRS
|
// Create iterator over all the files in the XDG_DATA_DIRS
|
||||||
// XDG compliancy is cool
|
// XDG compliancy is cool
|
||||||
let mut paths: Vec<Result<fs::DirEntry, io::Error>> = match env::var("XDG_DATA_DIRS") {
|
let mut paths: Vec<Result<fs::DirEntry, io::Error>> = match env::var("XDG_DATA_DIRS") {
|
||||||
@@ -186,7 +186,7 @@ pub fn scrubber(config: Config) -> Result<Vec<(DesktopEntry, u64)>, Box<dyn std:
|
|||||||
Ok(entry) => entry,
|
Ok(entry) => entry,
|
||||||
Err(_why) => return None,
|
Err(_why) => return None,
|
||||||
};
|
};
|
||||||
Some(DesktopEntry::from_dir_entry(entry, &config))
|
Some(DesktopEntry::from_dir_entry(entry, config))
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@@ -13,3 +13,4 @@ anyrun-plugin = { path = "../../anyrun-plugin" }
|
|||||||
abi_stable = "0.11.1"
|
abi_stable = "0.11.1"
|
||||||
reqwest = { version = "0.11.16", default-features = false, features = ["blocking", "json", "rustls-tls"] }
|
reqwest = { version = "0.11.16", default-features = false, features = ["blocking", "json", "rustls-tls"] }
|
||||||
serde = { version = "1.0.160", features = ["derive"] }
|
serde = { version = "1.0.160", features = ["derive"] }
|
||||||
|
ron = "0.8.0"
|
||||||
|
@@ -1,7 +1,24 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
use abi_stable::std_types::{ROption, RString, RVec};
|
use abi_stable::std_types::{ROption, RString, RVec};
|
||||||
use anyrun_plugin::*;
|
use anyrun_plugin::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
prefix: String,
|
||||||
|
max_entries: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
prefix: ":def".to_string(),
|
||||||
|
max_entries: 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ApiResponse {
|
struct ApiResponse {
|
||||||
@@ -36,7 +53,12 @@ struct Definition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
pub fn init(_config_dir: RString) {}
|
pub fn init(config_dir: RString) -> Config {
|
||||||
|
match fs::read_to_string(format!("{}/dictionary.ron", config_dir)) {
|
||||||
|
Ok(content) => ron::from_str(&content).unwrap_or_default(),
|
||||||
|
Err(_) => Config::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[handler]
|
#[handler]
|
||||||
pub fn handler(_match: Match) -> HandleResult {
|
pub fn handler(_match: Match) -> HandleResult {
|
||||||
@@ -44,12 +66,12 @@ pub fn handler(_match: Match) -> HandleResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get_matches]
|
#[get_matches]
|
||||||
pub fn get_matches(input: RString) -> RVec<Match> {
|
pub fn get_matches(input: RString, config: &Config) -> RVec<Match> {
|
||||||
if !input.starts_with(":def") {
|
let input = if let Some(input) = input.strip_prefix(&config.prefix) {
|
||||||
|
input.trim()
|
||||||
|
} else {
|
||||||
return RVec::new();
|
return RVec::new();
|
||||||
}
|
};
|
||||||
|
|
||||||
let input = &input[4..].trim();
|
|
||||||
|
|
||||||
let responses: Vec<ApiResponse> = match reqwest::blocking::get(format!(
|
let responses: Vec<ApiResponse> = match reqwest::blocking::get(format!(
|
||||||
"https://api.dictionaryapi.dev/api/v2/entries/en/{}",
|
"https://api.dictionaryapi.dev/api/v2/entries/en/{}",
|
||||||
@@ -89,7 +111,7 @@ pub fn get_matches(input: RString) -> RVec<Match> {
|
|||||||
})
|
})
|
||||||
.collect::<RVec<_>>()
|
.collect::<RVec<_>>()
|
||||||
})
|
})
|
||||||
.take(3)
|
.take(config.max_entries)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,3 +14,5 @@ kidex-common = { git = "https://github.com/Kirottu/kidex", features = ["util"] }
|
|||||||
abi_stable = "0.11.1"
|
abi_stable = "0.11.1"
|
||||||
fuzzy-matcher = "0.3.7"
|
fuzzy-matcher = "0.3.7"
|
||||||
open = "3.2.0"
|
open = "3.2.0"
|
||||||
|
serde = { version = "1.0.160", features = ["derive"] }
|
||||||
|
ron = "0.8.0"
|
||||||
|
@@ -2,9 +2,22 @@ use abi_stable::std_types::{ROption, RString, RVec};
|
|||||||
use anyrun_plugin::{anyrun_interface::HandleResult, *};
|
use anyrun_plugin::{anyrun_interface::HandleResult, *};
|
||||||
use fuzzy_matcher::FuzzyMatcher;
|
use fuzzy_matcher::FuzzyMatcher;
|
||||||
use kidex_common::IndexEntry;
|
use kidex_common::IndexEntry;
|
||||||
use std::{os::unix::prelude::OsStrExt, process::Command};
|
use serde::Deserialize;
|
||||||
|
use std::{fs, os::unix::prelude::OsStrExt, process::Command};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Config {
|
||||||
|
max_entries: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { max_entries: 3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
config: Config,
|
||||||
index: Vec<(usize, IndexEntry)>,
|
index: Vec<(usize, IndexEntry)>,
|
||||||
selection: Option<IndexEntry>,
|
selection: Option<IndexEntry>,
|
||||||
}
|
}
|
||||||
@@ -58,15 +71,21 @@ pub fn handler(selection: Match, state: &mut State) -> HandleResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
pub fn init(_config_dir: RString) -> State {
|
pub fn init(config_dir: RString) -> State {
|
||||||
|
let config = match fs::read_to_string(format!("{}/kidex.ron", config_dir)) {
|
||||||
|
Ok(content) => ron::from_str(&content).unwrap_or_default(),
|
||||||
|
Err(_) => Config::default(),
|
||||||
|
};
|
||||||
|
let index = match kidex_common::util::get_index(None) {
|
||||||
|
Ok(index) => index.into_iter().enumerate().collect(),
|
||||||
|
Err(why) => {
|
||||||
|
println!("Failed to get kidex index: {}", why);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
};
|
||||||
State {
|
State {
|
||||||
index: match kidex_common::util::get_index(None) {
|
config,
|
||||||
Ok(index) => index.into_iter().enumerate().collect(),
|
index,
|
||||||
Err(why) => {
|
|
||||||
println!("Failed to get kidex index: {}", why);
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selection: None,
|
selection: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +135,7 @@ pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
|||||||
|
|
||||||
index.sort_by(|a, b| b.2.cmp(&a.2));
|
index.sort_by(|a, b| b.2.cmp(&a.2));
|
||||||
|
|
||||||
index.truncate(3);
|
index.truncate(state.config.max_entries);
|
||||||
index
|
index
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(entry_index, id, _)| Match {
|
.map(|(entry_index, id, _)| Match {
|
||||||
|
@@ -11,12 +11,14 @@ mod randr;
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
prefix: String,
|
prefix: String,
|
||||||
|
max_entries: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Config {
|
Config {
|
||||||
prefix: ":dp".to_string(),
|
prefix: ":dp".to_string(),
|
||||||
|
max_entries: 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,11 +105,11 @@ pub fn handler(_match: Match, state: &mut State) -> HandleResult {
|
|||||||
|
|
||||||
#[get_matches]
|
#[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) {
|
let input = if let Some(input) = input.strip_prefix(&state.config.prefix) {
|
||||||
|
input.trim()
|
||||||
|
} else {
|
||||||
return RVec::new();
|
return RVec::new();
|
||||||
}
|
};
|
||||||
|
|
||||||
let input = &input[state.config.prefix.len()..].trim();
|
|
||||||
|
|
||||||
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default().smart_case();
|
||||||
let mut vec = match &state.inner {
|
let mut vec = match &state.inner {
|
||||||
@@ -187,7 +189,7 @@ pub fn get_matches(input: RString, state: &State) -> RVec<Match> {
|
|||||||
|
|
||||||
vec.sort_by(|a, b| b.1.cmp(&a.1));
|
vec.sort_by(|a, b| b.1.cmp(&a.1));
|
||||||
|
|
||||||
vec.truncate(5);
|
vec.truncate(state.config.max_entries);
|
||||||
|
|
||||||
vec.into_iter().map(|(_match, _)| _match).collect()
|
vec.into_iter().map(|(_match, _)| _match).collect()
|
||||||
}
|
}
|
||||||
|
@@ -16,35 +16,40 @@ struct Symbol {
|
|||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct Config {
|
struct Config {
|
||||||
symbols: HashMap<String, String>,
|
symbols: HashMap<String, String>,
|
||||||
|
max_entries: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
symbols: HashMap::new(),
|
||||||
|
max_entries: 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
config: Config,
|
||||||
|
symbols: Vec<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(config_dir: RString) -> Vec<Symbol> {
|
fn init(config_dir: RString) -> State {
|
||||||
// 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)) {
|
let config = if let Ok(content) = fs::read_to_string(format!("{}/symbols.ron", config_dir)) {
|
||||||
match ron::from_str::<Config>(&content) {
|
ron::from_str(&content).unwrap_or_default()
|
||||||
Ok(config) => {
|
} else {
|
||||||
let symbols = UNICODE_CHARS
|
Config::default()
|
||||||
.iter()
|
};
|
||||||
.map(|(name, chr)| (name.to_string(), chr.to_string()))
|
|
||||||
.chain(config.symbols.into_iter())
|
|
||||||
.map(|(name, chr)| Symbol { chr, name })
|
|
||||||
.collect();
|
|
||||||
return symbols;
|
|
||||||
}
|
|
||||||
Err(why) => {
|
|
||||||
println!("Error parsing symbols config file: {}", why);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UNICODE_CHARS
|
let symbols = UNICODE_CHARS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, chr)| Symbol {
|
.map(|(name, chr)| (name.to_string(), chr.to_string()))
|
||||||
chr: chr.to_string(),
|
.chain(config.symbols.clone().into_iter())
|
||||||
name: name.to_string(),
|
.map(|(name, chr)| Symbol { chr, name })
|
||||||
})
|
.collect();
|
||||||
.collect()
|
|
||||||
|
State { config, symbols }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[info]
|
#[info]
|
||||||
@@ -56,11 +61,11 @@ fn info() -> PluginInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get_matches]
|
#[get_matches]
|
||||||
fn get_matches(input: RString, symbols: &Vec<Symbol>) -> RVec<Match> {
|
fn get_matches(input: RString, state: &State) -> 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 = state
|
||||||
.clone()
|
.symbols
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|symbol| {
|
.filter_map(|symbol| {
|
||||||
matcher
|
matcher
|
||||||
.fuzzy_match(&symbol.name, &input)
|
.fuzzy_match(&symbol.name, &input)
|
||||||
@@ -71,13 +76,13 @@ fn get_matches(input: RString, symbols: &Vec<Symbol>) -> RVec<Match> {
|
|||||||
// Sort the symbol list according to the score
|
// Sort the symbol list according to the score
|
||||||
symbols.sort_by(|a, b| b.1.cmp(&a.1));
|
symbols.sort_by(|a, b| b.1.cmp(&a.1));
|
||||||
|
|
||||||
symbols.truncate(3);
|
symbols.truncate(state.config.max_entries);
|
||||||
|
|
||||||
symbols
|
symbols
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(symbol, _)| Match {
|
.map(|(symbol, _)| Match {
|
||||||
title: symbol.chr.into(),
|
title: symbol.chr.clone().into(),
|
||||||
description: ROption::RSome(symbol.name.into()),
|
description: ROption::RSome(symbol.name.clone().into()),
|
||||||
use_pango: false,
|
use_pango: false,
|
||||||
icon: ROption::RNone,
|
icon: ROption::RNone,
|
||||||
id: ROption::RNone,
|
id: ROption::RNone,
|
||||||
|
@@ -8,12 +8,14 @@ use serde::Deserialize;
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
prefix: String,
|
prefix: String,
|
||||||
|
max_entries: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
prefix: ":".to_string(),
|
prefix: ":".to_string(),
|
||||||
|
max_entries: 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +184,7 @@ fn get_matches(input: RString, data: &State) -> RVec<Match> {
|
|||||||
matches.sort_by(|a, b| b.2.cmp(&a.2));
|
matches.sort_by(|a, b| b.2.cmp(&a.2));
|
||||||
|
|
||||||
// We only want 3 matches
|
// We only want 3 matches
|
||||||
matches.truncate(3);
|
matches.truncate(data.config.max_entries);
|
||||||
|
|
||||||
tokio::runtime::Runtime::new().expect("Failed to spawn tokio runtime!").block_on(async move {
|
tokio::runtime::Runtime::new().expect("Failed to spawn tokio runtime!").block_on(async move {
|
||||||
// Create the futures for fetching the translation results
|
// Create the futures for fetching the translation results
|
||||||
|
Reference in New Issue
Block a user