diff --git a/grimoire/src/spell/factory.rs b/grimoire/src/spell/factory.rs index 84c128132ed1de1484f986dfe03e587be1d1781d..53dffa866ba7e3aab27d9d3a6baa6c52e6afec5e 100644 --- a/grimoire/src/spell/factory.rs +++ b/grimoire/src/spell/factory.rs @@ -8,12 +8,23 @@ use std::collections::HashMap; pub type SpellBuilderFunction = fn(SpellArguments) -> Result<Box<dyn Spell>, Error>; /// The spell factory, you have to register the spell before trying to create them. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct SpellFactory { /// The dispatch map, to get a builder by an associated spell name. dispatch: HashMap<&'static str, SpellBuilderFunction>, } +impl Default for SpellFactory { + fn default() -> Self { + use crate::spell::std as spell; + let mut this = Self { dispatch: Default::default() }; + + this.register::<spell::Log>().expect("error in std spells"); + + this + } +} + impl SpellFactory { /// Get the list of all registered spells. pub fn get_registered_spells(&self) -> impl Iterator<Item = &'static str> { diff --git a/grimoire/src/spell/mod.rs b/grimoire/src/spell/mod.rs index 35fd600f5db86c16027dfce7e58d48d9afcd9abd..aa9e2fa067f3d84de85bd54191554cbb6161edd5 100644 --- a/grimoire/src/spell/mod.rs +++ b/grimoire/src/spell/mod.rs @@ -1,9 +1,16 @@ //! The definition of Spells in the Grimoire engine. -mod factory; mod arguments; +mod factory; mod traits; -pub use factory::*; +/// Standard spells. +pub mod std { + mod log; + + pub use log::Log; +} + pub use arguments::*; +pub use factory::*; pub use traits::*; diff --git a/grimoire/src/spell/std/log.rs b/grimoire/src/spell/std/log.rs new file mode 100644 index 0000000000000000000000000000000000000000..5c7ba6f16334b67d41d7cb2209bd69139ecdefe0 --- /dev/null +++ b/grimoire/src/spell/std/log.rs @@ -0,0 +1,57 @@ +use crate::prelude::*; + +#[derive(Debug)] +pub struct Log { + level: String, + messages: Vec<String>, +} + +impl Spell for Log { + fn cast(&self, state: GrimoireState) -> Result<GrimoireState, GrimoireError> { + let (heading, complementary) = match self.messages.split_first() { + Some((heading, complementary)) => (heading, complementary), + None => return Ok(state), + }; + + let logger = |ident: bool, str: &str| { + let ident = ident.then_some("\t").unwrap_or_default(); + match self.level.as_str() { + "error" => log::error!(target: "grimoire", "{ident}{str}"), + _ => log::info!(target: "grimoire", "{ident}{str}"), + } + }; + + logger(false, heading); + complementary + .iter() + .for_each(|complementary| logger(true, complementary)); + + Ok(state) + } +} + +impl TryFrom<SpellArguments> for Log { + type Error = GrimoireError; + + fn try_from(mut args: SpellArguments) -> Result<Self, Self::Error> { + let level = args + .remove_as("level", GrimoireType::Identifier)? + .to_string(); + args.has_named() + .then_some(()) + .ok_or(GrimoireError::Unexpected("too much named arguments"))?; + + let messages = args + .into_iter() + .filter_map(|(key, msg)| key.is_none().then(|| msg.to_string())) + .collect(); + + Ok(Self { level, messages }) + } +} + +impl BuildableSpell for Log { + fn name() -> &'static str { + "log" + } +}