This commit is contained in:
Laurenz 2023-06-24 15:05:59 +02:00
parent b96b7b7ee1
commit f1025071ed
9 changed files with 63 additions and 63 deletions

View File

@ -303,15 +303,16 @@ fn compile(mut command: CompileSettings) -> StrResult<()> {
#[tracing::instrument(skip_all)]
fn compile_once(world: &mut SystemWorld, command: &CompileSettings) -> StrResult<bool> {
tracing::info!("Starting compilation");
let start_time = std::time::Instant::now();
let start = std::time::Instant::now();
status(command, Status::Compiling).unwrap();
world.reset();
world.main = world.resolve(&command.input).map_err(|err| err.to_string())?;
let result = typst::compile(world);
let duration = start_time.elapsed();
let duration = start.elapsed();
match result {
// Export the PDF / PNG.
Ok(document) => {
@ -427,9 +428,9 @@ enum Status {
impl Status {
fn message(&self) -> String {
match self {
Self::Compiling => "compiling ...".to_string(),
Self::Compiling => "compiling ...".into(),
Self::Success(duration) => format!("compiled successfully in {duration:.2?}"),
Self::Error => "compiled with errors".to_string(),
Self::Error => "compiled with errors".into(),
}
}

View File

@ -125,11 +125,10 @@ pub struct LimitsElem {
#[required]
pub body: Content,
/// Whether to apply limits in inline equations.
/// Whether to also force limits in inline equations.
///
/// It is useful to disable this setting
/// in most cases of applying limits globally
/// (inside show rules or new elements)
/// When applying limits globally (e.g., through a show rule), it is
/// typically a good idea to disable this.
#[default(true)]
pub inline: bool,
}

View File

@ -85,11 +85,11 @@ impl MathRow {
self.0.iter()
}
/// It is very unintuitive, but in current state of things
/// `MathRow` can contain several actual rows.
/// That function deconstructs it to "single" rows.
/// Extract the sublines of the row.
///
/// Hopefully that cloner is only a temporary hack
/// It is very unintuitive, but in current state of things, a `MathRow` can
/// contain several actual rows. That function deconstructs it to "single"
/// rows. Hopefully this is only a temporary hack.
pub fn rows(&self) -> Vec<Self> {
self.0
.split(|frag| matches!(frag, MathFragment::Linebreak))

View File

@ -206,9 +206,8 @@ fn layout(
let body = body.into_fragment(ctx);
let glyph = GlyphFragment::new(ctx, c, span);
let stretched = glyph.stretch_horizontal(ctx, body.width(), Abs::zero());
let body = MathRow::new(vec![body]);
let mut rows = vec![body, stretched.into()];
let mut rows = vec![MathRow::new(vec![body]), stretched.into()];
ctx.style(if reverse {
ctx.style.for_subscript()
} else {

View File

@ -1,5 +1,3 @@
use typst::diag::Hint;
use super::{BibliographyElem, CiteElem, Counter, Figurable, Numbering};
use crate::prelude::*;
use crate::text::TextElem;

View File

@ -10,7 +10,7 @@ pub use comemo::{Track, Tracked, TrackedMut};
#[doc(no_inline)]
pub use ecow::{eco_format, EcoString};
#[doc(no_inline)]
pub use typst::diag::{bail, error, At, SourceResult, StrResult};
pub use typst::diag::{bail, error, At, Hint, SourceResult, StrResult};
#[doc(no_inline)]
pub use typst::doc::*;
#[doc(no_inline)]

View File

@ -82,7 +82,8 @@ pub struct SourceError {
pub message: EcoString,
/// The trace of function calls leading to the error.
pub trace: Vec<Spanned<Tracepoint>>,
/// Additonal hints to the user, indicating how this error could be avoided or worked around.
/// Additonal hints to the user, indicating how this error could be avoided
/// or worked around.
pub hints: Vec<EcoString>,
}
@ -104,6 +105,12 @@ impl SourceError {
self
}
/// Adds user-facing hints to the error.
pub fn with_hints(mut self, hints: impl IntoIterator<Item = EcoString>) -> Self {
self.hints.extend(hints);
self
}
/// The range in the source file identified by
/// [`self.span.source()`](Span::source) where the error should be
/// annotated.
@ -115,12 +122,6 @@ impl SourceError {
ErrorPos::End => full.end..full.end,
}
}
/// Adds a user-facing hint to the error.
pub fn with_hints(mut self, hints: &mut Vec<EcoString>) -> Self {
self.hints.append(hints);
self
}
}
/// A part of an error's [trace](SourceError::trace).
@ -203,48 +204,44 @@ where
}
}
pub type StrWithHintResult<T> = Result<T, StrWithHint>;
/// A result type with a string error message and hints.
pub type HintedStrResult<T> = Result<T, HintedString>;
pub struct StrWithHint {
message: EcoString,
hints: Vec<EcoString>,
/// A string message with hints.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct HintedString {
/// A diagnostic message describing the problem.
pub message: EcoString,
/// Additonal hints to the user, indicating how this error could be avoided
/// or worked around.
pub hints: Vec<EcoString>,
}
impl<T> At<T> for Result<T, StrWithHint> {
impl<T> At<T> for Result<T, HintedString> {
fn at(self, span: Span) -> SourceResult<T> {
self.map_err(|mut diags| {
Box::new(vec![
SourceError::new(span, diags.message).with_hints(&mut diags.hints)
])
self.map_err(|diags| {
Box::new(vec![SourceError::new(span, diags.message).with_hints(diags.hints)])
})
}
}
/// Allows adding a user-facing hint in addition to the error.
pub trait Hint<T, S>
where
S: Into<EcoString>,
{
fn hint(self, hint: S) -> StrWithHintResult<T>;
/// Enrich a [`StrResult`] or [`HintedStrResult`] with a hint.
pub trait Hint<T> {
/// Add the hint.
fn hint(self, hint: impl Into<EcoString>) -> HintedStrResult<T>;
}
impl<T, S> Hint<T, S> for StrResult<T>
where
S: Into<EcoString>,
{
fn hint(self, hint: S) -> StrWithHintResult<T> {
self.map_err(|message| StrWithHint { message, hints: vec![hint.into()] })
impl<T> Hint<T> for StrResult<T> {
fn hint(self, hint: impl Into<EcoString>) -> HintedStrResult<T> {
self.map_err(|message| HintedString { message, hints: vec![hint.into()] })
}
}
impl<T, S> Hint<T, S> for StrWithHintResult<T>
where
S: Into<EcoString>,
{
fn hint(self, hint: S) -> StrWithHintResult<T> {
self.map_err(|mut diags| {
diags.hints.push(hint.into());
diags
impl<T> Hint<T> for HintedStrResult<T> {
fn hint(self, hint: impl Into<EcoString>) -> HintedStrResult<T> {
self.map_err(|mut error| {
error.hints.push(hint.into());
error
})
}
}

View File

@ -488,14 +488,18 @@ fn render_image(
let view_width = size.x.to_f32();
let view_height = size.y.to_f32();
let aspect = (image.width() as f32) / (image.height() as f32);
// For better-looking output, resize `image` to its final size before painting it to `canvas`.
// See https://github.com/typst/typst/issues/1404#issuecomment-1598374652 for the math.
// For better-looking output, resize `image` to its final size before
// painting it to `canvas`. For the math, see:
// https://github.com/typst/typst/issues/1404#issuecomment-1598374652
let theta = f32::atan2(-ts.kx, ts.sx);
// To avoid division by 0, choose the one of { sin, cos } that is further from 0.
// To avoid division by 0, choose the one of { sin, cos } that is
// further from 0.
let prefer_sin = theta.sin().abs() > std::f32::consts::FRAC_1_SQRT_2;
let scale_x =
f32::abs(if prefer_sin { ts.kx / theta.sin() } else { ts.sx / theta.cos() });
let aspect = (image.width() as f32) / (image.height() as f32);
let w = (scale_x * view_width.max(aspect * view_height)).ceil() as u32;
let h = ((w as f32) / aspect).ceil() as u32;

View File

@ -2,13 +2,14 @@
use std::cell::{RefCell, RefMut};
use std::collections::{HashMap, HashSet};
use std::env;
use std::ffi::OsStr;
use std::fmt::Write as FmtWrite;
use std::io::Write;
use std::fs;
use std::io::{self, Write};
use std::iter;
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::{env, io};
use std::{fs, iter};
use clap::Parser;
use comemo::{Prehashed, Track};
@ -555,10 +556,11 @@ fn test_part(
}
// Map errors to range and message format, discard traces and errors from
// other files. Collect hints.
// other files, collect hints.
//
// This has one caveat: due to the format of the expected hints, we can not verify if a hint belongs
// to a error or not. That should be irrelevant however, as the line of the hint is still verified.
// This has one caveat: due to the format of the expected hints, we can not
// verify if a hint belongs to a error or not. That should be irrelevant
// however, as the line of the hint is still verified.
let actual_errors_and_hints: HashSet<UserOutput> = errors
.into_iter()
.filter(|error| error.span.source() == id)