summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-09-20 19:49:47 +0200
committerLaurenz <laurmaedje@gmail.com>2022-09-20 19:49:47 +0200
commit3760748fddd3b793c79c370398a9d4a3fc5afc04 (patch)
treeb1a615e510aa231cfe9757a9c0a35a375e32e3ba /src/library
parent757a701c1aa2a6fb80033c7e75666661818da6f9 (diff)
Refactor error handling
Diffstat (limited to 'src/library')
-rw-r--r--src/library/graphics/hide.rs4
-rw-r--r--src/library/graphics/image.rs21
-rw-r--r--src/library/graphics/line.rs4
-rw-r--r--src/library/graphics/shape.rs4
-rw-r--r--src/library/graphics/transform.rs8
-rw-r--r--src/library/layout/align.rs4
-rw-r--r--src/library/layout/columns.rs6
-rw-r--r--src/library/layout/container.rs4
-rw-r--r--src/library/layout/flow.rs4
-rw-r--r--src/library/layout/grid.rs27
-rw-r--r--src/library/layout/pad.rs4
-rw-r--r--src/library/layout/page.rs12
-rw-r--r--src/library/layout/place.rs4
-rw-r--r--src/library/layout/spacing.rs4
-rw-r--r--src/library/layout/stack.rs6
-rw-r--r--src/library/math/mod.rs6
-rw-r--r--src/library/math/rex.rs4
-rw-r--r--src/library/prelude.rs4
-rw-r--r--src/library/structure/doc.rs6
-rw-r--r--src/library/structure/heading.rs8
-rw-r--r--src/library/structure/list.rs8
-rw-r--r--src/library/structure/reference.rs4
-rw-r--r--src/library/structure/table.rs10
-rw-r--r--src/library/text/deco.rs4
-rw-r--r--src/library/text/link.rs6
-rw-r--r--src/library/text/mod.rs18
-rw-r--r--src/library/text/par.rs14
-rw-r--r--src/library/text/raw.rs6
-rw-r--r--src/library/text/repeat.rs4
-rw-r--r--src/library/text/shaping.rs8
-rw-r--r--src/library/text/shift.rs6
-rw-r--r--src/library/utility/color.rs6
-rw-r--r--src/library/utility/data.rs47
-rw-r--r--src/library/utility/math.rs20
-rw-r--r--src/library/utility/mod.rs8
-rw-r--r--src/library/utility/string.rs16
36 files changed, 179 insertions, 150 deletions
diff --git a/src/library/graphics/hide.rs b/src/library/graphics/hide.rs
index f2a423ce..505dd1f6 100644
--- a/src/library/graphics/hide.rs
+++ b/src/library/graphics/hide.rs
@@ -6,7 +6,7 @@ pub struct HideNode(pub LayoutNode);
#[node]
impl HideNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::inline(Self(args.expect("body")?)))
}
}
@@ -17,7 +17,7 @@ impl Layout for HideNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let mut frames = self.0.layout(world, regions, styles)?;
for frame in &mut frames {
frame.clear();
diff --git a/src/library/graphics/image.rs b/src/library/graphics/image.rs
index 1642c7b0..c0249b3c 100644
--- a/src/library/graphics/image.rs
+++ b/src/library/graphics/image.rs
@@ -1,6 +1,6 @@
use std::ffi::OsStr;
-use crate::image::Image;
+use crate::image::{Image, ImageFormat, RasterFormat, VectorFormat};
use crate::library::prelude::*;
use crate::library::text::TextNode;
@@ -13,19 +13,22 @@ impl ImageNode {
/// How the image should adjust itself to a given area.
pub const FIT: ImageFit = ImageFit::Cover;
- fn construct(vm: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(vm: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let Spanned { v: path, span } =
args.expect::<Spanned<EcoString>>("path to image file")?;
let full = vm.locate(&path).at(span)?;
+ let buffer = vm.world.file(&full).at(span)?;
let ext = full.extension().and_then(OsStr::to_str).unwrap_or_default();
- let image = vm
- .world
- .file(&full)
- .and_then(|buffer| Image::new(buffer, ext))
- .map_err(|err| failed_to_load("image", &full, err))
- .at(span)?;
+ let format = match ext.to_lowercase().as_str() {
+ "png" => ImageFormat::Raster(RasterFormat::Png),
+ "jpg" | "jpeg" => ImageFormat::Raster(RasterFormat::Jpg),
+ "gif" => ImageFormat::Raster(RasterFormat::Gif),
+ "svg" | "svgz" => ImageFormat::Vector(VectorFormat::Svg),
+ _ => bail!(span, "unknown image format"),
+ };
+ let image = Image::new(buffer, format).at(span)?;
let width = args.named("width")?;
let height = args.named("height")?;
@@ -41,7 +44,7 @@ impl Layout for ImageNode {
_: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let pxw = self.0.width() as f64;
let pxh = self.0.height() as f64;
let px_ratio = pxw / pxh;
diff --git a/src/library/graphics/line.rs b/src/library/graphics/line.rs
index 95c3a709..ebfec1b2 100644
--- a/src/library/graphics/line.rs
+++ b/src/library/graphics/line.rs
@@ -15,7 +15,7 @@ impl LineNode {
#[property(resolve, fold)]
pub const STROKE: RawStroke = RawStroke::default();
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let origin = args.named("origin")?.unwrap_or_default();
let delta = match args.named::<Spec<Relative<RawLength>>>("to")? {
@@ -43,7 +43,7 @@ impl Layout for LineNode {
_: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let stroke = styles.get(Self::STROKE).unwrap_or_default();
let origin = self
diff --git a/src/library/graphics/shape.rs b/src/library/graphics/shape.rs
index ee5e43e8..d9162557 100644
--- a/src/library/graphics/shape.rs
+++ b/src/library/graphics/shape.rs
@@ -39,7 +39,7 @@ impl<const S: ShapeKind> ShapeNode<S> {
pub const RADIUS: Corners<Option<Relative<RawLength>>> =
Corners::splat(Relative::zero());
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let size = match S {
SQUARE => args.named::<RawLength>("size")?.map(Relative::from),
CIRCLE => args.named::<RawLength>("radius")?.map(|r| 2.0 * Relative::from(r)),
@@ -81,7 +81,7 @@ impl<const S: ShapeKind> Layout for ShapeNode<S> {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let mut frames;
if let Some(child) = &self.0 {
let mut inset = styles.get(Self::INSET);
diff --git a/src/library/graphics/transform.rs b/src/library/graphics/transform.rs
index 0a4f5b5f..34d45bd0 100644
--- a/src/library/graphics/transform.rs
+++ b/src/library/graphics/transform.rs
@@ -12,7 +12,7 @@ pub struct MoveNode {
#[node]
impl MoveNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let dx = args.named("dx")?.unwrap_or_default();
let dy = args.named("dy")?.unwrap_or_default();
Ok(Content::inline(Self {
@@ -28,7 +28,7 @@ impl Layout for MoveNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let mut frames = self.child.layout(world, regions, styles)?;
let delta = self.delta.resolve(styles);
@@ -62,7 +62,7 @@ impl<const T: TransformKind> TransformNode<T> {
#[property(resolve)]
pub const ORIGIN: Spec<Option<RawAlign>> = Spec::default();
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let transform = match T {
ROTATE => {
let angle = args.named_or_find("angle")?.unwrap_or_default();
@@ -89,7 +89,7 @@ impl<const T: TransformKind> Layout for TransformNode<T> {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
let mut frames = self.child.layout(world, regions, styles)?;
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs
index 3b1a4aaf..0c758cf2 100644
--- a/src/library/layout/align.rs
+++ b/src/library/layout/align.rs
@@ -12,7 +12,7 @@ pub struct AlignNode {
#[node]
impl AlignNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let aligns: Spec<Option<RawAlign>> = args.find()?.unwrap_or_default();
let body: Content = args.expect("body")?;
Ok(match (body, aligns) {
@@ -31,7 +31,7 @@ impl Layout for AlignNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// The child only needs to expand along an axis if there's no alignment.
let mut pod = regions.clone();
pod.expand &= self.aligns.map_is_none();
diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs
index bfbbfd8d..e0163f63 100644
--- a/src/library/layout/columns.rs
+++ b/src/library/layout/columns.rs
@@ -17,7 +17,7 @@ impl ColumnsNode {
#[property(resolve)]
pub const GUTTER: Relative<RawLength> = Ratio::new(0.04).into();
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::block(Self {
columns: args.expect("column count")?,
child: args.expect("body")?,
@@ -31,7 +31,7 @@ impl Layout for ColumnsNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.first.x.is_finite() {
@@ -106,7 +106,7 @@ pub struct ColbreakNode;
#[node]
impl ColbreakNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let weak = args.named("weak")?.unwrap_or(false);
Ok(Content::Colbreak { weak })
}
diff --git a/src/library/layout/container.rs b/src/library/layout/container.rs
index 66a43751..23556a2e 100644
--- a/src/library/layout/container.rs
+++ b/src/library/layout/container.rs
@@ -5,7 +5,7 @@ pub struct BoxNode;
#[node]
impl BoxNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let width = args.named("width")?;
let height = args.named("height")?;
let body: LayoutNode = args.eat()?.unwrap_or_default();
@@ -18,7 +18,7 @@ pub struct BlockNode;
#[node]
impl BlockNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::Block(args.eat()?.unwrap_or_default()))
}
}
diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs
index 841b80aa..05c10789 100644
--- a/src/library/layout/flow.rs
+++ b/src/library/layout/flow.rs
@@ -28,7 +28,7 @@ impl Layout for FlowNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let mut layouter = FlowLayouter::new(regions);
for (child, map) in self.0.iter() {
@@ -152,7 +152,7 @@ impl FlowLayouter {
world: &dyn World,
node: &LayoutNode,
styles: StyleChain,
- ) -> TypResult<()> {
+ ) -> SourceResult<()> {
// Don't even try layouting into a full region.
if self.regions.is_full() {
self.finish_region();
diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs
index 3fde9c10..cd4fc6b4 100644
--- a/src/library/layout/grid.rs
+++ b/src/library/layout/grid.rs
@@ -13,7 +13,7 @@ pub struct GridNode {
#[node]
impl GridNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let columns = args.named("columns")?.unwrap_or_default();
let rows = args.named("rows")?.unwrap_or_default();
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
@@ -36,7 +36,7 @@ impl Layout for GridNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Prepare grid layout by unifying content and gutter tracks.
let layouter = GridLayouter::new(
world,
@@ -203,7 +203,7 @@ impl<'a> GridLayouter<'a> {
}
/// Determines the columns sizes and then layouts the grid row-by-row.
- pub fn layout(mut self) -> TypResult<Vec<Frame>> {
+ pub fn layout(mut self) -> SourceResult<Vec<Frame>> {
self.measure_columns()?;
for y in 0 .. self.rows.len() {
@@ -228,7 +228,7 @@ impl<'a> GridLayouter<'a> {
}
/// Determine all column sizes.
- fn measure_columns(&mut self) -> TypResult<()> {
+ fn measure_columns(&mut self) -> SourceResult<()> {
// Sum of sizes of resolved relative tracks.
let mut rel = Length::zero();
@@ -275,7 +275,10 @@ impl<'a> GridLayouter<'a> {
}
/// Measure the size that is available to auto columns.
- fn measure_auto_columns(&mut self, available: Length) -> TypResult<(Length, usize)> {
+ fn measure_auto_columns(
+ &mut self,
+ available: Length,
+ ) -> SourceResult<(Length, usize)> {
let mut auto = Length::zero();
let mut count = 0;
@@ -355,7 +358,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with automatic height. Such a row may break across multiple
/// regions.
- fn layout_auto_row(&mut self, y: usize) -> TypResult<()> {
+ fn layout_auto_row(&mut self, y: usize) -> SourceResult<()> {
let mut resolved: Vec<Length> = vec![];
// Determine the size for each region of the row.
@@ -423,7 +426,11 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with relative height. Such a row cannot break across
/// multiple regions, but it may force a region break.
- fn layout_relative_row(&mut self, v: Relative<RawLength>, y: usize) -> TypResult<()> {
+ fn layout_relative_row(
+ &mut self,
+ v: Relative<RawLength>,
+ y: usize,
+ ) -> SourceResult<()> {
let resolved = v.resolve(self.styles).relative_to(self.regions.base.y);
let frame = self.layout_single_row(resolved, y)?;
@@ -444,7 +451,7 @@ impl<'a> GridLayouter<'a> {
}
/// Layout a row with fixed height and return its frame.
- fn layout_single_row(&mut self, height: Length, y: usize) -> TypResult<Frame> {
+ fn layout_single_row(&mut self, height: Length, y: usize) -> SourceResult<Frame> {
let mut output = Frame::new(Size::new(self.used.x, height));
let mut pos = Point::zero();
@@ -483,7 +490,7 @@ impl<'a> GridLayouter<'a> {
&mut self,
heights: &[Length],
y: usize,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Prepare frames.
let mut outputs: Vec<_> = heights
.iter()
@@ -535,7 +542,7 @@ impl<'a> GridLayouter<'a> {
}
/// Finish rows for one region.
- fn finish_region(&mut self) -> TypResult<()> {
+ fn finish_region(&mut self) -> SourceResult<()> {
// Determine the size of the grid in this region, expanding fully if
// there are fr rows.
let mut size = self.used;
diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs
index 72235ccd..983bfa11 100644
--- a/src/library/layout/pad.rs
+++ b/src/library/layout/pad.rs
@@ -11,7 +11,7 @@ pub struct PadNode {
#[node]
impl PadNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let all = args.named("rest")?.or(args.find()?);
let x = args.named("x")?;
let y = args.named("y")?;
@@ -31,7 +31,7 @@ impl Layout for PadNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Layout child into padded regions.
let padding = self.padding.resolve(styles);
let pod = regions.map(|size| shrink(size, padding));
diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs
index 6e43c4ef..ba597263 100644
--- a/src/library/layout/page.rs
+++ b/src/library/layout/page.rs
@@ -41,7 +41,7 @@ impl PageNode {
#[property(referenced)]
pub const FOREGROUND: Marginal = Marginal::None;
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::Page(Self(args.expect("body")?)))
}
@@ -60,7 +60,7 @@ impl PageNode {
world: &dyn World,
mut page: usize,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// When one of the lengths is infinite the page fits its content along
// that axis.
let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
@@ -159,7 +159,7 @@ pub struct PagebreakNode;
#[node]
impl PagebreakNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let weak = args.named("weak")?.unwrap_or(false);
Ok(Content::Pagebreak { weak })
}
@@ -178,7 +178,11 @@ pub enum Marginal {
impl Marginal {
/// Resolve the marginal based on the page number.
- pub fn resolve(&self, world: &dyn World, page: usize) -> TypResult<Option<Content>> {
+ pub fn resolve(
+ &self,
+ world: &dyn World,
+ page: usize,
+ ) -> SourceResult<Option<Content>> {
Ok(match self {
Self::None => None,
Self::Content(content) => Some(content.clone()),
diff --git a/src/library/layout/place.rs b/src/library/layout/place.rs
index bb3aac2d..862c969e 100644
--- a/src/library/layout/place.rs
+++ b/src/library/layout/place.rs
@@ -7,7 +7,7 @@ pub struct PlaceNode(pub LayoutNode);
#[node]
impl PlaceNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let aligns = args.find()?.unwrap_or(Spec::with_x(Some(RawAlign::Start)));
let dx = args.named("dx")?.unwrap_or_default();
let dy = args.named("dy")?.unwrap_or_default();
@@ -24,7 +24,7 @@ impl Layout for PlaceNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let out_of_flow = self.out_of_flow();
// The pod is the base area of the region because for absolute
diff --git a/src/library/layout/spacing.rs b/src/library/layout/spacing.rs
index e435e60c..0c5cbb92 100644
--- a/src/library/layout/spacing.rs
+++ b/src/library/layout/spacing.rs
@@ -8,7 +8,7 @@ pub struct HNode;
#[node]
impl HNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let amount = args.expect("spacing")?;
let weak = args.named("weak")?.unwrap_or(false);
Ok(Content::Horizontal { amount, weak })
@@ -20,7 +20,7 @@ pub struct VNode;
#[node]
impl VNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let amount = args.expect("spacing")?;
let weak = args.named("weak")?.unwrap_or(false);
Ok(Content::Vertical { amount, weak, generated: false })
diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs
index d07dc35e..a9fc1621 100644
--- a/src/library/layout/stack.rs
+++ b/src/library/layout/stack.rs
@@ -15,7 +15,7 @@ pub struct StackNode {
#[node]
impl StackNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::block(Self {
dir: args.named("dir")?.unwrap_or(Dir::TTB),
spacing: args.named("spacing")?,
@@ -30,7 +30,7 @@ impl Layout for StackNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
let mut layouter = StackLayouter::new(self.dir, regions, styles);
// Spacing to insert before the next node.
@@ -171,7 +171,7 @@ impl<'a> StackLayouter<'a> {
world: &dyn World,
node: &LayoutNode,
styles: StyleChain,
- ) -> TypResult<()> {
+ ) -> SourceResult<()> {
if self.regions.is_full() {
self.finish_region();
}
diff --git a/src/library/math/mod.rs b/src/library/math/mod.rs
index ed98ab1c..d71f6976 100644
--- a/src/library/math/mod.rs
+++ b/src/library/math/mod.rs
@@ -28,7 +28,7 @@ impl MathNode {
#[property(resolve, shorthand(around))]
pub const BELOW: Option<BlockSpacing> = Some(Ratio::one().into());
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self {
formula: args.expect("formula")?,
display: args.named("display")?.unwrap_or(false),
@@ -48,7 +48,7 @@ impl Show for MathNode {
}
}
- fn realize(&self, _: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, styles: StyleChain) -> SourceResult<Content> {
let node = self::rex::RexNode {
tex: self.formula.clone(),
display: self.display,
@@ -67,7 +67,7 @@ impl Show for MathNode {
_: &dyn World,
styles: StyleChain,
mut realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
let mut map = StyleMap::new();
map.set_family(styles.get(Self::FAMILY).clone(), styles);
diff --git a/src/library/math/rex.rs b/src/library/math/rex.rs
index 7bfdeb7a..76ba5177 100644
--- a/src/library/math/rex.rs
+++ b/src/library/math/rex.rs
@@ -25,13 +25,13 @@ impl Layout for RexNode {
world: &dyn World,
_: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Load the font.
let span = self.tex.span;
let font = world
.book()
.select(self.family.as_str(), variant(styles))
- .and_then(|id| world.font(id).ok())
+ .and_then(|id| world.font(id))
.ok_or("failed to find math font")
.at(span)?;
diff --git a/src/library/prelude.rs b/src/library/prelude.rs
index a69d9791..48eebaf6 100644
--- a/src/library/prelude.rs
+++ b/src/library/prelude.rs
@@ -8,9 +8,7 @@ pub use std::sync::Arc;
pub use typst_macros::node;
-pub use crate::diag::{
- failed_to_load, with_alternative, At, Error, StrResult, TypError, TypResult,
-};
+pub use crate::diag::{with_alternative, At, SourceError, SourceResult, StrResult};
pub use crate::eval::{
Arg, Args, Array, Cast, Dict, Dynamic, Func, Node, RawAlign, RawLength, RawStroke,
Scope, Smart, Value, Vm,
diff --git a/src/library/structure/doc.rs b/src/library/structure/doc.rs
index cabdb4dc..ba848b64 100644
--- a/src/library/structure/doc.rs
+++ b/src/library/structure/doc.rs
@@ -7,7 +7,11 @@ pub struct DocNode(pub StyleVec<PageNode>);
impl DocNode {
/// Layout the document into a sequence of frames, one per page.
- pub fn layout(&self, world: &dyn World, styles: StyleChain) -> TypResult<Vec<Frame>> {
+ pub fn layout(
+ &self,
+ world: &dyn World,
+ styles: StyleChain,
+ ) -> SourceResult<Vec<Frame>> {
let mut frames = vec![];
for (page, map) in self.0.iter() {
let number = 1 + frames.len();
diff --git a/src/library/structure/heading.rs b/src/library/structure/heading.rs
index c177481f..855c0503 100644
--- a/src/library/structure/heading.rs
+++ b/src/library/structure/heading.rs
@@ -60,7 +60,7 @@ impl HeadingNode {
/// Whether the heading is numbered.
pub const NUMBERED: bool = true;
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self {
body: args.expect("body")?,
level: args.named("level")?.unwrap_or(NonZeroUsize::new(1).unwrap()),
@@ -82,7 +82,7 @@ impl Show for HeadingNode {
}
}
- fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> SourceResult<Content> {
Ok(Content::block(self.body.clone()))
}
@@ -91,7 +91,7 @@ impl Show for HeadingNode {
world: &dyn World,
styles: StyleChain,
mut realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
macro_rules! resolve {
($key:expr) => {
styles.get($key).resolve(world, self.level)?
@@ -149,7 +149,7 @@ pub enum Leveled<T> {
impl<T: Cast + Clone> Leveled<T> {
/// Resolve the value based on the level.
- pub fn resolve(&self, world: &dyn World, level: NonZeroUsize) -> TypResult<T> {
+ pub fn resolve(&self, world: &dyn World, level: NonZeroUsize) -> SourceResult<T> {
Ok(match self {
Self::Value(value) => value.clone(),
Self::Mapping(mapping) => mapping(level),
diff --git a/src/library/structure/list.rs b/src/library/structure/list.rs
index e9365cd6..f63374f3 100644
--- a/src/library/structure/list.rs
+++ b/src/library/structure/list.rs
@@ -56,7 +56,7 @@ impl<const L: ListKind> ListNode<L> {
#[property(resolve)]
pub const SPACING: BlockSpacing = Ratio::one().into();
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self {
start: args.named("start")?.unwrap_or(1),
tight: args.named("tight")?.unwrap_or(true),
@@ -100,7 +100,7 @@ impl<const L: ListKind> Show for ListNode<L> {
}
}
- fn realize(&self, world: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, world: &dyn World, styles: StyleChain) -> SourceResult<Content> {
let mut cells = vec![];
let mut number = self.start;
@@ -148,7 +148,7 @@ impl<const L: ListKind> Show for ListNode<L> {
_: &dyn World,
styles: StyleChain,
realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
let mut above = styles.get(Self::ABOVE);
let mut below = styles.get(Self::BELOW);
@@ -211,7 +211,7 @@ impl Label {
world: &dyn World,
kind: ListKind,
number: usize,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
Ok(match self {
Self::Default => match kind {
UNORDERED => Content::Text('•'.into()),
diff --git a/src/library/structure/reference.rs b/src/library/structure/reference.rs
index 22dbec01..5d1dab38 100644
--- a/src/library/structure/reference.rs
+++ b/src/library/structure/reference.rs
@@ -6,7 +6,7 @@ pub struct RefNode(pub EcoString);
#[node(showable)]
impl RefNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self(args.expect("label")?)))
}
}
@@ -22,7 +22,7 @@ impl Show for RefNode {
}
}
- fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> SourceResult<Content> {
Ok(Content::Text(format_eco!("@{}", self.0)))
}
}
diff --git a/src/library/structure/table.rs b/src/library/structure/table.rs
index 08fa5386..f1ca7e03 100644
--- a/src/library/structure/table.rs
+++ b/src/library/structure/table.rs
@@ -30,7 +30,7 @@ impl TableNode {
#[property(resolve, shorthand(around))]
pub const BELOW: Option<BlockSpacing> = Some(Ratio::one().into());
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let columns = args.named("columns")?.unwrap_or_default();
let rows = args.named("rows")?.unwrap_or_default();
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
@@ -72,7 +72,7 @@ impl Show for TableNode {
}
}
- fn realize(&self, world: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, world: &dyn World, styles: StyleChain) -> SourceResult<Content> {
let fill = styles.get(Self::FILL);
let stroke = styles.get(Self::STROKE).map(RawStroke::unwrap_or_default);
let padding = styles.get(Self::PADDING);
@@ -98,7 +98,7 @@ impl Show for TableNode {
Ok(child)
})
- .collect::<TypResult<_>>()?;
+ .collect::<SourceResult<_>>()?;
Ok(Content::block(GridNode {
tracks: self.tracks.clone(),
@@ -113,7 +113,7 @@ impl Show for TableNode {
_: &dyn World,
styles: StyleChain,
realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
Ok(realized.spaced(styles.get(Self::ABOVE), styles.get(Self::BELOW)))
}
}
@@ -129,7 +129,7 @@ pub enum Celled<T> {
impl<T: Cast + Clone> Celled<T> {
/// Resolve the value based on the cell position.
- pub fn resolve(&self, world: &dyn World, x: usize, y: usize) -> TypResult<T> {
+ pub fn resolve(&self, world: &dyn World, x: usize, y: usize) -> SourceResult<T> {
Ok(match self {
Self::Value(value) => value.clone(),
Self::Func(func, span) => {
diff --git a/src/library/text/deco.rs b/src/library/text/deco.rs
index c58148b4..3d030d45 100644
--- a/src/library/text/deco.rs
+++ b/src/library/text/deco.rs
@@ -34,7 +34,7 @@ impl<const L: DecoLine> DecoNode<L> {
/// with the glyphs. Does not apply to strikethrough.
pub const EVADE: bool = true;
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -48,7 +48,7 @@ impl<const L: DecoLine> Show for DecoNode<L> {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, styles: StyleChain) -> SourceResult<Content> {
Ok(self.0.clone().styled(TextNode::DECO, Decoration {
line: L,
stroke: styles.get(Self::STROKE).unwrap_or_default(),
diff --git a/src/library/text/link.rs b/src/library/text/link.rs
index 7d5c3109..f89bbd67 100644
--- a/src/library/text/link.rs
+++ b/src/library/text/link.rs
@@ -18,7 +18,7 @@ impl LinkNode {
/// Whether to underline the link.
pub const UNDERLINE: Smart<bool> = Smart::Auto;
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show({
let dest = args.expect::<Destination>("destination")?;
let body = match dest {
@@ -64,7 +64,7 @@ impl Show for LinkNode {
}
}
- fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> SourceResult<Content> {
Ok(self.body.clone().unwrap_or_else(|| match &self.dest {
Destination::Url(url) => {
let mut text = url.as_str();
@@ -83,7 +83,7 @@ impl Show for LinkNode {
_: &dyn World,
styles: StyleChain,
mut realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
let mut map = StyleMap::new();
map.set(TextNode::LINK, Some(self.dest.clone()));
diff --git a/src/library/text/mod.rs b/src/library/text/mod.rs
index be586874..55b866cb 100644
--- a/src/library/text/mod.rs
+++ b/src/library/text/mod.rs
@@ -128,7 +128,7 @@ impl TextNode {
#[property(skip, fold)]
pub const DECO: Decoration = vec![];
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
// The text constructor is special: It doesn't create a text node.
// Instead, it leaves the passed argument structurally unchanged, but
// styles all text in it.
@@ -422,17 +422,17 @@ impl Fold for Vec<(Tag, u32)> {
}
/// Convert a string or content to lowercase.
-pub fn lower(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn lower(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
case(Case::Lower, args)
}
/// Convert a string or content to uppercase.
-pub fn upper(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn upper(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
case(Case::Upper, args)
}
/// Change the case of text.
-fn case(case: Case, args: &mut Args) -> TypResult<Value> {
+fn case(case: Case, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect("string or content")?;
Ok(match v {
Value::Str(v) => Value::Str(case.apply(&v).into()),
@@ -461,7 +461,7 @@ impl Case {
}
/// Display text in small capitals.
-pub fn smallcaps(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn smallcaps(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let body: Content = args.expect("content")?;
Ok(Value::Content(body.styled(TextNode::SMALLCAPS, true)))
}
@@ -493,7 +493,7 @@ pub struct StrongNode(pub Content);
#[node(showable)]
impl StrongNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -507,7 +507,7 @@ impl Show for StrongNode {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> SourceResult<Content> {
Ok(self.0.clone().styled(TextNode::BOLD, Toggle))
}
}
@@ -518,7 +518,7 @@ pub struct EmphNode(pub Content);
#[node(showable)]
impl EmphNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -532,7 +532,7 @@ impl Show for EmphNode {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, _: &dyn World, _: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, _: StyleChain) -> SourceResult<Content> {
Ok(self.0.clone().styled(TextNode::ITALIC, Toggle))
}
}
diff --git a/src/library/text/par.rs b/src/library/text/par.rs
index e8282ef1..00a1e034 100644
--- a/src/library/text/par.rs
+++ b/src/library/text/par.rs
@@ -49,7 +49,7 @@ impl ParNode {
#[property(resolve)]
pub const LINEBREAKS: Smart<Linebreaks> = Smart::Auto;
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
// The paragraph constructor is special: It doesn't create a paragraph
// node. Instead, it just ensures that the passed content lives is in a
// separate paragraph and styles it.
@@ -67,7 +67,7 @@ impl Layout for ParNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// Collect all text into one string for BiDi analysis.
let (text, segments) = collect(self, &styles);
@@ -170,7 +170,7 @@ pub struct ParbreakNode;
#[node]
impl ParbreakNode {
- fn construct(_: &mut Vm, _: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, _: &mut Args) -> SourceResult<Content> {
Ok(Content::Parbreak)
}
}
@@ -180,7 +180,7 @@ pub struct LinebreakNode;
#[node]
impl LinebreakNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
let justified = args.named("justified")?.unwrap_or(false);
Ok(Content::Linebreak { justified })
}
@@ -502,7 +502,7 @@ fn prepare<'a>(
segments: Vec<(Segment<'a>, StyleChain<'a>)>,
regions: &Regions,
styles: StyleChain<'a>,
-) -> TypResult<Preparation<'a>> {
+) -> SourceResult<Preparation<'a>> {
let bidi = BidiInfo::new(&text, match styles.get(TextNode::DIR) {
Dir::LTR => Some(Level::ltr()),
Dir::RTL => Some(Level::rtl()),
@@ -1025,7 +1025,7 @@ fn stack(
world: &dyn World,
lines: &[Line],
regions: &Regions,
-) -> TypResult<Vec<Frame>> {
+) -> SourceResult<Vec<Frame>> {
// Determine the paragraph's width: Full width of the region if we
// should expand or there's fractional spacing, fit-to-width otherwise.
let mut width = regions.first.x;
@@ -1076,7 +1076,7 @@ fn commit(
line: &Line,
regions: &Regions,
width: Length,
-) -> TypResult<Frame> {
+) -> SourceResult<Frame> {
let mut remaining = width - line.width;
let mut offset = Length::zero();
diff --git a/src/library/text/raw.rs b/src/library/text/raw.rs
index c729fa40..5bce2a90 100644
--- a/src/library/text/raw.rs
+++ b/src/library/text/raw.rs
@@ -35,7 +35,7 @@ impl RawNode {
#[property(resolve, shorthand(around))]
pub const BELOW: Option<BlockSpacing> = Some(Ratio::one().into());
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self {
text: args.expect("text")?,
block: args.named("block")?.unwrap_or(false),
@@ -59,7 +59,7 @@ impl Show for RawNode {
}
}
- fn realize(&self, _: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, _: &dyn World, styles: StyleChain) -> SourceResult<Content> {
let lang = styles.get(Self::LANG).as_ref().map(|s| s.to_lowercase());
let foreground = THEME
.settings
@@ -114,7 +114,7 @@ impl Show for RawNode {
_: &dyn World,
styles: StyleChain,
mut realized: Content,
- ) -> TypResult<Content> {
+ ) -> SourceResult<Content> {
let mut map = StyleMap::new();
map.set_family(styles.get(Self::FAMILY).clone(), styles);
map.set(TextNode::OVERHANG, false);
diff --git a/src/library/text/repeat.rs b/src/library/text/repeat.rs
index c2a0de70..78a21069 100644
--- a/src/library/text/repeat.rs
+++ b/src/library/text/repeat.rs
@@ -6,7 +6,7 @@ pub struct RepeatNode(pub LayoutNode);
#[node]
impl RepeatNode {
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::inline(Self(args.expect("body")?)))
}
}
@@ -17,7 +17,7 @@ impl Layout for RepeatNode {
world: &dyn World,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult<Vec<Frame>> {
+ ) -> SourceResult<Vec<Frame>> {
// The actual repeating happens directly in the paragraph.
self.0.layout(world, regions, styles)
}
diff --git a/src/library/text/shaping.rs b/src/library/text/shaping.rs
index 6e505702..c1d0341b 100644
--- a/src/library/text/shaping.rs
+++ b/src/library/text/shaping.rs
@@ -165,7 +165,7 @@ impl<'a> ShapedText<'a> {
if let Some(font) = world
.book()
.select(family, self.variant)
- .and_then(|id| world.font(id).ok())
+ .and_then(|id| world.font(id))
{
expand(&font);
break;
@@ -223,7 +223,7 @@ impl<'a> ShapedText<'a> {
let font = world
.book()
.select(family, self.variant)
- .and_then(|id| world.font(id).ok())?;
+ .and_then(|id| world.font(id))?;
let ttf = font.ttf();
let glyph_id = ttf.glyph_index('-')?;
let x_advance = font.to_em(ttf.glyph_hor_advance(glyph_id)?);
@@ -371,7 +371,7 @@ fn shape_segment<'a>(
let book = ctx.world.book();
let mut selection = families.find_map(|family| {
book.select(family, ctx.variant)
- .and_then(|id| ctx.world.font(id).ok())
+ .and_then(|id| ctx.world.font(id))
.filter(|font| !ctx.used.contains(font))
});
@@ -380,7 +380,7 @@ fn shape_segment<'a>(
let first = ctx.used.first().map(Font::info);
selection = book
.select_fallback(first, ctx.variant, text)
- .and_then(|id| ctx.world.font(id).ok())
+ .and_then(|id| ctx.world.font(id))
.filter(|font| !ctx.used.contains(font));
}
diff --git a/src/library/text/shift.rs b/src/library/text/shift.rs
index 5da36da1..b359c5ed 100644
--- a/src/library/text/shift.rs
+++ b/src/library/text/shift.rs
@@ -28,7 +28,7 @@ impl<const S: ScriptKind> ShiftNode<S> {
/// The font size for synthetic sub- and superscripts.
pub const SIZE: TextSize = TextSize(Em::new(0.6).into());
- fn construct(_: &mut Vm, args: &mut Args) -> TypResult<Content> {
+ fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
@@ -42,7 +42,7 @@ impl<const S: ScriptKind> Show for ShiftNode<S> {
dict! { "body" => Value::Content(self.0.clone()) }
}
- fn realize(&self, world: &dyn World, styles: StyleChain) -> TypResult<Content> {
+ fn realize(&self, world: &dyn World, styles: StyleChain) -> SourceResult<Content> {
let mut transformed = None;
if styles.get(Self::TYPOGRAPHIC) {
if let Some(text) = search_text(&self.0, S) {
@@ -96,7 +96,7 @@ fn is_shapable(world: &dyn World, text: &str, styles: StyleChain) -> bool {
if let Some(font) = world
.book()
.select(family.as_str(), variant(styles))
- .and_then(|id| world.font(id).ok())
+ .and_then(|id| world.font(id))
{
return text.chars().all(|c| font.ttf().glyph_index(c).is_some());
}
diff --git a/src/library/utility/color.rs b/src/library/utility/color.rs
index a7d55d1c..a5a5704d 100644
--- a/src/library/utility/color.rs
+++ b/src/library/utility/color.rs
@@ -3,13 +3,13 @@ use std::str::FromStr;
use crate::library::prelude::*;
/// Create a grayscale color.
-pub fn luma(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn luma(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Component(luma) = args.expect("gray component")?;
Ok(Value::Color(LumaColor::new(luma).into()))
}
/// Create an RGB(A) color.
-pub fn rgb(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn rgb(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
Ok(Value::Color(
if let Some(string) = args.find::<Spanned<EcoString>>()? {
match RgbaColor::from_str(&string.v) {
@@ -27,7 +27,7 @@ pub fn rgb(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// Create a CMYK color.
-pub fn cmyk(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn cmyk(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let RatioComponent(c) = args.expect("cyan component")?;
let RatioComponent(m) = args.expect("magenta component")?;
let RatioComponent(y) = args.expect("yellow component")?;
diff --git a/src/library/utility/data.rs b/src/library/utility/data.rs
index 59f3d351..1ae8949a 100644
--- a/src/library/utility/data.rs
+++ b/src/library/utility/data.rs
@@ -1,30 +1,43 @@
+use std::fmt::Write;
+
use crate::library::prelude::*;
/// Read structured data from a CSV file.
-pub fn csv(vm: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn csv(vm: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v: path, span } =
args.expect::<Spanned<EcoString>>("path to csv file")?;
let path = vm.locate(&path).at(span)?;
- let try_load = || -> io::Result<Value> {
- let data = vm.world.file(&path)?;
+ let data = vm.world.file(&path).at(span)?;
- let mut builder = csv::ReaderBuilder::new();
- builder.has_headers(false);
+ let mut builder = csv::ReaderBuilder::new();
+ builder.has_headers(false);
- let mut reader = builder.from_reader(data.as_slice());
- let mut vec = vec![];
+ let mut reader = builder.from_reader(data.as_slice());
+ let mut vec = vec![];
- for result in reader.records() {
- vec.push(Value::Array(
- result?.iter().map(|field| Value::Str(field.into())).collect(),
- ))
- }
+ for result in reader.records() {
+ let row = result.map_err(format_csv_error).at(span)?;
+ let array = row.iter().map(|field| Value::Str(field.into())).collect();
+ vec.push(Value::Array(array))
+ }
- Ok(Value::Array(Array::from_vec(vec)))
- };
+ Ok(Value::Array(Array::from_vec(vec)))
+}
- try_load()
- .map_err(|err| failed_to_load("csv file", &path, err))
- .at(span)
+/// Format the user-facing CSV error message.
+fn format_csv_error(error: csv::Error) -> String {
+ match error.kind() {
+ csv::ErrorKind::Utf8 { .. } => "file is not valid utf-8".into(),
+ csv::ErrorKind::UnequalLengths { pos, expected_len, len } => {
+ let mut msg = format!(
+ "failed to parse csv file: found {len} instead of {expected_len} fields"
+ );
+ if let Some(pos) = pos {
+ write!(msg, " in line {}", pos.line()).unwrap();
+ }
+ msg
+ }
+ _ => "failed to parse csv file".into(),
+ }
}
diff --git a/src/library/utility/math.rs b/src/library/utility/math.rs
index 47648282..7c3af490 100644
--- a/src/library/utility/math.rs
+++ b/src/library/utility/math.rs
@@ -3,7 +3,7 @@ use std::cmp::Ordering;
use crate::library::prelude::*;
/// Convert a value to an integer.
-pub fn int(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn int(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect("value")?;
Ok(Value::Int(match v {
Value::Bool(v) => v as i64,
@@ -18,7 +18,7 @@ pub fn int(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// Convert a value to a float.
-pub fn float(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn float(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect("value")?;
Ok(Value::Float(match v {
Value::Int(v) => v as f64,
@@ -32,7 +32,7 @@ pub fn float(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// The absolute value of a numeric value.
-pub fn abs(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn abs(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect("numeric value")?;
Ok(match v {
Value::Int(v) => Value::Int(v.abs()),
@@ -48,17 +48,17 @@ pub fn abs(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// The minimum of a sequence of values.
-pub fn min(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn min(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
minmax(args, Ordering::Less)
}
/// The maximum of a sequence of values.
-pub fn max(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn max(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
minmax(args, Ordering::Greater)
}
/// Find the minimum or maximum of a sequence of values.
-fn minmax(args: &mut Args, goal: Ordering) -> TypResult<Value> {
+fn minmax(args: &mut Args, goal: Ordering) -> SourceResult<Value> {
let mut extremum = args.expect::<Value>("value")?;
for Spanned { v, span } in args.all::<Spanned<Value>>()? {
match v.partial_cmp(&extremum) {
@@ -79,17 +79,17 @@ fn minmax(args: &mut Args, goal: Ordering) -> TypResult<Value> {
}
/// Whether an integer is even.
-pub fn even(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn even(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
Ok(Value::Bool(args.expect::<i64>("integer")? % 2 == 0))
}
/// Whether an integer is odd.
-pub fn odd(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn odd(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
Ok(Value::Bool(args.expect::<i64>("integer")? % 2 != 0))
}
/// The modulo of two numbers.
-pub fn mod_(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn mod_(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v: v1, span: span1 } = args.expect("integer or float")?;
let Spanned { v: v2, span: span2 } = args.expect("integer or float")?;
@@ -119,7 +119,7 @@ pub fn mod_(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// Create a sequence of numbers.
-pub fn range(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn range(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let first = args.expect::<i64>("end")?;
let (start, end) = match args.eat::<i64>()? {
Some(second) => (first, second),
diff --git a/src/library/utility/mod.rs b/src/library/utility/mod.rs
index 40a107ba..3fc413f7 100644
--- a/src/library/utility/mod.rs
+++ b/src/library/utility/mod.rs
@@ -15,12 +15,12 @@ use crate::library::prelude::*;
use crate::source::Source;
/// The name of a value's type.
-pub fn type_(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn type_(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
Ok(args.expect::<Value>("value")?.type_name().into())
}
/// Ensure that a condition is fulfilled.
-pub fn assert(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn assert(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect::<Spanned<bool>>("condition")?;
if !v {
bail!(span, "assertion failed");
@@ -29,7 +29,7 @@ pub fn assert(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// Evaluate a string as Typst markup.
-pub fn eval(vm: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn eval(vm: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v: text, span } = args.expect::<Spanned<String>>("source")?;
// Parse the source and set a synthetic span for all nodes.
@@ -44,7 +44,7 @@ pub fn eval(vm: &mut Vm, args: &mut Args) -> TypResult<Value> {
// Handle control flow.
if let Some(flow) = sub.flow {
- return Err(flow.forbidden());
+ bail!(flow.forbidden());
}
Ok(Value::Content(result?))
diff --git a/src/library/utility/string.rs b/src/library/utility/string.rs
index d825d84b..91a990a9 100644
--- a/src/library/utility/string.rs
+++ b/src/library/utility/string.rs
@@ -2,12 +2,12 @@ use crate::eval::Regex;
use crate::library::prelude::*;
/// The string representation of a value.
-pub fn repr(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn repr(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
Ok(args.expect::<Value>("value")?.repr().into())
}
/// Convert a value to a string.
-pub fn str(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn str(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect("value")?;
Ok(Value::Str(match v {
Value::Int(v) => format_str!("{}", v),
@@ -18,33 +18,33 @@ pub fn str(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
}
/// Create blind text.
-pub fn lorem(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn lorem(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let words: usize = args.expect("number of words")?;
Ok(Value::Str(lipsum::lipsum(words).into()))
}
/// Create a regular expression.
-pub fn regex(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn regex(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
let Spanned { v, span } = args.expect::<Spanned<EcoString>>("regular expression")?;
Ok(Regex::new(&v).at(span)?.into())
}
/// Converts an integer into one or multiple letters.
-pub fn letter(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn letter(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
numbered(Numbering::Letter, args)
}
/// Converts an integer into a roman numeral.
-pub fn roman(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn roman(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
numbered(Numbering::Roman, args)
}
/// Convert a number into a symbol.
-pub fn symbol(_: &mut Vm, args: &mut Args) -> TypResult<Value> {
+pub fn symbol(_: &mut Vm, args: &mut Args) -> SourceResult<Value> {
numbered(Numbering::Symbol, args)
}
-fn numbered(numbering: Numbering, args: &mut Args) -> TypResult<Value> {
+fn numbered(numbering: Numbering, args: &mut Args) -> SourceResult<Value> {
let n = args.expect::<usize>("non-negative integer")?;
Ok(Value::Str(numbering.apply(n).into()))
}