diff --git a/src/bin/main.rs b/src/bin/main.rs index 11f308803..92a83dff1 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,9 +1,10 @@ +use std::error::Error; use std::fs::{File, read_to_string}; use std::io::BufWriter; use std::path::{Path, PathBuf}; use futures_executor::block_on; -use typstc::{Typesetter, DynErrorProvider}; +use typstc::{Typesetter, DebugErrorProvider}; use typstc::toddle::query::fs::EagerFsProvider; use typstc::export::pdf; @@ -15,7 +16,7 @@ fn main() { } } -fn run() -> Result<(), Box> { +fn run() -> Result<(), Box> { let args: Vec = std::env::args().collect(); if args.len() < 2 || args.len() > 3 { println!("usage: {} source [destination]", @@ -38,7 +39,7 @@ fn run() -> Result<(), Box> { .map_err(|_| "failed to read from source file")?; let (fs, entries) = EagerFsProvider::from_index("../fonts", "index.json")?; - let provider = DynErrorProvider::new(fs); + let provider = DebugErrorProvider::new(fs); let typesetter = Typesetter::new((Box::new(provider), entries)); let layouts = block_on(typesetter.typeset(&src)); diff --git a/src/error.rs b/src/error.rs index 1eb48debb..3a095eef3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -35,3 +35,38 @@ impl Error { Error { message: message.into(), severity } } } + +/// Construct an error with formatted message and optionally severity and / or +/// span. +/// +/// # Examples +/// ``` +/// # use typstc::err; +/// # use typstc::syntax::span::Span; +/// # let span = Span::ZERO; +/// # let value = 0; +/// +/// // With span and default severity `Error`. +/// err!(span; "the wrong {}", value); +/// +/// // With no span and severity `Warning`. +/// err!(@Warning: span; "non-fatal!"); +/// +/// // Without span and default severity. +/// err!("no spans here ..."); +/// ``` +#[macro_export] +macro_rules! err { + (@$severity:ident: $span:expr; $($args:tt)*) => { + $crate::syntax::span::Spanned { v: err!(@$severity: $($args)*), span: $span } + }; + + (@$severity:ident: $($args:tt)*) => { + $crate::error::Error { + message: format!($($args)*), + severity: $crate::error::Severity::$severity, + } + }; + + ($($tts:tt)*) => { err!(@Error: $($tts)*) }; +} diff --git a/src/func.rs b/src/func.rs index 63d7e8efe..590d9ed32 100644 --- a/src/func.rs +++ b/src/func.rs @@ -198,38 +198,3 @@ macro_rules! body { } }; } - -/// Construct an error with formatted message and optionally severity and / or -/// span. -/// -/// # Examples -/// ``` -/// # use typstc::err; -/// # use typstc::syntax::span::Span; -/// # let span = Span::ZERO; -/// # let value = 0; -/// -/// // With span and default severity `Error`. -/// err!(span; "the wrong {}", value); -/// -/// // With no span and severity `Warning`. -/// err!(@Warning: span; "non-fatal!"); -/// -/// // Without span and default severity. -/// err!("no spans here ..."); -/// ``` -#[macro_export] -macro_rules! err { - (@$severity:ident: $span:expr; $($args:tt)*) => { - $crate::syntax::span::Spanned { v: err!(@Error: $($args)*), span: $span } - }; - - (@$severity:ident: $($args:tt)*) => { - $crate::error::Error { - message: format!($($args)*), - severity: $crate::error::Severity::$severity, - } - }; - - ($($tts:tt)*) => { err!(@Error: $($tts)*) }; -} diff --git a/src/lib.rs b/src/lib.rs index afb327666..2d6fa0216 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ pub use toddle; use std::cell::RefCell; -use std::error::Error; +use std::fmt::Debug; use async_trait::async_trait; use smallvec::smallvec; @@ -40,6 +40,7 @@ macro_rules! pub_use_mod { }; } +#[macro_use] pub mod error; pub mod export; #[macro_use] @@ -71,7 +72,7 @@ pub struct Typesetter { pub type GlobalFontLoader = SharedFontLoader; /// The provider type of font loaders used in the [`Typesetter`]. -pub type GlobalProvider = Box>>; +pub type GlobalProvider = Box>>; impl Typesetter { /// Create a new typesetter. @@ -135,29 +136,30 @@ impl Typesetter { } } -/// Wraps a font provider and transforms its errors into boxed trait objects. -/// This enables font providers that do not return boxed errors to be used with -/// the typesetter. +/// Wraps a font provider and transforms its errors into boxed [`Debug`] trait +/// objects. This enables font providers that do not return these boxed errors +/// to be used with the typesetter. #[derive(Debug)] -pub struct DynErrorProvider

{ +pub struct DebugErrorProvider

{ provider: P, } -impl

DynErrorProvider

-where P: FontProvider, P::Error: Error + 'static { - /// Create a new dynamic error provider from any provider. - pub fn new(provider: P) -> DynErrorProvider

{ - DynErrorProvider { provider } +impl

DebugErrorProvider

+where P: FontProvider, P::Error: Debug + 'static { + /// Create a new debug error provider from any provider. + pub fn new(provider: P) -> DebugErrorProvider

{ + DebugErrorProvider { provider } } } #[async_trait(?Send)] -impl

FontProvider for DynErrorProvider

-where P: FontProvider, P::Error: Error + 'static { +impl

FontProvider for DebugErrorProvider

+where P: FontProvider, P::Error: Debug + 'static { type Data = P::Data; - type Error = Box; + type Error = Box; async fn load(&self, index: usize, variant: usize) -> Result, Self::Error> { - Ok(self.provider.load(index, variant).await?) + self.provider.load(index, variant).await + .map_err(|d| Box::new(d) as Box) } } diff --git a/src/library/font.rs b/src/library/font.rs index be4d263ff..422a68f97 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -15,7 +15,7 @@ function! { FontFamilyFunc { body: body!(opt: body, ctx, errors, decos), list: header.args.pos.get_all::(errors) - .map(Into::into) + .map(|s| s.0.to_lowercase()) .collect(), } } diff --git a/src/syntax/func/keys.rs b/src/syntax/func/keys.rs index cb12ee1b5..b8f142eed 100644 --- a/src/syntax/func/keys.rs +++ b/src/syntax/func/keys.rs @@ -105,7 +105,7 @@ key!(AxisKey, /// A key which is equivalent to a [`AxisKey`] but uses typical extent keywords /// instead of axis keywords, e.g. `width` instead of `horizontal`. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct ExtentKey(AxisKey); +pub struct ExtentKey(pub AxisKey); key!(ExtentKey, "width" | "w" => ExtentKey(Specific(Horizontal)), diff --git a/src/syntax/func/values.rs b/src/syntax/func/values.rs index 18d451e3f..d2b54a0b7 100644 --- a/src/syntax/func/values.rs +++ b/src/syntax/func/values.rs @@ -87,7 +87,7 @@ value!(ScaleSize, "number or size", /// A value type that matches [`Expr::Ident`] and [`Expr::Str`] and implements /// `Into`. -pub struct StringLike(String); +pub struct StringLike(pub String); value!(StringLike, "identifier or string", Expr::Ident(Ident(s)) => StringLike(s), @@ -117,7 +117,7 @@ impl From for String { /// [func: size=default] => None /// [func: size=2cm] => Some(Size::cm(2.0)) /// ``` -pub struct Defaultable(Option); +pub struct Defaultable(pub Option); impl Value for Defaultable { fn parse(expr: Spanned) -> Result { diff --git a/tests/src/typeset.rs b/tests/src/typeset.rs index 6a5cdb9e5..61889e956 100644 --- a/tests/src/typeset.rs +++ b/tests/src/typeset.rs @@ -8,7 +8,7 @@ use std::process::Command; use futures_executor::block_on; -use typstc::{Typesetter, DynErrorProvider}; +use typstc::{Typesetter, DebugErrorProvider}; use typstc::layout::{MultiLayout, Serialize}; use typstc::size::{Size, Size2D, ValueBox}; use typstc::style::{PageStyle, PaperClass}; @@ -65,8 +65,8 @@ fn test(name: &str, src: &str) -> DynResult<()> { println!("Testing: {}.", name); let (fs, entries) = EagerFsProvider::from_index("../fonts", "index.json")?; - let paths = fs.paths(); - let provider = DynErrorProvider::new(fs); + let files = fs.files().to_vec(); + let provider = DebugErrorProvider::new(fs); let mut typesetter = Typesetter::new((Box::new(provider), entries)); typesetter.set_page_style(PageStyle { @@ -84,14 +84,12 @@ fn test(name: &str, src: &str) -> DynResult<()> { // Compute the font's paths. let mut fonts = HashMap::new(); - let loader = typesetter.loader().borrow(); for layout in &layouts { for index in layout.find_used_fonts() { fonts.entry(index) - .or_insert_with(|| &paths[index.id][index.variant]); + .or_insert_with(|| &files[index.id][index.variant]); } } - drop(loader); // Write the serialized layout file. let path = format!("tests/cache/{}.serialized", name);