lowfat_plugin/
discovery.rs1use crate::manifest::PluginManifest;
2use std::collections::HashMap;
3use std::fs;
4use std::path::{Path, PathBuf};
5
6#[derive(Debug)]
8pub struct DiscoveredPlugin {
9 pub manifest: PluginManifest,
10 pub base_dir: PathBuf,
11 pub category: String,
12}
13
14pub fn discover_plugins(plugin_dir: &Path) -> Vec<DiscoveredPlugin> {
22 let mut plugins = Vec::new();
23 scan_plugin_dir(plugin_dir, &mut plugins);
24 plugins
25}
26
27fn scan_plugin_dir(dir: &Path, plugins: &mut Vec<DiscoveredPlugin>) {
28 let entries = match fs::read_dir(dir) {
29 Ok(e) => e,
30 Err(_) => return,
31 };
32
33 for category_entry in entries.flatten() {
34 let category_path = category_entry.path();
35 if !category_path.is_dir() {
36 continue;
37 }
38 let category = category_entry
39 .file_name()
40 .to_string_lossy()
41 .to_string();
42
43 let plugin_entries = match fs::read_dir(&category_path) {
44 Ok(e) => e,
45 Err(_) => continue,
46 };
47
48 for plugin_entry in plugin_entries.flatten() {
49 let plugin_path = plugin_entry.path();
50
51 let manifest_path = if plugin_path.join("lowfat.toml").is_file() {
53 plugin_path.join("lowfat.toml")
54 } else if plugin_path.join("init.toml").is_file() {
55 plugin_path.join("init.toml")
56 } else {
57 continue;
58 };
59
60 let content = match fs::read_to_string(&manifest_path) {
61 Ok(c) => c,
62 Err(_) => continue,
63 };
64
65 let manifest = match PluginManifest::parse(&content) {
66 Ok(m) => m,
67 Err(e) => {
68 eprintln!(
69 "[lowfat] warning: invalid manifest at {}: {}",
70 manifest_path.display(),
71 e
72 );
73 continue;
74 }
75 };
76
77 plugins.push(DiscoveredPlugin {
78 manifest,
79 base_dir: plugin_path,
80 category,
81 });
82 break;
83 }
84 }
85}
86
87pub fn resolve_plugins(plugins: &[DiscoveredPlugin]) -> HashMap<String, usize> {
90 let mut map = HashMap::new();
91 for (idx, plugin) in plugins.iter().enumerate() {
92 for cmd in &plugin.manifest.plugin.commands {
93 map.insert(cmd.clone(), idx);
94 }
95 }
96 map
97}