diff --git a/src/config.rs b/src/config.rs index c78286a..3c79985 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,15 +15,16 @@ use crate::{scripting::create_lua, utils::Describe}; pub struct SiloConfig { /// Diff tool used to display file differences pub diff_tool: String, - /// Context values for handlebars that are available globally under the `ctx` variable - pub template_context: HashMap, + /// Additional config options + #[serde(flatten)] + pub userdata: HashMap, } impl Default for SiloConfig { fn default() -> Self { Self { diff_tool: detect_difftool(), - template_context: HashMap::new(), + userdata: HashMap::new(), } } } @@ -50,7 +51,7 @@ pub fn read_config(repo: &Path) -> Result { let mut lines = vec![ "local silo = require 'silo'".to_owned(), "local utils = require 'utils'".to_owned(), - "local config = silo.config".to_owned(), + "local config = silo.default_config".to_owned(), ]; if old_config.exists() { lines.push("".to_owned()); @@ -86,7 +87,7 @@ pub fn read_config(repo: &Path) -> Result { } fn read_lua_config(path: &Path) -> Result { - let lua = create_lua(&())?; + let lua = create_lua(&SiloConfig::default())?; let result = lua .load(path) .eval() diff --git a/src/main.rs b/src/main.rs index 77562dc..0f5eada 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ fn main() -> Result<()> { let repo = SiloRepo::open(&args.repo)?; println!( "{}", - serde_json::to_string_pretty(&templating::context(repo.config.template_context)) + serde_json::to_string_pretty(&templating::context(repo.config.userdata)) .into_diagnostic()? ) } diff --git a/src/repo/contents.rs b/src/repo/contents.rs index 2461b03..aaed1ba 100644 --- a/src/repo/contents.rs +++ b/src/repo/contents.rs @@ -4,14 +4,14 @@ use std::{ rc::Rc, }; -use crate::{scripting::create_lua, templating, utils::Describe}; +use crate::{config::SiloConfig, scripting::create_lua, templating, utils::Describe}; use super::{ApplyContext, ParseContext, ReadMode}; use globset::{Glob, GlobSet, GlobSetBuilder}; use lazy_static::lazy_static; use miette::{Context, IntoDiagnostic, Result}; use mlua::LuaSerdeExt; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; #[derive(Clone, Debug)] pub struct Contents { @@ -56,7 +56,7 @@ impl DirEntry { let metadata = if script_tmpl.exists() { log::debug!("Found script template"); - let metadata = RootDirData::read_lua(&script_tmpl, &ctx.config.template_context)?; + let metadata = RootDirData::read_lua(&script_tmpl, &ctx.config)?; ctx = Rc::new(ParseContext::new( path.clone(), metadata.read_mode(), @@ -78,8 +78,7 @@ impl DirEntry { } else if meta_tmpl.exists() { log::debug!("Found metadata template"); log::warn!("Old template metadata files are deprecated. Please migrate to the `silo.dir.lua` syntax"); - let metadata = - RootDirData::read_template(&meta_tmpl, &ctx.config.template_context)?; + let metadata = RootDirData::read_template(&meta_tmpl, &ctx.config)?; ctx = Rc::new(ParseContext::new( path.clone(), metadata.read_mode(), @@ -132,7 +131,7 @@ impl DirEntry { Ok(()) } DirEntry::Root(_, data, children) => { - let rendered_path = templating::render(&data.path, &ctx.config.template_context)?; + let rendered_path = templating::render(&data.path, &ctx.config)?; let cwd = PathBuf::from(rendered_path); for child in children { @@ -171,7 +170,7 @@ impl FileEntry { let filename = new_path.file_name().unwrap(); let dest = cwd.join(filename); - let render_contents = templating::render(&contents, &ctx.config.template_context)?; + let render_contents = templating::render(&contents, &ctx.config.userdata)?; ctx.fs.write_all(&dest, &render_contents.into_bytes())?; ctx.fs @@ -223,18 +222,18 @@ impl RootDirData { .with_context(|| format!("parsing metadata file {path:?}")) } - fn read_template(path: &Path, ctx: T) -> Result { + fn read_template(path: &Path, cfg: &SiloConfig) -> Result { let contents = fs::read_to_string(path) .into_diagnostic() .with_context(|| format!("reading metadata file {path:?}"))?; - let rendered = templating::render(&contents, ctx)?; + let rendered = templating::render(&contents, cfg)?; toml::from_str(&rendered) .into_diagnostic() .with_context(|| format!("parsing metadata file {path:?}")) } - fn read_lua(path: &Path, ctx: T) -> Result { - let lua = create_lua(&ctx)?; + fn read_lua(path: &Path, cfg: &SiloConfig) -> Result { + let lua = create_lua(&cfg)?; let cfg: Self = lua .from_value(lua.load(path).eval().describe("evaluating script")?) .describe("deserialize lua value")?; diff --git a/src/repo/hooks.rs b/src/repo/hooks.rs index 4c923ed..3a0a474 100644 --- a/src/repo/hooks.rs +++ b/src/repo/hooks.rs @@ -8,7 +8,7 @@ use std::{ use miette::{IntoDiagnostic, Result}; -use crate::{scripting::create_lua, utils::Describe}; +use crate::{config::SiloConfig, scripting::create_lua, utils::Describe}; #[derive(Clone, Debug)] pub struct Hooks { @@ -46,7 +46,7 @@ impl Hooks { } } - pub fn load(path: &Path) -> Result { + pub fn load(config: &SiloConfig, path: &Path) -> Result { log::debug!("Parsing hooks in {path:?}"); let readdir = fs::read_dir(path).into_diagnostic()?; let mut scripts = Vec::new(); @@ -60,7 +60,7 @@ impl Hooks { .is_some_and(|f| f.to_string_lossy().ends_with(".hook.lua")) { log::debug!("Found hook {path:?}"); - scripts.push(Arc::new(HookScript::load(&path)?)) + scripts.push(Arc::new(HookScript::load(config, &path)?)) } } @@ -107,8 +107,8 @@ impl Hooks { } impl HookScript { - pub fn load(path: &Path) -> Result { - let lua = create_lua(&())?; + pub fn load(config: &SiloConfig, path: &Path) -> Result { + let lua = create_lua(&config)?; let module: OwnedTable = lua .load(path) .eval() diff --git a/src/repo/mod.rs b/src/repo/mod.rs index 427a7ba..b6c70ce 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -43,7 +43,7 @@ impl SiloRepo { let hook_path = path.join("hooks"); let hooks = if hook_path.exists() { - Hooks::load(&hook_path)? + Hooks::load(&config, &hook_path)? } else { Hooks::empty() }; diff --git a/src/scripting/mod.rs b/src/scripting/mod.rs index 05e1151..1312d36 100644 --- a/src/scripting/mod.rs +++ b/src/scripting/mod.rs @@ -5,19 +5,19 @@ pub mod utils_module; use miette::Result; use mlua::{Lua, LuaSerdeExt}; -use serde::Serialize; -use crate::utils::Describe; +use crate::{config::SiloConfig, utils::Describe}; -pub fn create_lua(ctx: &T) -> Result { +pub fn create_lua(config: &SiloConfig) -> Result { let lua = Lua::new(); { let globals = lua.globals(); require::register_require(&lua).describe("registering custom require")?; globals .set( - "silo_ctx", - lua.to_value(ctx).describe("serializing context to lua")?, + "__silo_config", + lua.to_value(config) + .describe("serializing context to lua")?, ) .describe("registering silo context")?; } diff --git a/src/scripting/silo_module.rs b/src/scripting/silo_module.rs index c3be412..eb0f501 100644 --- a/src/scripting/silo_module.rs +++ b/src/scripting/silo_module.rs @@ -9,8 +9,9 @@ pub fn silo_module(lua: &Lua) -> Result { exports.set("dirs", lua.to_value(&silo_ctx.dirs)?)?; exports.set("flags", lua.to_value(&silo_ctx.flags)?)?; exports.set("system", lua.to_value(&silo_ctx.system)?)?; - exports.set("usercfg", lua.globals().get::<_, mlua::Value>("silo_ctx")?)?; - exports.set("config", lua.to_value(&SiloConfig::default())?)?; + let config = lua.globals().get::<_, mlua::Value>("__silo_config")?; + exports.set("config", config)?; + exports.set("default_config", lua.to_value(&SiloConfig::default())?)?; Ok(exports) } diff --git a/src/templating/mod.rs b/src/templating/mod.rs index 68eb24d..852b24b 100644 --- a/src/templating/mod.rs +++ b/src/templating/mod.rs @@ -7,7 +7,7 @@ use miette::{Context, IntoDiagnostic, Result}; use serde::Serialize; mod helpers; -pub fn render(template: &str, ctx: T) -> Result { +pub fn render(template: &str, ctx: T) -> Result { engine() .render_template(template, &context(ctx)) .into_diagnostic() @@ -28,11 +28,15 @@ fn engine<'a>() -> Handlebars<'a> { hb } -pub fn context<'a, T: Serialize>(ctx: T) -> WrappedContext<'a, T> { +pub fn context<'a, T: Serialize + Clone>(cfg: T) -> WrappedContext<'a, T> { lazy_static! { static ref CTX: ContextData = ContextData::default(); } - WrappedContext { data: &CTX, ctx } + WrappedContext { + data: &CTX, + ctx: cfg.clone(), + cfg, + } } #[derive(Serialize)] @@ -40,6 +44,7 @@ pub struct WrappedContext<'a, T: Serialize> { #[serde(flatten)] data: &'a ContextData, ctx: T, + cfg: T, } #[derive(Clone, Debug, Serialize, Default)]