1use std::path::{Path, PathBuf};
2
3use crate::sandbox::{LuaError, LuaRuntime};
4
5#[derive(Debug, Clone)]
7pub struct LuaExtension {
8 pub name: String,
9 pub path: PathBuf,
10}
11
12pub fn discover_extensions(
14 user_config_dir: &Path,
15 project_dir: Option<&Path>,
16) -> Vec<LuaExtension> {
17 let mut extensions = Vec::new();
18
19 let mut dirs = vec![user_config_dir.join("lua")];
20 if let Some(project) = project_dir {
21 dirs.push(project.join(".imp").join("lua"));
22 }
23
24 for dir in &dirs {
25 if let Ok(entries) = std::fs::read_dir(dir) {
26 for entry in entries.flatten() {
27 let path = entry.path();
28
29 if path.extension().is_some_and(|e| e == "lua") {
31 let name = path
32 .file_stem()
33 .map(|s| s.to_string_lossy().to_string())
34 .unwrap_or_default();
35 extensions.push(LuaExtension { name, path });
36 continue;
37 }
38
39 if path.is_dir() {
41 let init = path.join("init.lua");
42 if init.exists() {
43 let name = path
44 .file_name()
45 .map(|s| s.to_string_lossy().to_string())
46 .unwrap_or_default();
47 extensions.push(LuaExtension { name, path: init });
48 }
49 }
50 }
51 }
52 }
53
54 extensions
55}
56
57pub fn load_extensions(
59 runtime: &LuaRuntime,
60 extensions: &[LuaExtension],
61) -> Vec<(String, Result<(), LuaError>)> {
62 extensions
63 .iter()
64 .map(|ext| {
65 let result = runtime.exec_file(&ext.path);
66 (ext.name.clone(), result)
67 })
68 .collect()
69}
70
71pub fn reload(
73 user_config_dir: &Path,
74 project_dir: Option<&Path>,
75) -> Result<(LuaRuntime, Vec<LuaExtension>), LuaError> {
76 let extensions = discover_extensions(user_config_dir, project_dir);
77 let runtime = LuaRuntime::new()?;
78 crate::bridge::setup_host_api(&runtime)?;
79 load_extensions(&runtime, &extensions);
80 Ok((runtime, extensions))
81}