summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-25 11:16:03 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-25 11:16:03 +0200
commit3309ff9fe5ea36134e8ddf11ac2c84613b569856 (patch)
treeb3eb48d444a5dee7273a76c548a64be96d76f0b9 /src
parent362a7f2a8ac76f944efa05eabcab0960817777c5 (diff)
Slim down context
Diffstat (limited to 'src')
-rw-r--r--src/font.rs52
-rw-r--r--src/image.rs20
-rw-r--r--src/lib.rs105
-rw-r--r--src/library/utility/mod.rs2
-rw-r--r--src/loading/fs.rs7
-rw-r--r--src/loading/mem.rs7
-rw-r--r--src/main.rs19
-rw-r--r--src/model/content.rs2
-rw-r--r--src/source.rs18
9 files changed, 114 insertions, 118 deletions
diff --git a/src/font.rs b/src/font.rs
index 9280ff8d..34ce6389 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -73,6 +73,32 @@ impl FontStore {
}
}
+ /// An ordered iterator over all font families this loader knows and details
+ /// about the faces that are part of them.
+ pub fn families(
+ &self,
+ ) -> impl Iterator<Item = (&str, impl Iterator<Item = &FaceInfo>)> + '_ {
+ // Since the keys are lowercased, we instead use the family field of the
+ // first face's info.
+ let faces = self.loader.faces();
+ self.families.values().map(|ids| {
+ let family = faces[ids[0].0 as usize].family.as_str();
+ let infos = ids.iter().map(|&id| &faces[id.0 as usize]);
+ (family, infos)
+ })
+ }
+
+ /// Get a reference to a loaded face.
+ ///
+ /// This panics if the face with this `id` was not loaded. This function
+ /// should only be called with ids returned by this store's
+ /// [`select()`](Self::select) and
+ /// [`select_fallback()`](Self::select_fallback) methods.
+ #[track_caller]
+ pub fn get(&self, id: FaceId) -> &Face {
+ self.faces[id.0 as usize].as_ref().expect("font face was not loaded")
+ }
+
/// Try to find and load a font face from the given `family` that matches
/// the given `variant` as closely as possible.
pub fn select(&mut self, family: &str, variant: FontVariant) -> Option<FaceId> {
@@ -200,32 +226,6 @@ impl FontStore {
Some(id)
}
-
- /// Get a reference to a loaded face.
- ///
- /// This panics if the face with this `id` was not loaded. This function
- /// should only be called with ids returned by this store's
- /// [`select()`](Self::select) and
- /// [`select_fallback()`](Self::select_fallback) methods.
- #[track_caller]
- pub fn get(&self, id: FaceId) -> &Face {
- self.faces[id.0 as usize].as_ref().expect("font face was not loaded")
- }
-
- /// An ordered iterator over all font families this loader knows and details
- /// about the faces that are part of them.
- pub fn families(
- &self,
- ) -> impl Iterator<Item = (&str, impl Iterator<Item = &FaceInfo>)> + '_ {
- // Since the keys are lowercased, we instead use the family field of the
- // first face's info.
- let faces = self.loader.faces();
- self.families.values().map(|ids| {
- let family = faces[ids[0].0 as usize].family.as_str();
- let infos = ids.iter().map(|&id| &faces[id.0 as usize]);
- (family, infos)
- })
- }
}
/// How many words the two strings share in their prefix.
diff --git a/src/image.rs b/src/image.rs
index 87c093d3..1392ecf1 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -48,6 +48,16 @@ impl ImageStore {
}
}
+ /// Get a reference to a loaded image.
+ ///
+ /// This panics if no image with this `id` was loaded. This function should
+ /// only be called with ids returned by this store's [`load()`](Self::load)
+ /// method.
+ #[track_caller]
+ pub fn get(&self, id: ImageId) -> &Image {
+ &self.images[id.0 as usize]
+ }
+
/// Load and decode an image file from a path relative to the compilation
/// environment's root.
pub fn load(&mut self, path: &Path) -> io::Result<ImageId> {
@@ -64,16 +74,6 @@ impl ImageStore {
}
})
}
-
- /// Get a reference to a loaded image.
- ///
- /// This panics if no image with this `id` was loaded. This function should
- /// only be called with ids returned by this store's [`load()`](Self::load)
- /// method.
- #[track_caller]
- pub fn get(&self, id: ImageId) -> &Image {
- &self.images[id.0 as usize]
- }
}
/// A loaded image.
diff --git a/src/lib.rs b/src/lib.rs
index 5173b022..41487f87 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -66,22 +66,16 @@ use crate::model::StyleMap;
use crate::source::{SourceId, SourceStore};
use crate::util::PathExt;
-/// The core context which holds the loader, stores, and configuration.
+/// The core context which holds the configuration and stores.
pub struct Context {
- /// The loader the context was created with.
- pub loader: Arc<dyn Loader>,
/// Stores loaded source files.
pub sources: SourceStore,
/// Stores parsed font faces.
pub fonts: FontStore,
/// Stores decoded images.
pub images: ImageStore,
- /// The compilation root.
- root: PathBuf,
- /// The standard library scope.
- std: Arc<Scope>,
- /// The default styles.
- styles: Arc<StyleMap>,
+ /// The context's configuration.
+ pub config: Config,
/// Cached modules.
modules: HashMap<SourceId, Module>,
/// The stack of imported files that led to evaluation of the current file.
@@ -93,24 +87,18 @@ pub struct Context {
}
impl Context {
- /// Create a new context with the default settings.
- pub fn new(loader: Arc<dyn Loader>) -> Self {
- Self::builder().build(loader)
- }
-
- /// Create a new context with advanced settings.
- pub fn builder() -> ContextBuilder {
- ContextBuilder::default()
- }
-
- /// A read-only reference to the standard library scope.
- pub fn std(&self) -> &Scope {
- &self.std
- }
-
- /// A read-only reference to the styles.
- pub fn styles(&self) -> &StyleMap {
- &self.styles
+ /// Create a new context.
+ pub fn new(loader: Arc<dyn Loader>, config: Config) -> Self {
+ Self {
+ sources: SourceStore::new(Arc::clone(&loader)),
+ fonts: FontStore::new(Arc::clone(&loader)),
+ images: ImageStore::new(loader),
+ config,
+ modules: HashMap::new(),
+ route: vec![],
+ deps: vec![],
+ flow: None,
+ }
}
/// Evaluate a source file and return the resulting module.
@@ -144,7 +132,7 @@ impl Context {
self.route.push(id);
// Evaluate the module.
- let std = self.std.clone();
+ let std = self.config.std.clone();
let mut scp = Scopes::new(Some(&std));
let result = ast.eval(self, &mut scp);
@@ -175,10 +163,10 @@ impl Context {
/// Resolve a user-entered path to be relative to the compilation
/// environment's root.
- pub fn locate(&self, path: &str) -> StrResult<PathBuf> {
+ fn locate(&self, path: &str) -> StrResult<PathBuf> {
if let Some(&id) = self.route.last() {
if let Some(path) = path.strip_prefix('/') {
- return Ok(self.root.join(path).normalize());
+ return Ok(self.config.root.join(path).normalize());
}
if let Some(dir) = self.sources.get(id).path().parent() {
@@ -190,51 +178,70 @@ impl Context {
}
}
-/// A builder for a [`Context`].
+/// Compilation configuration.
+pub struct Config {
+ /// The compilation root.
+ pub root: PathBuf,
+ /// The standard library scope.
+ pub std: Arc<Scope>,
+ /// The default styles.
+ pub styles: Arc<StyleMap>,
+}
+
+impl Config {
+ /// Create a new configuration builder.
+ pub fn builder() -> ConfigBuilder {
+ ConfigBuilder::default()
+ }
+}
+
+impl Default for Config {
+ fn default() -> Self {
+ Self::builder().build()
+ }
+}
+
+/// A builder for a [`Config`].
///
-/// This struct is created by [`Context::builder`].
-#[derive(Default)]
-pub struct ContextBuilder {
+/// This struct is created by [`Config::builder`].
+#[derive(Debug, Default, Clone)]
+pub struct ConfigBuilder {
root: PathBuf,
std: Option<Arc<Scope>>,
styles: Option<Arc<StyleMap>>,
}
-impl ContextBuilder {
+impl ConfigBuilder {
/// The compilation root, relative to which absolute paths are.
+ ///
+ /// Default: Empty path.
pub fn root(&mut self, root: impl Into<PathBuf>) -> &mut Self {
self.root = root.into();
self
}
- /// The scope containing definitions that are available everywhere
- /// (the standard library).
+ /// The scope containing definitions that are available everywhere.
+ ///
+ /// Default: Typst's standard library.
pub fn std(&mut self, std: impl Into<Arc<Scope>>) -> &mut Self {
self.std = Some(std.into());
self
}
/// The default properties for page size, font selection and so on.
+ ///
+ /// Default: Empty style map.
pub fn styles(&mut self, styles: impl Into<Arc<StyleMap>>) -> &mut Self {
self.styles = Some(styles.into());
self
}
- /// Finish building the context by providing the `loader` used to load
- /// fonts, images, source files and other resources.
- pub fn build(&self, loader: Arc<dyn Loader>) -> Context {
- Context {
- sources: SourceStore::new(Arc::clone(&loader)),
- fonts: FontStore::new(Arc::clone(&loader)),
- images: ImageStore::new(Arc::clone(&loader)),
- loader,
+ /// Finish building the configuration.
+ pub fn build(&self) -> Config {
+ Config {
root: self.root.clone(),
std: self.std.clone().unwrap_or_else(|| Arc::new(library::new())),
styles: self.styles.clone().unwrap_or_default(),
- modules: HashMap::new(),
- route: vec![],
- deps: vec![],
- flow: None,
}
}
}
diff --git a/src/library/utility/mod.rs b/src/library/utility/mod.rs
index 355315e4..c4e847c3 100644
--- a/src/library/utility/mod.rs
+++ b/src/library/utility/mod.rs
@@ -42,7 +42,7 @@ pub fn eval(ctx: &mut Context, args: &mut Args) -> TypResult<Value> {
let prev_route = mem::take(&mut ctx.route);
// Evaluate the source.
- let std = ctx.std.clone();
+ let std = ctx.config.std.clone();
let mut scp = Scopes::new(Some(&std));
let result = ast.eval(ctx, &mut scp);
diff --git a/src/loading/fs.rs b/src/loading/fs.rs
index 3398ebd3..23b67e34 100644
--- a/src/loading/fs.rs
+++ b/src/loading/fs.rs
@@ -1,7 +1,6 @@
use std::fs::{self, File};
use std::io;
use std::path::Path;
-use std::sync::Arc;
use memmap2::Mmap;
use same_file::Handle;
@@ -35,12 +34,6 @@ impl FsLoader {
self
}
- /// Builder-style method to wrap the loader in an [`Arc`] to make it usable
- /// with the [`Context`](crate::Context).
- pub fn wrap(self) -> Arc<Self> {
- Arc::new(self)
- }
-
/// Search for fonts in the operating system's font directories.
pub fn search_system(&mut self) {
self.search_system_impl();
diff --git a/src/loading/mem.rs b/src/loading/mem.rs
index d4c0e7e4..662de100 100644
--- a/src/loading/mem.rs
+++ b/src/loading/mem.rs
@@ -2,7 +2,6 @@ use std::borrow::Cow;
use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
-use std::sync::Arc;
use super::{FileHash, Loader};
use crate::font::FaceInfo;
@@ -31,12 +30,6 @@ impl MemLoader {
self
}
- /// Builder-style method to wrap the loader in an [`Arc`] to make it usable
- /// with the [`Context`](crate::Context).
- pub fn wrap(self) -> Arc<Self> {
- Arc::new(self)
- }
-
/// Insert a path-file mapping. If the data forms a font, then that font
/// will be available for layouting.
///
diff --git a/src/main.rs b/src/main.rs
index c017e735..2865c67e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,9 +2,10 @@ use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;
+use std::sync::Arc;
use codespan_reporting::diagnostic::{Diagnostic, Label};
-use codespan_reporting::term::{self, termcolor, Config, Styles};
+use codespan_reporting::term::{self, termcolor};
use pico_args::Arguments;
use same_file::is_same_file;
use termcolor::{ColorChoice, StandardStream, WriteColor};
@@ -17,7 +18,7 @@ use typst::loading::FsLoader;
use typst::parse::TokenMode;
use typst::source::SourceStore;
use typst::syntax;
-use typst::Context;
+use typst::{Config, Context};
/// What to do.
enum Command {
@@ -172,7 +173,7 @@ fn print_help(help: &'static str) {
/// Print an application-level error (independent from a source file).
fn print_error(msg: &str) -> io::Result<()> {
let mut w = StandardStream::stderr(ColorChoice::Always);
- let styles = Styles::default();
+ let styles = term::Styles::default();
w.set_color(&styles.header_error)?;
write!(w, "error")?;
@@ -192,11 +193,11 @@ fn dispatch(command: Command) -> StrResult<()> {
/// Execute a typesetting command.
fn typeset(command: TypesetCommand) -> StrResult<()> {
- let mut builder = Context::builder();
+ let mut config = Config::builder();
if let Some(root) = &command.root {
- builder.root(root);
+ config.root(root);
} else if let Some(dir) = command.input.parent() {
- builder.root(dir);
+ config.root(dir);
}
// Create a loader for fonts and files.
@@ -204,7 +205,7 @@ fn typeset(command: TypesetCommand) -> StrResult<()> {
// Create the context which holds loaded source files, fonts, images and
// cached artifacts.
- let mut ctx = builder.build(loader.wrap());
+ let mut ctx = Context::new(Arc::new(loader), config.build());
// Load the source file.
let id = ctx
@@ -236,7 +237,7 @@ fn print_diagnostics(
errors: Vec<Error>,
) -> Result<(), codespan_reporting::files::Error> {
let mut w = StandardStream::stderr(ColorChoice::Always);
- let config = Config { tab_width: 2, ..Default::default() };
+ let config = term::Config { tab_width: 2, ..Default::default() };
for error in errors {
// The main diagnostic.
@@ -274,7 +275,7 @@ fn highlight(command: HighlightCommand) -> StrResult<()> {
/// Execute a font listing command.
fn fonts(command: FontsCommand) -> StrResult<()> {
let loader = FsLoader::new().with_system();
- let fonts = FontStore::new(loader.wrap());
+ let fonts = FontStore::new(Arc::new(loader));
for (name, infos) in fonts.families() {
println!("{name}");
diff --git a/src/model/content.rs b/src/model/content.rs
index 8b76c795..64579747 100644
--- a/src/model/content.rs
+++ b/src/model/content.rs
@@ -210,7 +210,7 @@ impl Content {
/// Layout this content into a collection of pages.
pub fn layout(&self, ctx: &mut Context) -> TypResult<Vec<Arc<Frame>>> {
- let copy = ctx.styles.clone();
+ let copy = ctx.config.styles.clone();
let styles = StyleChain::with_root(&copy);
let scratch = Scratch::default();
diff --git a/src/source.rs b/src/source.rs
index 7973a2ee..cd5a453a 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -59,6 +59,16 @@ impl SourceStore {
}
}
+ /// Get a reference to a loaded source file.
+ ///
+ /// This panics if no source file with this `id` exists. This function
+ /// should only be called with ids returned by this store's
+ /// [`load()`](Self::load) and [`provide()`](Self::provide) methods.
+ #[track_caller]
+ pub fn get(&self, id: SourceId) -> &SourceFile {
+ &self.sources[id.0 as usize]
+ }
+
/// Load a source file from a path relative to the compilation environment's
/// root.
///
@@ -109,14 +119,6 @@ impl SourceStore {
id
}
- /// Get a reference to a loaded source file.
- ///
- /// This panics if no source file with this `id` exists.
- #[track_caller]
- pub fn get(&self, id: SourceId) -> &SourceFile {
- &self.sources[id.0 as usize]
- }
-
/// Fully [replace](SourceFile::replace) the source text of a file.
///
/// This panics if no source file with this `id` exists.