summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-07-21 11:25:49 +0200
committerLaurenz <laurmaedje@gmail.com>2021-07-21 11:28:33 +0200
commitb0e5212973ce2efcb1433323d67c06eea1a81785 (patch)
tree3b040a4e23d2d99157050d95b67376b2fb866618 /src
parent9488b1b850152eb564dbfefc898c962bdac73eb4 (diff)
Fs builder methods + tidy up
Diffstat (limited to 'src')
-rw-r--r--src/eval/mod.rs8
-rw-r--r--src/lib.rs9
-rw-r--r--src/loading/fs.rs96
-rw-r--r--src/main.rs12
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(),
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 90fd8774..594b4a59 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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.