use mlua::{Lua, Result as LuaResult};
use std::fs;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub enum EditorCommand {
UseBuiltinTheme(String),
SetThemeColor { name: String, value: String },
SetSidebarVisible(bool),
SetSidebarWidth(f32),
}
#[derive(Debug, Clone)]
pub struct StartupScriptLoad {
pub path: PathBuf,
pub source: Option<String>,
pub commands: Vec<EditorCommand>,
pub error: Option<String>,
}
pub fn startup_script_path() -> PathBuf {
crate::config::theme_manager::get_config_dir().join("init.lua")
}
pub fn load_startup_script() -> StartupScriptLoad {
let path = startup_script_path();
let source = match fs::read_to_string(&path) {
Ok(source) => source,
Err(err) => {
return StartupScriptLoad {
path,
source: None,
commands: Vec::new(),
error: Some(err.to_string()),
};
}
};
match eval_script(&source) {
Ok(commands) => StartupScriptLoad {
path,
source: Some(source),
commands,
error: None,
},
Err(err) => StartupScriptLoad {
path,
source: Some(source),
commands: Vec::new(),
error: Some(err),
},
}
}
pub fn eval_script(source: &str) -> Result<Vec<EditorCommand>, String> {
let lua = Lua::new();
let commands = Arc::new(Mutex::new(Vec::<EditorCommand>::new()));
let pinel = lua.create_table().map_err(|e| e.to_string())?;
let theme = lua.create_table().map_err(|e| e.to_string())?;
let ui = lua.create_table().map_err(|e| e.to_string())?;
{
let commands = Arc::clone(&commands);
let f = lua
.create_function(move |_, name: String| -> LuaResult<()> {
commands
.lock()
.unwrap()
.push(EditorCommand::UseBuiltinTheme(name));
Ok(())
})
.map_err(|e| e.to_string())?;
theme.set("use_builtin", f).map_err(|e| e.to_string())?;
}
{
let commands = Arc::clone(&commands);
let f = lua
.create_function(move |_, (name, value): (String, String)| -> LuaResult<()> {
commands
.lock()
.unwrap()
.push(EditorCommand::SetThemeColor { name, value });
Ok(())
})
.map_err(|e| e.to_string())?;
theme.set("set_color", f).map_err(|e| e.to_string())?;
}
{
let commands = Arc::clone(&commands);
let f = lua
.create_function(move |_, visible: bool| -> LuaResult<()> {
commands
.lock()
.unwrap()
.push(EditorCommand::SetSidebarVisible(visible));
Ok(())
})
.map_err(|e| e.to_string())?;
ui.set("show_sidebar", f).map_err(|e| e.to_string())?;
}
{
let commands = Arc::clone(&commands);
let f = lua
.create_function(move |_, width: f32| -> LuaResult<()> {
commands
.lock()
.unwrap()
.push(EditorCommand::SetSidebarWidth(width));
Ok(())
})
.map_err(|e| e.to_string())?;
ui.set("set_sidebar_width", f).map_err(|e| e.to_string())?;
}
pinel.set("theme", theme).map_err(|e| e.to_string())?;
pinel.set("ui", ui).map_err(|e| e.to_string())?;
lua.globals().set("pinel", pinel).map_err(|e| e.to_string())?;
lua.load(source).exec().map_err(|e| e.to_string())?;
let queued_commands = commands.lock().unwrap().clone();
Ok(queued_commands)
}