Repository: typst/typst
File: crates/typst-cli/src/compile.rs (Rust)

Code before:
    }
}

/// Execute a compilation command.
pub fn compile(mut timer: Timer, mut command: CompileCommand) -> StrResult<()> {
    let mut world =
        SystemWorld::new(&command.common).map_err(|err| eco_format!("{err}"))?;
    timer.record(&mut world, |world| compile_once(world, &mut command, false))??;
    Ok(())
}

/// Compile a single time.
///
/// Returns whether it compiled without errors.
#[typst_macros::time(name = "compile once")]
pub fn compile_once(
    world: &mut SystemWorld,
    command: &mut CompileCommand,
    watching: bool,
) -> StrResult<()> {
    let start = std::time::Instant::now();
    if watching {
        Status::Compiling.print(command).unwrap();
    }

    if !check_main_file_is_valid(world, command, watching)? {
        // No unexpected errors occurred, but the main file was invalid.
        // We have already alerted the user about it, so we don't proceed.
        return Ok(());
    }

    let mut tracer = Tracer::new();
    let result = typst::compile(world, &mut tracer);
    let warnings = tracer.warnings();

    match result {
        // Export the PDF / PNG.
        Ok(document) => {
            export(world, &document, command, watching)?;
            let duration = start.elapsed();

            if watching {
                if warnings.is_empty() {
                    Status::Success(duration).print(command).unwrap();
                } else {
                    Status::PartialSuccess(duration).print(command).unwrap();
                }
            }

            print_diagnostics(world, &[], &warnings, command.common.diagnostic_format)
                .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;

Review comment (refactor):
I think a cleaner way to do this would be something like
```rs
    if let Err(errors) = world
        .source(world.main())
        .map_err(|err| hint_main_file(err, &command.common.input))
```
Then we only extract the hinting into a separate function and we don't need `unwrap_err` below.

Code after:

/// Execute a compilation command.
pub fn compile(mut timer: Timer, mut command: CompileCommand) -> StrResult<()> {
    let mut world =
        SystemWorld::new(&command.common).map_err(|err| eco_format!("{err}"))?;
    timer.record(&mut world, |world| compile_once(world, &mut command, false))??;
    Ok(())
}

/// Compile a single time.
///
/// Returns whether it compiled without errors.
#[typst_macros::time(name = "compile once")]
pub fn compile_once(
    world: &mut SystemWorld,
    command: &mut CompileCommand,
    watching: bool,
) -> StrResult<()> {
    let start = std::time::Instant::now();
    if watching {
        Status::Compiling.print(command).unwrap();
    }

    if let Err(errors) = world
        .source(world.main())
        .map_err(|err| hint_invalid_main_file(err, &command.common.input))
    {
        set_failed();
        if watching {
            Status::Error.print(command).unwrap();
        }

        print_diagnostics(world, &errors, &[], command.common.diagnostic_format)
            .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;

        return Ok(());
    }

    let mut tracer = Tracer::new();
    let result = typst::compile(world, &mut tracer);
    let warnings = tracer.warnings();

    match result {
        // Export the PDF / PNG.
        Ok(document) => {
            export(world, &document, command, watching)?;
            let duration = start.elapsed();

            if watching {
                if warnings.is_empty() {
                    Status::Success(duration).print(command).unwrap();