mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Introduce Library
This commit is contained in:
parent
b2a3d3f235
commit
5ae81971f2
@ -19,9 +19,10 @@ use siphasher::sip128::{Hasher128, SipHasher};
|
|||||||
use termcolor::{ColorChoice, StandardStream, WriteColor};
|
use termcolor::{ColorChoice, StandardStream, WriteColor};
|
||||||
use typst::diag::{FileError, FileResult, SourceError, StrResult};
|
use typst::diag::{FileError, FileResult, SourceError, StrResult};
|
||||||
use typst::font::{Font, FontBook, FontInfo, FontVariant};
|
use typst::font::{Font, FontBook, FontInfo, FontVariant};
|
||||||
|
use typst::model::Library;
|
||||||
use typst::syntax::{Source, SourceId};
|
use typst::syntax::{Source, SourceId};
|
||||||
use typst::util::{Buffer, PathExt};
|
use typst::util::{Buffer, PathExt};
|
||||||
use typst::{Config, World};
|
use typst::World;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
type CodespanResult<T> = Result<T, CodespanError>;
|
type CodespanResult<T> = Result<T, CodespanError>;
|
||||||
@ -178,15 +179,8 @@ fn typeset(command: TypesetCommand) -> StrResult<()> {
|
|||||||
PathBuf::new()
|
PathBuf::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = Config {
|
|
||||||
root,
|
|
||||||
scope: typst_library::scope(),
|
|
||||||
styles: typst_library::styles(),
|
|
||||||
items: typst_library::items(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the world that serves sources, fonts and files.
|
// Create the world that serves sources, fonts and files.
|
||||||
let mut world = SystemWorld::new(config);
|
let mut world = SystemWorld::new(root);
|
||||||
|
|
||||||
// Typeset.
|
// Typeset.
|
||||||
typeset_once(&mut world, &command)?;
|
typeset_once(&mut world, &command)?;
|
||||||
@ -371,7 +365,8 @@ fn fonts(command: FontsCommand) -> StrResult<()> {
|
|||||||
|
|
||||||
/// A world that provides access to the operating system.
|
/// A world that provides access to the operating system.
|
||||||
struct SystemWorld {
|
struct SystemWorld {
|
||||||
config: Prehashed<Config>,
|
root: PathBuf,
|
||||||
|
library: Prehashed<Library>,
|
||||||
book: Prehashed<FontBook>,
|
book: Prehashed<FontBook>,
|
||||||
fonts: Vec<FontSlot>,
|
fonts: Vec<FontSlot>,
|
||||||
hashes: RefCell<HashMap<PathBuf, FileResult<PathHash>>>,
|
hashes: RefCell<HashMap<PathBuf, FileResult<PathHash>>>,
|
||||||
@ -394,12 +389,13 @@ struct PathSlot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SystemWorld {
|
impl SystemWorld {
|
||||||
fn new(config: Config) -> Self {
|
fn new(root: PathBuf) -> Self {
|
||||||
let mut searcher = FontSearcher::new();
|
let mut searcher = FontSearcher::new();
|
||||||
searcher.search_system();
|
searcher.search_system();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config: Prehashed::new(config),
|
root,
|
||||||
|
library: Prehashed::new(typst_library::new()),
|
||||||
book: Prehashed::new(searcher.book),
|
book: Prehashed::new(searcher.book),
|
||||||
fonts: searcher.fonts,
|
fonts: searcher.fonts,
|
||||||
hashes: RefCell::default(),
|
hashes: RefCell::default(),
|
||||||
@ -410,8 +406,12 @@ impl SystemWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl World for SystemWorld {
|
impl World for SystemWorld {
|
||||||
fn config(&self) -> &Prehashed<Config> {
|
fn root(&self) -> &Path {
|
||||||
&self.config
|
&self.root
|
||||||
|
}
|
||||||
|
|
||||||
|
fn library(&self) -> &Prehashed<Library> {
|
||||||
|
&self.library
|
||||||
}
|
}
|
||||||
|
|
||||||
fn book(&self) -> &Prehashed<FontBook> {
|
fn book(&self) -> &Prehashed<FontBook> {
|
||||||
|
@ -10,12 +10,17 @@ pub mod structure;
|
|||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
use typst::geom::{Align, Color, Dir, GenAlign};
|
use typst::geom::{Align, Color, Dir, GenAlign};
|
||||||
use typst::model::{LangItems, Node, NodeId, Scope, StyleMap};
|
use typst::model::{LangItems, Library, Node, NodeId, Scope, StyleMap};
|
||||||
|
|
||||||
use self::layout::LayoutRoot;
|
use self::layout::LayoutRoot;
|
||||||
|
|
||||||
/// Construct the standard library scope.
|
/// Construct the standard library.
|
||||||
pub fn scope() -> Scope {
|
pub fn new() -> Library {
|
||||||
|
Library { scope: scope(), styles: styles(), items: items() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct the standard scope.
|
||||||
|
fn scope() -> Scope {
|
||||||
let mut std = Scope::new();
|
let mut std = Scope::new();
|
||||||
|
|
||||||
// Text.
|
// Text.
|
||||||
@ -147,12 +152,12 @@ pub fn scope() -> Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the standard style map.
|
/// Construct the standard style map.
|
||||||
pub fn styles() -> StyleMap {
|
fn styles() -> StyleMap {
|
||||||
StyleMap::new()
|
StyleMap::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the standard lang item mapping.
|
/// Construct the standard lang item mapping.
|
||||||
pub fn items() -> LangItems {
|
fn items() -> LangItems {
|
||||||
LangItems {
|
LangItems {
|
||||||
layout: |content, world, styles| content.layout_root(world, styles),
|
layout: |content, world, styles| content.layout_root(world, styles),
|
||||||
em: |styles| styles.get(text::TextNode::SIZE),
|
em: |styles| styles.get(text::TextNode::SIZE),
|
||||||
|
33
src/lib.rs
33
src/lib.rs
@ -42,14 +42,14 @@ pub mod frame;
|
|||||||
pub mod image;
|
pub mod image;
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::Path;
|
||||||
|
|
||||||
use comemo::{Prehashed, Track};
|
use comemo::{Prehashed, Track};
|
||||||
|
|
||||||
use crate::diag::{FileResult, SourceResult};
|
use crate::diag::{FileResult, SourceResult};
|
||||||
use crate::font::{Font, FontBook};
|
use crate::font::{Font, FontBook};
|
||||||
use crate::frame::Frame;
|
use crate::frame::Frame;
|
||||||
use crate::model::{LangItems, Route, Scope, StyleChain, StyleMap};
|
use crate::model::{Library, Route, StyleChain};
|
||||||
use crate::syntax::{Source, SourceId};
|
use crate::syntax::{Source, SourceId};
|
||||||
use crate::util::Buffer;
|
use crate::util::Buffer;
|
||||||
|
|
||||||
@ -62,24 +62,24 @@ pub fn typeset(
|
|||||||
world: &(dyn World + 'static),
|
world: &(dyn World + 'static),
|
||||||
source: &Source,
|
source: &Source,
|
||||||
) -> SourceResult<Vec<Frame>> {
|
) -> SourceResult<Vec<Frame>> {
|
||||||
// Set up the language items.
|
|
||||||
let config = world.config();
|
|
||||||
crate::model::set_lang_items(config.items);
|
|
||||||
|
|
||||||
// Evaluate the source file into a module.
|
// Evaluate the source file into a module.
|
||||||
let route = Route::default();
|
let route = Route::default();
|
||||||
let module = model::eval(world.track(), route.track(), source)?;
|
let module = model::eval(world.track(), route.track(), source)?;
|
||||||
|
|
||||||
// Layout the module's contents.
|
// Layout the module's contents.
|
||||||
let styles = StyleChain::with_root(&config.styles);
|
let library = world.library();
|
||||||
item!(layout)(&module.content, world.track(), styles)
|
let styles = StyleChain::with_root(&library.styles);
|
||||||
|
(library.items.layout)(&module.content, world.track(), styles)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The environment in which typesetting occurs.
|
/// The environment in which typesetting occurs.
|
||||||
#[comemo::track]
|
#[comemo::track]
|
||||||
pub trait World {
|
pub trait World {
|
||||||
/// Access the global configuration.
|
/// The compilation root.
|
||||||
fn config(&self) -> &Prehashed<Config>;
|
fn root(&self) -> &Path;
|
||||||
|
|
||||||
|
/// The standard library.
|
||||||
|
fn library(&self) -> &Prehashed<Library>;
|
||||||
|
|
||||||
/// Metadata about all known fonts.
|
/// Metadata about all known fonts.
|
||||||
fn book(&self) -> &Prehashed<FontBook>;
|
fn book(&self) -> &Prehashed<FontBook>;
|
||||||
@ -96,16 +96,3 @@ pub trait World {
|
|||||||
/// Access a source file by id.
|
/// Access a source file by id.
|
||||||
fn source(&self, id: SourceId) -> &Source;
|
fn source(&self, id: SourceId) -> &Source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The global configuration for typesetting.
|
|
||||||
#[derive(Debug, Clone, Hash)]
|
|
||||||
pub struct Config {
|
|
||||||
/// The compilation root, relative to which absolute paths are.
|
|
||||||
pub root: PathBuf,
|
|
||||||
/// The scope containing definitions that are available everywhere.
|
|
||||||
pub scope: Scope,
|
|
||||||
/// The default properties for page size, font selection and so on.
|
|
||||||
pub styles: StyleMap,
|
|
||||||
/// Defines which standard library items fulfill which syntactical roles.
|
|
||||||
pub items: LangItems,
|
|
||||||
}
|
|
||||||
|
@ -35,10 +35,13 @@ pub fn eval(
|
|||||||
panic!("Tried to cyclicly evaluate {}", path);
|
panic!("Tried to cyclicly evaluate {}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hook up the lang items.
|
||||||
|
let library = world.library();
|
||||||
|
super::set_lang_items(library.items.clone());
|
||||||
|
|
||||||
// Evaluate the module.
|
// Evaluate the module.
|
||||||
let route = unsafe { Route::insert(route, id) };
|
let route = unsafe { Route::insert(route, id) };
|
||||||
let std = &world.config().scope;
|
let scopes = Scopes::new(Some(&library.scope));
|
||||||
let scopes = Scopes::new(Some(std));
|
|
||||||
let mut vm = Vm::new(world, route.track(), id, scopes);
|
let mut vm = Vm::new(world, route.track(), id, scopes);
|
||||||
let result = source.ast()?.eval(&mut vm);
|
let result = source.ast()?.eval(&mut vm);
|
||||||
|
|
||||||
|
@ -5,41 +5,26 @@ use std::num::NonZeroUsize;
|
|||||||
use comemo::Tracked;
|
use comemo::Tracked;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
use super::{Content, NodeId, StyleChain};
|
use super::{Content, NodeId, Scope, StyleChain, StyleMap};
|
||||||
use crate::diag::SourceResult;
|
use crate::diag::SourceResult;
|
||||||
use crate::frame::Frame;
|
use crate::frame::Frame;
|
||||||
use crate::geom::{Abs, Dir};
|
use crate::geom::{Abs, Dir};
|
||||||
use crate::util::{hash128, EcoString};
|
use crate::util::{hash128, EcoString};
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// Global storage for lang items.
|
/// A Typst standard library.
|
||||||
#[doc(hidden)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub static LANG_ITEMS: OnceCell<LangItems> = OnceCell::new();
|
pub struct Library {
|
||||||
|
/// The scope containing definitions that are available everywhere.
|
||||||
/// Set the lang items. This is a hack :(
|
pub scope: Scope,
|
||||||
///
|
/// The default properties for page size, font selection and so on.
|
||||||
/// Passing the lang items everywhere they are needed (especially the text node
|
pub styles: StyleMap,
|
||||||
/// related things) is very painful. By storing them globally, in theory, we
|
/// Defines which standard library items fulfill which syntactical roles.
|
||||||
/// break incremental, but only when different sets of lang items are used in
|
pub items: LangItems,
|
||||||
/// the same program. For this reason, if this function is called multiple
|
|
||||||
/// times, the items must be the same.
|
|
||||||
pub(crate) fn set_lang_items(items: LangItems) {
|
|
||||||
if LANG_ITEMS.set(items).is_err() {
|
|
||||||
let first = hash128(LANG_ITEMS.get().unwrap());
|
|
||||||
let second = hash128(&items);
|
|
||||||
assert_eq!(first, second, "set differing lang items");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access a lang item.
|
|
||||||
macro_rules! item {
|
|
||||||
($name:ident) => {
|
|
||||||
$crate::model::LANG_ITEMS.get().unwrap().$name
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Definition of certain standard library items the language is aware of.
|
/// Definition of certain standard library items the language is aware of.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LangItems {
|
pub struct LangItems {
|
||||||
/// The root layout function.
|
/// The root layout function.
|
||||||
pub layout: fn(
|
pub layout: fn(
|
||||||
@ -128,3 +113,29 @@ impl Hash for LangItems {
|
|||||||
self.math_align.hash(state);
|
self.math_align.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Global storage for lang items.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub static LANG_ITEMS: OnceCell<LangItems> = OnceCell::new();
|
||||||
|
|
||||||
|
/// Set the lang items. This is a hack :(
|
||||||
|
///
|
||||||
|
/// Passing the lang items everywhere they are needed (especially the text node
|
||||||
|
/// related things) is very painful. By storing them globally, in theory, we
|
||||||
|
/// break incremental, but only when different sets of lang items are used in
|
||||||
|
/// the same program. For this reason, if this function is called multiple
|
||||||
|
/// times, the items must be the same.
|
||||||
|
pub(crate) fn set_lang_items(items: LangItems) {
|
||||||
|
if let Err(items) = LANG_ITEMS.set(items) {
|
||||||
|
let first = hash128(LANG_ITEMS.get().unwrap());
|
||||||
|
let second = hash128(&items);
|
||||||
|
assert_eq!(first, second, "set differing lang items");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access a lang item.
|
||||||
|
macro_rules! item {
|
||||||
|
($name:ident) => {
|
||||||
|
$crate::model::LANG_ITEMS.get().unwrap().$name
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
//! Document and computation model.
|
//! Document and computation model.
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod items;
|
mod library;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod cast;
|
mod cast;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -34,7 +34,7 @@ pub use self::content::*;
|
|||||||
pub use self::dict::*;
|
pub use self::dict::*;
|
||||||
pub use self::eval::*;
|
pub use self::eval::*;
|
||||||
pub use self::func::*;
|
pub use self::func::*;
|
||||||
pub use self::items::*;
|
pub use self::library::*;
|
||||||
pub use self::scope::*;
|
pub use self::scope::*;
|
||||||
pub use self::str::*;
|
pub use self::str::*;
|
||||||
pub use self::styles::*;
|
pub use self::styles::*;
|
||||||
|
@ -38,7 +38,7 @@ impl<'a> Vm<'a> {
|
|||||||
location,
|
location,
|
||||||
scopes,
|
scopes,
|
||||||
flow: None,
|
flow: None,
|
||||||
items: world.config().items,
|
items: world.library().items.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ impl<'a> Vm<'a> {
|
|||||||
pub fn locate(&self, path: &str) -> StrResult<PathBuf> {
|
pub fn locate(&self, path: &str) -> StrResult<PathBuf> {
|
||||||
if !self.location.is_detached() {
|
if !self.location.is_detached() {
|
||||||
if let Some(path) = path.strip_prefix('/') {
|
if let Some(path) = path.strip_prefix('/') {
|
||||||
return Ok(self.world.config().root.join(path).normalize());
|
return Ok(self.world.root().join(path).normalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dir) = self.world.source(self.location).path().parent() {
|
if let Some(dir) = self.world.source(self.location).path().parent() {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::Path;
|
||||||
|
|
||||||
use comemo::{Prehashed, Track, Tracked};
|
use comemo::{Prehashed, Track, Tracked};
|
||||||
use iai::{black_box, main, Iai};
|
use iai::{black_box, main, Iai};
|
||||||
use typst::diag::{FileError, FileResult};
|
use typst::diag::{FileError, FileResult};
|
||||||
use typst::font::{Font, FontBook};
|
use typst::font::{Font, FontBook};
|
||||||
|
use typst::model::Library;
|
||||||
use typst::syntax::{Source, SourceId, TokenMode, Tokens};
|
use typst::syntax::{Source, SourceId, TokenMode, Tokens};
|
||||||
use typst::util::Buffer;
|
use typst::util::Buffer;
|
||||||
use typst::{Config, World};
|
use typst::World;
|
||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
|
|
||||||
const TEXT: &str = include_str!("../typ/benches/bench.typ");
|
const TEXT: &str = include_str!("../typ/benches/bench.typ");
|
||||||
@ -90,7 +91,7 @@ fn bench_render(iai: &mut Iai) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct BenchWorld {
|
struct BenchWorld {
|
||||||
config: Prehashed<Config>,
|
library: Prehashed<Library>,
|
||||||
book: Prehashed<FontBook>,
|
book: Prehashed<FontBook>,
|
||||||
font: Font,
|
font: Font,
|
||||||
source: Source,
|
source: Source,
|
||||||
@ -98,22 +99,14 @@ struct BenchWorld {
|
|||||||
|
|
||||||
impl BenchWorld {
|
impl BenchWorld {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let config = Config {
|
|
||||||
root: PathBuf::new(),
|
|
||||||
scope: typst_library::scope(),
|
|
||||||
styles: typst_library::styles(),
|
|
||||||
items: typst_library::items(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let font = Font::new(FONT.into(), 0).unwrap();
|
let font = Font::new(FONT.into(), 0).unwrap();
|
||||||
let book = FontBook::from_fonts([&font]);
|
let book = FontBook::from_fonts([&font]);
|
||||||
let source = Source::detached(TEXT);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config: Prehashed::new(config),
|
library: Prehashed::new(typst_library::new()),
|
||||||
book: Prehashed::new(book),
|
book: Prehashed::new(book),
|
||||||
font,
|
font,
|
||||||
source,
|
source: Source::detached(TEXT),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +116,12 @@ impl BenchWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl World for BenchWorld {
|
impl World for BenchWorld {
|
||||||
fn config(&self) -> &Prehashed<Config> {
|
fn root(&self) -> &Path {
|
||||||
&self.config
|
Path::new("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn library(&self) -> &Prehashed<Library> {
|
||||||
|
&self.library
|
||||||
}
|
}
|
||||||
|
|
||||||
fn book(&self) -> &Prehashed<FontBook> {
|
fn book(&self) -> &Prehashed<FontBook> {
|
||||||
|
@ -15,10 +15,10 @@ use typst::diag::{bail, FileError, FileResult};
|
|||||||
use typst::font::{Font, FontBook};
|
use typst::font::{Font, FontBook};
|
||||||
use typst::frame::{Element, Frame};
|
use typst::frame::{Element, Frame};
|
||||||
use typst::geom::{Abs, RgbaColor, Sides};
|
use typst::geom::{Abs, RgbaColor, Sides};
|
||||||
use typst::model::{Smart, Value};
|
use typst::model::{Library, Smart, Value};
|
||||||
use typst::syntax::{Source, SourceId, SyntaxNode};
|
use typst::syntax::{Source, SourceId, SyntaxNode};
|
||||||
use typst::util::{Buffer, PathExt};
|
use typst::util::{Buffer, PathExt};
|
||||||
use typst::{Config, World};
|
use typst::World;
|
||||||
use typst_library::layout::PageNode;
|
use typst_library::layout::PageNode;
|
||||||
use typst_library::text::{TextNode, TextSize};
|
use typst_library::text::{TextNode, TextSize};
|
||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
@ -144,21 +144,22 @@ impl Args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn config() -> Config {
|
fn library() -> Library {
|
||||||
|
let mut lib = typst_library::new();
|
||||||
|
|
||||||
// Set page width to 120pt with 10pt margins, so that the inner page is
|
// Set page width to 120pt with 10pt margins, so that the inner page is
|
||||||
// exactly 100pt wide. Page height is unbounded and font size is 10pt so
|
// exactly 100pt wide. Page height is unbounded and font size is 10pt so
|
||||||
// that it multiplies to nice round numbers.
|
// that it multiplies to nice round numbers.
|
||||||
let mut styles = typst_library::styles();
|
lib.styles.set(PageNode::WIDTH, Smart::Custom(Abs::pt(120.0).into()));
|
||||||
styles.set(PageNode::WIDTH, Smart::Custom(Abs::pt(120.0).into()));
|
lib.styles.set(PageNode::HEIGHT, Smart::Auto);
|
||||||
styles.set(PageNode::HEIGHT, Smart::Auto);
|
lib.styles
|
||||||
styles.set(PageNode::MARGIN, Sides::splat(Some(Smart::Custom(Abs::pt(10.0).into()))));
|
.set(PageNode::MARGIN, Sides::splat(Some(Smart::Custom(Abs::pt(10.0).into()))));
|
||||||
styles.set(TextNode::SIZE, TextSize(Abs::pt(10.0).into()));
|
lib.styles.set(TextNode::SIZE, TextSize(Abs::pt(10.0).into()));
|
||||||
|
|
||||||
// Hook up helpers into the global scope.
|
// Hook up helpers into the global scope.
|
||||||
let mut scope = typst_library::scope();
|
lib.scope.define("conifer", RgbaColor::new(0x9f, 0xEB, 0x52, 0xFF));
|
||||||
scope.define("conifer", RgbaColor::new(0x9f, 0xEB, 0x52, 0xFF));
|
lib.scope.define("forest", RgbaColor::new(0x43, 0xA1, 0x27, 0xFF));
|
||||||
scope.define("forest", RgbaColor::new(0x43, 0xA1, 0x27, 0xFF));
|
lib.scope.def_fn("test", move |_, args| {
|
||||||
scope.def_fn("test", move |_, args| {
|
|
||||||
let lhs = args.expect::<Value>("left-hand side")?;
|
let lhs = args.expect::<Value>("left-hand side")?;
|
||||||
let rhs = args.expect::<Value>("right-hand side")?;
|
let rhs = args.expect::<Value>("right-hand side")?;
|
||||||
if lhs != rhs {
|
if lhs != rhs {
|
||||||
@ -166,7 +167,7 @@ fn config() -> Config {
|
|||||||
}
|
}
|
||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
});
|
});
|
||||||
scope.def_fn("print", move |_, args| {
|
lib.scope.def_fn("print", move |_, args| {
|
||||||
print!("> ");
|
print!("> ");
|
||||||
for (i, value) in args.all::<Value>()?.into_iter().enumerate() {
|
for (i, value) in args.all::<Value>()?.into_iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@ -178,18 +179,13 @@ fn config() -> Config {
|
|||||||
Ok(Value::None)
|
Ok(Value::None)
|
||||||
});
|
});
|
||||||
|
|
||||||
Config {
|
lib
|
||||||
root: PathBuf::new(),
|
|
||||||
scope,
|
|
||||||
styles,
|
|
||||||
items: typst_library::items(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A world that provides access to the tests environment.
|
/// A world that provides access to the tests environment.
|
||||||
struct TestWorld {
|
struct TestWorld {
|
||||||
print: PrintConfig,
|
print: PrintConfig,
|
||||||
config: Prehashed<Config>,
|
library: Prehashed<Library>,
|
||||||
book: Prehashed<FontBook>,
|
book: Prehashed<FontBook>,
|
||||||
fonts: Vec<Font>,
|
fonts: Vec<Font>,
|
||||||
paths: RefCell<HashMap<PathBuf, PathSlot>>,
|
paths: RefCell<HashMap<PathBuf, PathSlot>>,
|
||||||
@ -219,7 +215,7 @@ impl TestWorld {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
print,
|
print,
|
||||||
config: Prehashed::new(config()),
|
library: Prehashed::new(library()),
|
||||||
book: Prehashed::new(FontBook::from_fonts(&fonts)),
|
book: Prehashed::new(FontBook::from_fonts(&fonts)),
|
||||||
fonts,
|
fonts,
|
||||||
paths: RefCell::default(),
|
paths: RefCell::default(),
|
||||||
@ -229,8 +225,12 @@ impl TestWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl World for TestWorld {
|
impl World for TestWorld {
|
||||||
fn config(&self) -> &Prehashed<Config> {
|
fn root(&self) -> &Path {
|
||||||
&self.config
|
Path::new("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn library(&self) -> &Prehashed<Library> {
|
||||||
|
&self.library
|
||||||
}
|
}
|
||||||
|
|
||||||
fn book(&self) -> &Prehashed<FontBook> {
|
fn book(&self) -> &Prehashed<FontBook> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user