Separate typesetting and compilation

This commit is contained in:
Laurenz 2022-11-24 17:51:07 +01:00
parent 8d3c68a1de
commit 96f72eee6c
6 changed files with 49 additions and 24 deletions

View File

@ -30,12 +30,12 @@ type CodespanError = codespan_reporting::files::Error;
/// What to do. /// What to do.
enum Command { enum Command {
Typeset(TypesetCommand), Compile(CompileCommand),
Fonts(FontsCommand), Fonts(FontsCommand),
} }
/// Typeset a .typ file into a PDF file. /// Compile a .typ file into a PDF file.
struct TypesetCommand { struct CompileCommand {
input: PathBuf, input: PathBuf,
output: PathBuf, output: PathBuf,
root: Option<PathBuf>, root: Option<PathBuf>,
@ -110,7 +110,7 @@ fn parse_args() -> StrResult<Command> {
let root = args.opt_value_from_str("--root").map_err(|_| "missing root path")?; let root = args.opt_value_from_str("--root").map_err(|_| "missing root path")?;
let watch = args.contains(["-w", "--watch"]); let watch = args.contains(["-w", "--watch"]);
let (input, output) = parse_input_output(&mut args, "pdf")?; let (input, output) = parse_input_output(&mut args, "pdf")?;
Command::Typeset(TypesetCommand { input, output, watch, root }) Command::Compile(CompileCommand { input, output, watch, root })
}; };
// Don't allow excess arguments. // Don't allow excess arguments.
@ -164,13 +164,13 @@ fn print_error(msg: &str) -> io::Result<()> {
/// Dispatch a command. /// Dispatch a command.
fn dispatch(command: Command) -> StrResult<()> { fn dispatch(command: Command) -> StrResult<()> {
match command { match command {
Command::Typeset(command) => typeset(command), Command::Compile(command) => compile(command),
Command::Fonts(command) => fonts(command), Command::Fonts(command) => fonts(command),
} }
} }
/// Execute a typesetting command. /// Execute a compilation command.
fn typeset(command: TypesetCommand) -> StrResult<()> { fn compile(command: CompileCommand) -> StrResult<()> {
let root = if let Some(root) = &command.root { let root = if let Some(root) = &command.root {
root.clone() root.clone()
} else if let Some(dir) = command.input.parent() { } else if let Some(dir) = command.input.parent() {
@ -182,8 +182,8 @@ fn typeset(command: TypesetCommand) -> StrResult<()> {
// Create the world that serves sources, fonts and files. // Create the world that serves sources, fonts and files.
let mut world = SystemWorld::new(root); let mut world = SystemWorld::new(root);
// Typeset. // Perform initial compilation.
typeset_once(&mut world, &command)?; compile_once(&mut world, &command)?;
if !command.watch { if !command.watch {
return Ok(()); return Ok(());
@ -221,20 +221,20 @@ fn typeset(command: TypesetCommand) -> StrResult<()> {
} }
if recompile { if recompile {
typeset_once(&mut world, &command)?; compile_once(&mut world, &command)?;
} }
} }
} }
/// Typeset a single time. /// Compile a single time.
fn typeset_once(world: &mut SystemWorld, command: &TypesetCommand) -> StrResult<()> { fn compile_once(world: &mut SystemWorld, command: &CompileCommand) -> StrResult<()> {
status(command, Status::Compiling).unwrap(); status(command, Status::Compiling).unwrap();
world.reset(); world.reset();
let main = world.resolve(&command.input).map_err(|err| err.to_string())?; let main = world.resolve(&command.input).map_err(|err| err.to_string())?;
let source = world.source(main); let source = world.source(main);
match typst::typeset(world, source) { match typst::compile(world, source) {
// Export the PDF. // Export the PDF.
Ok(frames) => { Ok(frames) => {
let buffer = typst::export::pdf(&frames); let buffer = typst::export::pdf(&frames);
@ -254,7 +254,7 @@ fn typeset_once(world: &mut SystemWorld, command: &TypesetCommand) -> StrResult<
} }
/// Clear the terminal and render the status message. /// Clear the terminal and render the status message.
fn status(command: &TypesetCommand, status: Status) -> io::Result<()> { fn status(command: &CompileCommand, status: Status) -> io::Result<()> {
if !command.watch { if !command.watch {
return Ok(()); return Ok(());
} }

View File

@ -49,16 +49,16 @@ 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::{Library, Route, StyleChain}; use crate::model::{Library, Route};
use crate::syntax::{Source, SourceId}; use crate::syntax::{Source, SourceId};
use crate::util::Buffer; use crate::util::Buffer;
/// Typeset a source file into a collection of layouted frames. /// Compile a source file into a collection of layouted frames.
/// ///
/// Returns either a vector of frames representing individual pages or /// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span /// diagnostics in the form of a vector of error message with file and span
/// information. /// information.
pub fn typeset( pub fn compile(
world: &(dyn World + 'static), world: &(dyn World + 'static),
source: &Source, source: &Source,
) -> SourceResult<Vec<Frame>> { ) -> SourceResult<Vec<Frame>> {
@ -66,10 +66,8 @@ pub fn typeset(
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. // Typeset the module's contents.
let library = world.library(); model::typeset(world.track(), &module.content)
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.

View File

@ -21,6 +21,7 @@ mod func;
mod methods; mod methods;
mod ops; mod ops;
mod scope; mod scope;
mod typeset;
mod vm; mod vm;
#[doc(hidden)] #[doc(hidden)]
@ -38,5 +39,6 @@ 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::*;
pub use self::typeset::*;
pub use self::value::*; pub use self::value::*;
pub use self::vm::*; pub use self::vm::*;

17
src/model/typeset.rs Normal file
View File

@ -0,0 +1,17 @@
use comemo::Tracked;
use super::{Content, StyleChain};
use crate::diag::SourceResult;
use crate::frame::Frame;
use crate::World;
/// Typeset content into a collection of layouted frames.
///
/// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span
/// information.
pub fn typeset(world: Tracked<dyn World>, content: &Content) -> SourceResult<Vec<Frame>> {
let library = world.library();
let styles = StyleChain::with_root(&library.styles);
(library.items.layout)(content, world, styles)
}

View File

@ -21,6 +21,7 @@ main!(
bench_edit, bench_edit,
bench_eval, bench_eval,
bench_typeset, bench_typeset,
bench_compile,
bench_highlight, bench_highlight,
bench_render, bench_render,
); );
@ -81,12 +82,19 @@ fn bench_eval(iai: &mut Iai) {
fn bench_typeset(iai: &mut Iai) { fn bench_typeset(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
iai.run(|| typst::typeset(&world, &world.source)); let route = typst::model::Route::default();
let module = typst::model::eval(world.track(), route.track(), &world.source).unwrap();
iai.run(|| typst::model::typeset(world.track(), &module.content));
}
fn bench_compile(iai: &mut Iai) {
let world = BenchWorld::new();
iai.run(|| typst::compile(&world, &world.source));
} }
fn bench_render(iai: &mut Iai) { fn bench_render(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
let frames = typst::typeset(&world, &world.source).unwrap(); let frames = typst::compile(&world, &world.source).unwrap();
iai.run(|| typst::export::render(&frames[0], 1.0)) iai.run(|| typst::export::render(&frames[0], 1.0))
} }

View File

@ -424,7 +424,7 @@ fn test_part(
println!("Model:\n{:#?}\n", module.content); println!("Model:\n{:#?}\n", module.content);
} }
let (mut frames, errors) = match typst::typeset(world, source) { let (mut frames, errors) = match typst::compile(world, source) {
Ok(frames) => (frames, vec![]), Ok(frames) => (frames, vec![]),
Err(errors) => (vec![], *errors), Err(errors) => (vec![], *errors),
}; };