Desktop Action support for the Applications plugin
This commit is contained in:
57
Cargo.lock
generated
57
Cargo.lock
generated
@@ -37,7 +37,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustc_version 0.4.0",
|
"rustc_version 0.4.0",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
"typed-arena",
|
"typed-arena",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -101,6 +101,8 @@ dependencies = [
|
|||||||
"abi_stable",
|
"abi_stable",
|
||||||
"anyrun-plugin",
|
"anyrun-plugin",
|
||||||
"fuzzy-matcher",
|
"fuzzy-matcher",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
"sublime_fuzzy",
|
"sublime_fuzzy",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ dependencies = [
|
|||||||
"core_extensions",
|
"core_extensions",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -352,7 +354,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"scratch",
|
"scratch",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -369,7 +371,7 @@ checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -380,7 +382,7 @@ checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -509,7 +511,7 @@ checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -686,7 +688,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -790,7 +792,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1267,7 +1269,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1433,7 +1435,7 @@ dependencies = [
|
|||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1450,18 +1452,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.49"
|
version = "1.0.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -1676,22 +1678,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.159"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.152"
|
version = "1.0.159"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.13",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1792,6 +1794,17 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "6.0.3"
|
version = "6.0.3"
|
||||||
@@ -1845,7 +1858,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2120,7 +2133,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2154,7 +2167,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.107",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@@ -13,3 +13,5 @@ anyrun-plugin = { path = "../../anyrun-plugin" }
|
|||||||
abi_stable = "0.11.1"
|
abi_stable = "0.11.1"
|
||||||
sublime_fuzzy = "0.7.0"
|
sublime_fuzzy = "0.7.0"
|
||||||
fuzzy-matcher = "0.3.7"
|
fuzzy-matcher = "0.3.7"
|
||||||
|
ron = "0.8.0"
|
||||||
|
serde = { version = "1.0.159", features = ["derive"] }
|
||||||
|
@@ -2,7 +2,13 @@ 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 scrubber::DesktopEntry;
|
use scrubber::DesktopEntry;
|
||||||
use std::process::Command;
|
use serde::Deserialize;
|
||||||
|
use std::{fs, process::Command};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
pub struct Config {
|
||||||
|
desktop_actions: bool,
|
||||||
|
}
|
||||||
|
|
||||||
mod scrubber;
|
mod scrubber;
|
||||||
|
|
||||||
@@ -25,8 +31,22 @@ pub fn handler(selection: Match, entries: &mut Vec<(DesktopEntry, u64)>) -> Hand
|
|||||||
HandleResult::Close
|
HandleResult::Close
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(_config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
pub fn init(config_dir: RString) -> Vec<(DesktopEntry, u64)> {
|
||||||
scrubber::scrubber().expect("Failed to load desktop entries!")
|
let config: Config = match fs::read_to_string(format!("{}/applications.ron", config_dir)) {
|
||||||
|
Ok(content) => ron::from_str(&content).unwrap_or_else(|why| {
|
||||||
|
eprintln!("Error parsing applications plugin config: {}", why);
|
||||||
|
Config::default()
|
||||||
|
}),
|
||||||
|
Err(why) => {
|
||||||
|
eprintln!("Error reading applications plugin config: {}", why);
|
||||||
|
Config::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scrubber::scrubber(config).unwrap_or_else(|why| {
|
||||||
|
eprintln!("Failed to load desktop entries: {}", why);
|
||||||
|
Vec::new()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_matches(input: RString, entries: &mut Vec<(DesktopEntry, u64)>) -> RVec<Match> {
|
pub fn get_matches(input: RString, entries: &mut Vec<(DesktopEntry, u64)>) -> RVec<Match> {
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
use std::{collections::HashMap, env, ffi::OsStr, fs, io};
|
use std::{collections::HashMap, env, ffi::OsStr, fs, io};
|
||||||
|
|
||||||
|
use crate::Config;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DesktopEntry {
|
pub struct DesktopEntry {
|
||||||
pub exec: String,
|
pub exec: String,
|
||||||
@@ -12,55 +14,118 @@ const FIELD_CODE_LIST: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
impl DesktopEntry {
|
impl DesktopEntry {
|
||||||
fn from_dir_entry(entry: &fs::DirEntry) -> Option<Self> {
|
fn from_dir_entry(entry: &fs::DirEntry, config: &Config) -> Vec<Self> {
|
||||||
if entry.path().extension() == Some(OsStr::new("desktop")) {
|
if entry.path().extension() == Some(OsStr::new("desktop")) {
|
||||||
let content = match fs::read_to_string(entry.path()) {
|
let content = match fs::read_to_string(entry.path()) {
|
||||||
Ok(content) => content,
|
Ok(content) => content,
|
||||||
Err(_) => return None,
|
Err(_) => return Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut map = HashMap::new();
|
let lines = content.lines().collect::<Vec<_>>();
|
||||||
for line in content.lines() {
|
|
||||||
if line.starts_with("[") && line != "[Desktop Entry]" {
|
let sections = lines
|
||||||
break;
|
.split_inclusive(|line| line.starts_with('['))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut line = None;
|
||||||
|
let mut new_sections = Vec::new();
|
||||||
|
|
||||||
|
for section in sections.iter() {
|
||||||
|
if let Some(line) = line {
|
||||||
|
let mut section = section.to_vec();
|
||||||
|
section.insert(0, line);
|
||||||
|
section.pop();
|
||||||
|
new_sections.push(section);
|
||||||
}
|
}
|
||||||
let (key, val) = match line.split_once("=") {
|
line = Some(section.last().unwrap_or(&""));
|
||||||
Some(keyval) => keyval,
|
|
||||||
None => continue,
|
|
||||||
};
|
|
||||||
map.insert(key, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if map.get("Type")? == &"Application"
|
let mut ret = Vec::new();
|
||||||
&& match map.get("NoDisplay") {
|
|
||||||
Some(no_display) => !no_display.parse::<bool>().unwrap_or(true),
|
let entry = match new_sections.iter().find_map(|section| {
|
||||||
None => true,
|
if section[0].starts_with("[Desktop Entry]") {
|
||||||
}
|
let mut map = HashMap::new();
|
||||||
{
|
|
||||||
Some(DesktopEntry {
|
for line in section.iter().skip(1) {
|
||||||
exec: {
|
if let Some((key, val)) = line.split_once('=') {
|
||||||
let mut exec = map.get("Exec")?.to_string();
|
map.insert(key, val);
|
||||||
for field_code in FIELD_CODE_LIST {
|
|
||||||
exec = exec.replace(field_code, "");
|
|
||||||
}
|
}
|
||||||
exec
|
}
|
||||||
},
|
|
||||||
name: map.get("Name")?.to_string(),
|
if map.get("Type")? == &"Application"
|
||||||
icon: map
|
&& match map.get("NoDisplay") {
|
||||||
.get("Icon")
|
Some(no_display) => !no_display.parse::<bool>().unwrap_or(true),
|
||||||
.unwrap_or(&"application-x-executable")
|
None => true,
|
||||||
.to_string(),
|
}
|
||||||
})
|
{
|
||||||
} else {
|
Some(DesktopEntry {
|
||||||
None
|
exec: {
|
||||||
|
let mut exec = map.get("Exec")?.to_string();
|
||||||
|
|
||||||
|
for field_code in FIELD_CODE_LIST {
|
||||||
|
exec = exec.replace(field_code, "");
|
||||||
|
}
|
||||||
|
exec
|
||||||
|
},
|
||||||
|
name: map.get("Name")?.to_string(),
|
||||||
|
icon: map
|
||||||
|
.get("Icon")
|
||||||
|
.unwrap_or(&"application-x-executable")
|
||||||
|
.to_string(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Some(entry) => entry,
|
||||||
|
None => return Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if config.desktop_actions {
|
||||||
|
for section in new_sections {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
for line in section.iter().skip(1) {
|
||||||
|
if let Some((key, val)) = line.split_once('=') {
|
||||||
|
map.insert(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if section[0].starts_with("[Desktop Action") {
|
||||||
|
ret.push(DesktopEntry {
|
||||||
|
exec: match map.get("Exec") {
|
||||||
|
Some(exec) => {
|
||||||
|
let mut exec = exec.to_string();
|
||||||
|
|
||||||
|
for field_code in FIELD_CODE_LIST {
|
||||||
|
exec = exec.replace(field_code, "");
|
||||||
|
}
|
||||||
|
exec
|
||||||
|
}
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
name: match map.get("Name") {
|
||||||
|
Some(name) => format!("{}: {}", entry.name, name),
|
||||||
|
None => continue,
|
||||||
|
},
|
||||||
|
icon: entry.icon.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.push(entry);
|
||||||
|
ret
|
||||||
} else {
|
} else {
|
||||||
None
|
Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scrubber() -> 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") {
|
||||||
@@ -68,7 +133,7 @@ pub fn scrubber() -> Result<Vec<(DesktopEntry, u64)>, Box<dyn std::error::Error>
|
|||||||
// The vec for all the DirEntry objects
|
// The vec for all the DirEntry objects
|
||||||
let mut paths = Vec::new();
|
let mut paths = Vec::new();
|
||||||
// Parse the XDG_DATA_DIRS variable and list files of all the paths
|
// Parse the XDG_DATA_DIRS variable and list files of all the paths
|
||||||
for dir in data_dirs.split(":") {
|
for dir in data_dirs.split(':') {
|
||||||
match fs::read_dir(format!("{}/applications/", dir)) {
|
match fs::read_dir(format!("{}/applications/", dir)) {
|
||||||
Ok(dir) => {
|
Ok(dir) => {
|
||||||
paths.extend(dir);
|
paths.extend(dir);
|
||||||
@@ -102,20 +167,19 @@ pub fn scrubber() -> Result<Vec<(DesktopEntry, u64)>, Box<dyn std::error::Error>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
paths.extend(fs::read_dir(&user_path)?);
|
paths.extend(fs::read_dir(user_path)?);
|
||||||
|
|
||||||
// Keeping track of the entries
|
|
||||||
let mut id = 0;
|
|
||||||
|
|
||||||
Ok(paths
|
Ok(paths
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|entry| {
|
.filter_map(|entry| {
|
||||||
id += 1;
|
|
||||||
let entry = match entry {
|
let entry = match entry {
|
||||||
Ok(entry) => entry,
|
Ok(entry) => entry,
|
||||||
Err(_why) => return None,
|
Err(_why) => return None,
|
||||||
};
|
};
|
||||||
DesktopEntry::from_dir_entry(entry).map(|val| (val, id))
|
Some(DesktopEntry::from_dir_entry(entry, &config))
|
||||||
})
|
})
|
||||||
|
.flatten()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, val)| (val, i as u64))
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user