dots/.config/awesome/ui/fresnel/lenses/src/application.rs

108 lines
2.9 KiB
Rust

use std::{
fs::read_dir,
path::PathBuf,
};
use freedesktop_entry_parser as fd;
use mlua::prelude::*;
use parking_lot::Mutex;
use rayon::prelude::*;
use url::Url;
use crate::entry::{
entries_to_lua_table,
Entry,
};
fn parse_entry<'a>(entry: fd::Entry, path: PathBuf) -> Result<Entry, ()> {
let section = entry.section("Desktop Entry");
let name = section.attr("Name").ok_or(())?.to_string();
if section.attr("Type").ok_or(())? != "Application" {
return Err(());
}
match section.attr("OnlyShowIn") {
Some(_) => return Err(()),
None => {}
}
match section.attr("Hidden") {
Some(_) => return Err(()),
None => {}
}
match section.attr("NoDisplay") {
Some(_) => return Err(()),
None => {}
}
let exec = section.attr("Exec").ok_or(())?.to_string();
let mut new_exec = exec.clone();
for (index, _) in exec.match_indices("%") {
match exec.chars().nth(index + 1).unwrap().to_ascii_lowercase() {
'i' => match section.attr("Icon") {
Some(icon) => new_exec.replace_range(index..index + 2, &format!("--icon {}", icon)),
None => {}
},
'c' => new_exec.replace_range(index..index + 2, &name),
'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(&path)?.as_str()),
'f' | 'u' | 'v' | 'm' | 'd' | 'n' => new_exec.replace_range(index..index + 2, ""),
_ => continue,
}
}
Ok(Entry {
message: name,
exec: Some((
new_exec,
section
.attr("Terminal")
.unwrap_or("false")
.parse()
.map_err(drop)?,
)),
provider: "Application".to_string(),
})
}
pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
let applications_dir = "/usr/share/applications";
let entries = read_dir(applications_dir)?
.map(|result| result.map(|e| e.path()))
.collect::<Result<Vec<_>, std::io::Error>>()?;
let entries = entries
.into_iter()
.filter(|e| match e.extension() {
Some(ext) if ext == "desktop" => true,
None | _ => false,
})
.collect::<Vec<_>>();
let mut parsed_entries: Mutex<Vec<Entry>> = Mutex::new(Vec::new());
entries.into_par_iter().for_each(|path| {
let entry = match fd::parse_entry(&path) {
Ok(entry) => entry,
Err(_) => return,
};
match parse_entry(entry, path) {
Ok(parsed_entry) => parsed_entries.lock().push(parsed_entry),
Err(_) => return,
}
});
Ok(entries_to_lua_table(
parsed_entries
.get_mut()
.iter()
.filter(|entry| entry.message.to_lowercase().contains(&input))
.map(|entry| (*entry).clone())
.collect(),
lua,
))
}