diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-07-21 11:25:49 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-07-21 11:28:33 +0200 |
| commit | b0e5212973ce2efcb1433323d67c06eea1a81785 (patch) | |
| tree | 3b040a4e23d2d99157050d95b67376b2fb866618 /src | |
| parent | 9488b1b850152eb564dbfefc898c962bdac73eb4 (diff) | |
Fs builder methods + tidy up
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/mod.rs | 8 | ||||
| -rw-r--r-- | src/lib.rs | 9 | ||||
| -rw-r--r-- | src/loading/fs.rs | 96 | ||||
| -rw-r--r-- | src/main.rs | 12 |
4 files changed, 71 insertions, 54 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 0efaaa90..9ec33b13 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -36,8 +36,8 @@ use crate::syntax::*; use crate::Context; /// Evaluate a parsed source file into a module. -pub fn eval(ctx: &mut Context, location: FileId, ast: Rc<SyntaxTree>) -> Pass<Module> { - let mut ctx = EvalContext::new(ctx, location); +pub fn eval(ctx: &mut Context, file: FileId, ast: Rc<SyntaxTree>) -> Pass<Module> { + let mut ctx = EvalContext::new(ctx, file); let template = ast.eval(&mut ctx); let module = Module { scope: ctx.scopes.top, template }; Pass::new(module, ctx.diags) @@ -70,13 +70,13 @@ pub struct EvalContext<'a> { impl<'a> EvalContext<'a> { /// Create a new evaluation context. - pub fn new(ctx: &'a mut Context, location: FileId) -> Self { + pub fn new(ctx: &'a mut Context, file: FileId) -> Self { Self { loader: ctx.loader.as_ref(), images: &mut ctx.images, scopes: Scopes::new(Some(&ctx.std)), diags: DiagSet::new(), - route: vec![location], + route: vec![file], modules: HashMap::new(), } } @@ -96,8 +96,8 @@ impl Context { /// Typeset a source file into a collection of layouted frames. /// - /// The `file` is the file id of the source file and is used to resolve - /// relative paths (for importing and image loading). + /// The `file` identifies the source file and is used to resolve relative + /// paths (for importing and image loading). /// /// Returns a vector of frames representing individual pages alongside /// diagnostic information (errors and warnings). @@ -125,15 +125,14 @@ pub struct ContextBuilder { } impl ContextBuilder { - /// The scope containing definitions that are available everywhere, + /// The scope containing definitions that are available everywhere /// (the standard library). pub fn std(mut self, std: Scope) -> Self { self.std = Some(std); self } - /// The `state` defining initial properties for page size, font selection - /// and so on. + /// The initial properties for page size, font selection and so on. pub fn state(mut self, state: State) -> Self { self.state = Some(state); self diff --git a/src/loading/fs.rs b/src/loading/fs.rs index 8785499e..407e2d94 100644 --- a/src/loading/fs.rs +++ b/src/loading/fs.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; +use std::rc::Rc; use memmap2::Mmap; use same_file::Handle; @@ -28,8 +29,57 @@ impl FsLoader { Self { faces: vec![], paths: RefCell::default() } } + /// Builder-style variant of `search_system`. + pub fn with_system(mut self) -> Self { + self.search_system(); + self + } + + /// Builder-style variant of `search_path`. + pub fn with_path(mut self, dir: impl AsRef<Path>) -> Self { + self.search_path(dir); + self + } + + /// Builder-style method to wrap the loader in an [`Rc`] to make it usable + /// with the [`Context`](crate::Context). + pub fn wrap(self) -> Rc<Self> { + Rc::new(self) + } + + /// Search for fonts in the operating system's font directories. + pub fn search_system(&mut self) { + self.search_system_impl(); + } + + /// Search for all fonts at a path. + /// + /// If the path is a directory, all contained fonts will be searched for + /// recursively. + pub fn search_path(&mut self, dir: impl AsRef<Path>) { + let walk = WalkDir::new(dir) + .follow_links(true) + .sort_by(|a, b| a.file_name().cmp(b.file_name())) + .into_iter() + .filter_map(|e| e.ok()); + + for entry in walk { + let path = entry.path(); + if let Some(ext) = path.extension().and_then(|s| s.to_str()) { + match ext { + #[rustfmt::skip] + "ttf" | "otf" | "TTF" | "OTF" | + "ttc" | "otc" | "TTC" | "OTC" => { + self.search_file(path).ok(); + } + _ => {} + } + } + } + } + /// Resolve a file id for a path. - pub fn resolve_path(&self, path: &Path) -> io::Result<FileId> { + pub fn resolve(&self, path: &Path) -> io::Result<FileId> { let file = File::open(path)?; let meta = file.metadata()?; if meta.is_file() { @@ -42,9 +92,8 @@ impl FsLoader { } } - /// Search for fonts in the operating system's font directories. #[cfg(all(unix, not(target_os = "macos")))] - pub fn search_system(&mut self) { + fn search_system_impl(&mut self) { self.search_path("/usr/share/fonts"); self.search_path("/usr/local/share/fonts"); @@ -53,9 +102,8 @@ impl FsLoader { } } - /// Search for fonts in the operating system's font directories. #[cfg(target_os = "macos")] - pub fn search_system(&mut self) { + fn search_system_impl(&mut self) { self.search_path("/Library/Fonts"); self.search_path("/Network/Library/Fonts"); self.search_path("/System/Library/Fonts"); @@ -65,9 +113,8 @@ impl FsLoader { } } - /// Search for fonts in the operating system's font directories. #[cfg(windows)] - pub fn search_system(&mut self) { + fn search_system_impl(&mut self) { let windir = std::env::var("WINDIR").unwrap_or_else(|_| "C:\\Windows".to_string()); @@ -82,32 +129,6 @@ impl FsLoader { } } - /// Search for all fonts at a path. - /// - /// If the path is a directory, all contained fonts will be searched for - /// recursively. - pub fn search_path(&mut self, dir: impl AsRef<Path>) { - let walk = WalkDir::new(dir) - .follow_links(true) - .sort_by(|a, b| a.file_name().cmp(b.file_name())) - .into_iter() - .filter_map(|e| e.ok()); - - for entry in walk { - let path = entry.path(); - if let Some(ext) = path.extension().and_then(|s| s.to_str()) { - match ext { - #[rustfmt::skip] - "ttf" | "otf" | "TTF" | "OTF" | - "ttc" | "otc" | "TTC" | "OTC" => { - self.search_file(path).ok(); - } - _ => {} - } - } - } - } - /// Index the font faces in the file at the given path. /// /// The file may form a font collection and contain multiple font faces, @@ -154,7 +175,7 @@ impl FsLoader { stretch: FontStretch::from_number(face.width().to_number()), }; - let file = self.resolve_path(path)?; + let file = self.resolve(path)?; self.faces.push(FaceInfo { file, index, family, variant }); Ok(()) @@ -182,11 +203,8 @@ mod tests { #[test] fn test_index_font_dir() { - let mut loader = FsLoader::new(); - loader.search_path("fonts"); - - let map = loader.paths.borrow(); - let mut paths: Vec<_> = map.values().collect(); + let map = FsLoader::new().with_path("fonts").paths.into_inner(); + let mut paths: Vec<_> = map.into_iter().map(|p| p.1).collect(); paths.sort(); assert_eq!(paths, [ diff --git a/src/main.rs b/src/main.rs index f9da37fa..91edff17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ use std::fs; use std::path::{Path, PathBuf}; -use std::rc::Rc; use anyhow::{anyhow, bail, Context}; use same_file::is_same_file; @@ -30,17 +29,18 @@ fn main() -> anyhow::Result<()> { } // Create a loader for fonts and files. - let mut loader = typst::loading::FsLoader::new(); - loader.search_path("fonts"); - loader.search_system(); + let loader = typst::loading::FsLoader::new() + .with_path("fonts") + .with_system() + .wrap(); // Resolve the file id of the source file and read the file. - let src_id = loader.resolve_path(src_path).context("source file not found")?; + let src_id = loader.resolve(src_path).context("source file not found")?; let src = fs::read_to_string(&src_path) .map_err(|_| anyhow!("failed to read source file"))?; // Typeset. - let mut ctx = typst::Context::new(Rc::new(loader)); + let mut ctx = typst::Context::new(loader); let pass = ctx.typeset(src_id, &src); // Print diagnostics. |
