diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-10-23 00:14:43 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-10-23 00:21:40 +0200 |
| commit | ecf0ff4d054f11c79ec0ddbbdf45f3dfcf9fc8d7 (patch) | |
| tree | efdc76915e5c7f43629aa3aa5d5aa3998d7f5367 /src/func.rs | |
| parent | cff325b520727ac0eec46a3757831afaa0916cc1 (diff) | |
Introduce a set of macros for writing functions more concisely 🎁
Diffstat (limited to 'src/func.rs')
| -rw-r--r-- | src/func.rs | 172 |
1 files changed, 0 insertions, 172 deletions
diff --git a/src/func.rs b/src/func.rs deleted file mode 100644 index 05bbe83d..00000000 --- a/src/func.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! Dynamic typesetting functions. - -use std::any::Any; -use std::collections::HashMap; -use std::fmt::{self, Debug, Formatter}; - -use crate::layout::{Layout, LayoutContext, Alignment, LayoutResult, MultiLayout}; -use crate::parsing::{ParseContext, ParseResult}; -use crate::style::TextStyle; -use crate::syntax::{FuncHeader, SyntaxTree}; - -/// Typesetting function types. -/// -/// These types have to be able to parse tokens into themselves and store the -/// relevant information from the parsing to do their role in typesetting later. -/// -/// The trait `FunctionBounds` is automatically implemented for types which can -/// be used as functions, that is they fulfill the bounds `Debug + PartialEq + -/// 'static`. -pub trait Function: FunctionBounds { - /// Parse the header and body into this function given a context. - fn parse(header: &FuncHeader, body: Option<&str>, ctx: ParseContext) -> ParseResult<Self> - where Self: Sized; - - /// Layout this function given a context. - /// - /// Returns optionally the resulting layout and a new context if changes to - /// the context should be made. - fn layout(&self, ctx: LayoutContext) -> LayoutResult<CommandList>; -} - -impl PartialEq for dyn Function { - fn eq(&self, other: &dyn Function) -> bool { - self.help_eq(other) - } -} - -/// A helper trait that describes requirements for types that can implement -/// [`Function`]. -/// -/// Automatically implemented for all types which fulfill to the bounds `Debug + -/// PartialEq + 'static`. There should be no need to implement this manually. -pub trait FunctionBounds: Debug { - /// Cast self into `Any`. - fn help_cast_as_any(&self) -> &dyn Any; - - /// Compare self with another function. - fn help_eq(&self, other: &dyn Function) -> bool; -} - -impl<T> FunctionBounds for T -where T: Debug + PartialEq + 'static -{ - fn help_cast_as_any(&self) -> &dyn Any { - self - } - - fn help_eq(&self, other: &dyn Function) -> bool { - if let Some(other) = other.help_cast_as_any().downcast_ref::<Self>() { - self == other - } else { - false - } - } -} - -/// A sequence of commands requested for execution by a function. -#[derive(Debug)] -pub struct CommandList<'a> { - pub commands: Vec<Command<'a>>, -} - -impl<'a> CommandList<'a> { - /// Create an empty command list. - pub fn new() -> CommandList<'a> { - CommandList { commands: vec![] } - } - - /// Create a command list with commands from a vector. - pub fn from_vec(commands: Vec<Command<'a>>) -> CommandList<'a> { - CommandList { commands } - } - - /// Add a command to the sequence. - pub fn add(&mut self, command: Command<'a>) { - self.commands.push(command); - } - - /// Whether there are any commands in this sequence. - pub fn is_empty(&self) -> bool { - self.commands.is_empty() - } -} - -impl<'a> IntoIterator for CommandList<'a> { - type Item = Command<'a>; - type IntoIter = std::vec::IntoIter<Command<'a>>; - - fn into_iter(self) -> Self::IntoIter { - self.commands.into_iter() - } -} - -impl<'a> IntoIterator for &'a CommandList<'a> { - type Item = &'a Command<'a>; - type IntoIter = std::slice::Iter<'a, Command<'a>>; - - fn into_iter(self) -> Self::IntoIter { - self.commands.iter() - } -} - -/// Commands requested for execution by functions. -#[derive(Debug)] -pub enum Command<'a> { - Layout(&'a SyntaxTree), - Add(Layout), - AddMany(MultiLayout), - AddFlex(Layout), - SetAlignment(Alignment), - SetStyle(TextStyle), - FinishLayout, - FinishFlexRun, -} - -macro_rules! commands { - ($($x:expr),*$(,)*) => ({ - $crate::func::CommandList::from_vec(vec![$($x,)*]) - }); -} - -/// A map from identifiers to functions. -pub struct Scope { - parsers: HashMap<String, Box<ParseFunc>>, -} - -/// A function which parses a function invocation into a function type. -type ParseFunc = dyn Fn(&FuncHeader, Option<&str>, ParseContext) -> ParseResult<Box<dyn Function>>; - -impl Scope { - /// Create a new empty scope. - pub fn new() -> Scope { - Scope { - parsers: HashMap::new(), - } - } - - /// Create a new scope with the standard functions contained. - pub fn with_std() -> Scope { - crate::library::std() - } - - /// Add a function type to the scope giving it a name. - pub fn add<F: Function + 'static>(&mut self, name: &str) { - self.parsers.insert( - name.to_owned(), - Box::new(|h, b, c| F::parse(h, b, c).map(|func| Box::new(func) as Box<dyn Function>)), - ); - } - - /// Return the parser with the given name if there is one. - pub(crate) fn get_parser(&self, name: &str) -> Option<&ParseFunc> { - self.parsers.get(name).map(|x| &**x) - } -} - -impl Debug for Scope { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "Scope ")?; - write!(f, "{:?}", self.parsers.keys()) - } -} |
