mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Unified file loading errors
This commit is contained in:
parent
0dacb2d151
commit
7fb19d5ef8
12
src/diag.rs
12
src/diag.rs
@ -1,6 +1,8 @@
|
|||||||
//! Diagnostics.
|
//! Diagnostics.
|
||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::syntax::{Span, Spanned};
|
use crate::syntax::{Span, Spanned};
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
@ -134,3 +136,13 @@ pub fn with_alternative(msg: String, alt: &str) -> String {
|
|||||||
msg
|
msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format a file loading failure.
|
||||||
|
pub fn failed_to_load(target: &str, path: &Path, error: io::Error) -> String {
|
||||||
|
match error.kind() {
|
||||||
|
io::ErrorKind::NotFound => {
|
||||||
|
format!("file not found (searched at {})", path.display())
|
||||||
|
}
|
||||||
|
_ => format!("failed to load {target} ({error})"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -967,12 +967,7 @@ impl Eval for IncludeExpr {
|
|||||||
fn import(vm: &mut Machine, path: &str, span: Span) -> TypResult<Module> {
|
fn import(vm: &mut Machine, path: &str, span: Span) -> TypResult<Module> {
|
||||||
// Load the source file.
|
// Load the source file.
|
||||||
let full = vm.locate(&path).at(span)?;
|
let full = vm.locate(&path).at(span)?;
|
||||||
let id = vm.ctx.sources.load(&full).map_err(|err| match err.kind() {
|
let id = vm.ctx.sources.load(&full).at(span)?;
|
||||||
std::io::ErrorKind::NotFound => {
|
|
||||||
error!(span, "file not found (searched at {})", full.display())
|
|
||||||
}
|
|
||||||
_ => error!(span, "failed to load source file ({})", err),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Prevent cyclic importing.
|
// Prevent cyclic importing.
|
||||||
if vm.route.contains(&id) {
|
if vm.route.contains(&id) {
|
||||||
|
32
src/image.rs
32
src/image.rs
@ -10,6 +10,7 @@ use std::sync::Arc;
|
|||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use image::{DynamicImage, ImageFormat};
|
use image::{DynamicImage, ImageFormat};
|
||||||
|
|
||||||
|
use crate::diag::{failed_to_load, StrResult};
|
||||||
use crate::loading::{FileHash, Loader};
|
use crate::loading::{FileHash, Loader};
|
||||||
|
|
||||||
/// A unique identifier for a loaded image.
|
/// A unique identifier for a loaded image.
|
||||||
@ -60,19 +61,24 @@ impl ImageStore {
|
|||||||
|
|
||||||
/// Load and decode an image file from a path relative to the compilation
|
/// Load and decode an image file from a path relative to the compilation
|
||||||
/// environment's root.
|
/// environment's root.
|
||||||
pub fn load(&mut self, path: &Path) -> io::Result<ImageId> {
|
pub fn load(&mut self, path: &Path) -> StrResult<ImageId> {
|
||||||
let hash = self.loader.resolve(path)?;
|
let mut try_load = || -> io::Result<ImageId> {
|
||||||
Ok(*match self.files.entry(hash) {
|
let hash = self.loader.resolve(path)?;
|
||||||
Entry::Occupied(entry) => entry.into_mut(),
|
Ok(*match self.files.entry(hash) {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Occupied(entry) => entry.into_mut(),
|
||||||
let buffer = self.loader.load(path)?;
|
Entry::Vacant(entry) => {
|
||||||
let ext = path.extension().and_then(OsStr::to_str).unwrap_or_default();
|
let buffer = self.loader.load(path)?;
|
||||||
let image = Image::parse(&buffer, ext)?;
|
let ext =
|
||||||
let id = ImageId(self.images.len() as u32);
|
path.extension().and_then(OsStr::to_str).unwrap_or_default();
|
||||||
self.images.push(image);
|
let image = Image::parse(&buffer, ext)?;
|
||||||
entry.insert(id)
|
let id = ImageId(self.images.len() as u32);
|
||||||
}
|
self.images.push(image);
|
||||||
})
|
entry.insert(id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
try_load().map_err(|err| failed_to_load("image", path, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,7 @@ impl ImageNode {
|
|||||||
args.expect::<Spanned<EcoString>>("path to image file")?;
|
args.expect::<Spanned<EcoString>>("path to image file")?;
|
||||||
|
|
||||||
let full = vm.locate(&path).at(span)?;
|
let full = vm.locate(&path).at(span)?;
|
||||||
let id = vm.ctx.images.load(&full).map_err(|err| match err.kind() {
|
let id = vm.ctx.images.load(&full).at(span)?;
|
||||||
std::io::ErrorKind::NotFound => {
|
|
||||||
error!(span, "file not found (searched at {})", full.display())
|
|
||||||
}
|
|
||||||
_ => error!(span, "failed to load image ({})", err),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let width = args.named("width")?;
|
let width = args.named("width")?;
|
||||||
let height = args.named("height")?;
|
let height = args.named("height")?;
|
||||||
|
|
||||||
|
@ -206,10 +206,7 @@ fn typeset(command: TypesetCommand) -> StrResult<()> {
|
|||||||
let mut ctx = Context::new(Arc::new(loader), config.build());
|
let mut ctx = Context::new(Arc::new(loader), config.build());
|
||||||
|
|
||||||
// Load the source file.
|
// Load the source file.
|
||||||
let id = ctx
|
let id = ctx.sources.load(&command.input)?;
|
||||||
.sources
|
|
||||||
.load(&command.input)
|
|
||||||
.map_err(|_| "failed to load source file")?;
|
|
||||||
|
|
||||||
// Typeset.
|
// Typeset.
|
||||||
match typst::typeset(&mut ctx, id) {
|
match typst::typeset(&mut ctx, id) {
|
||||||
|
@ -8,7 +8,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
|
|
||||||
use crate::diag::TypResult;
|
use crate::diag::{failed_to_load, StrResult, TypResult};
|
||||||
use crate::loading::{FileHash, Loader};
|
use crate::loading::{FileHash, Loader};
|
||||||
use crate::parse::{is_newline, parse, reparse};
|
use crate::parse::{is_newline, parse, reparse};
|
||||||
use crate::syntax::ast::Markup;
|
use crate::syntax::ast::Markup;
|
||||||
@ -74,19 +74,22 @@ impl SourceStore {
|
|||||||
///
|
///
|
||||||
/// If there already exists a source file for this path, it is
|
/// If there already exists a source file for this path, it is
|
||||||
/// [replaced](SourceFile::replace).
|
/// [replaced](SourceFile::replace).
|
||||||
pub fn load(&mut self, path: impl AsRef<Path>) -> io::Result<SourceId> {
|
pub fn load(&mut self, path: &Path) -> StrResult<SourceId> {
|
||||||
let path = path.as_ref();
|
let mut try_load = || -> io::Result<SourceId> {
|
||||||
let hash = self.loader.resolve(path)?;
|
let hash = self.loader.resolve(path)?;
|
||||||
if let Some(&id) = self.files.get(&hash) {
|
if let Some(&id) = self.files.get(&hash) {
|
||||||
return Ok(id);
|
return Ok(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.loader.load(path)?;
|
let data = self.loader.load(path)?;
|
||||||
let src = String::from_utf8(data).map_err(|_| {
|
let src = String::from_utf8(data).map_err(|_| {
|
||||||
io::Error::new(io::ErrorKind::InvalidData, "file is not valid utf-8")
|
io::Error::new(io::ErrorKind::InvalidData, "file is not valid utf-8")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(self.provide(path, src))
|
Ok(self.provide(path, src))
|
||||||
|
};
|
||||||
|
|
||||||
|
try_load().map_err(|err| failed_to_load("source file", path, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Directly provide a source file.
|
/// Directly provide a source file.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user