use std::collections::HashMap;
use std::env;
use std::path::PathBuf;
use crate::desktop;
use crate::provider::{Provider, run_provider};
pub struct DesktopProvider;
impl Provider for DesktopProvider {
type Item = desktop::DesktopInfo;
fn title(&self) -> &str {
"drun"
}
fn collect(&self) -> HashMap<String, desktop::DesktopInfo> {
let data_home = env::var_os("XDG_DATA_HOME")
.map(PathBuf::from)
.unwrap_or_else(|| {
let home = env::var_os("HOME").unwrap_or_default();
PathBuf::from(home).join(".local").join("share")
});
let data_dirs = env::var_os("XDG_DATA_DIRS")
.map(|p| env::split_paths(&p).collect::<Vec<_>>())
.unwrap_or_else(|| {
vec![
PathBuf::from("/usr/local/share"),
PathBuf::from("/usr/share"),
]
});
let mut applications_paths = Vec::new();
for path in std::iter::once(&data_home).chain(data_dirs.iter()) {
applications_paths.push(path.join("applications"));
}
let mut desktop_files = HashMap::new();
for dir in &applications_paths {
let Ok(entries) = dir.read_dir() else {
continue;
};
for entry in entries.flatten() {
let path = entry.path();
if path.extension().is_some_and(|e| e == "desktop")
&& path.is_file()
&& let Some(info) = desktop::parse_desktop_info(&path)
{
desktop_files.entry(info.name.clone()).or_insert(info);
}
}
}
desktop_files
}
fn launch(&self, item: &desktop::DesktopInfo) {
desktop::launch(item);
}
}
pub fn drun() -> i32 {
run_provider(DesktopProvider)
}