summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-11-10 13:35:49 +0100
committerLaurenz <laurmaedje@gmail.com>2024-11-13 10:21:40 +0100
commit5625914872b2824388ce65f3fb184d913f29cbff (patch)
treee8ca84034dea217686ed0f4b179e1e391a3a46e3 /crates
parent6c22ba1cbd21dae100f25b0268389f993f075626 (diff)
Simplify import handling
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-eval/src/import.rs94
-rw-r--r--crates/typst-ide/src/analyze.rs35
-rw-r--r--crates/typst-ide/src/utils.rs25
3 files changed, 79 insertions, 75 deletions
diff --git a/crates/typst-eval/src/import.rs b/crates/typst-eval/src/import.rs
index 316fbf87..aee632bf 100644
--- a/crates/typst-eval/src/import.rs
+++ b/crates/typst-eval/src/import.rs
@@ -3,6 +3,7 @@ use ecow::{eco_format, eco_vec, EcoString};
use typst_library::diag::{
bail, error, warning, At, FileError, SourceResult, Trace, Tracepoint,
};
+use typst_library::engine::Engine;
use typst_library::foundations::{Content, Module, Value};
use typst_library::World;
use typst_syntax::ast::{self, AstNode};
@@ -28,8 +29,16 @@ impl Eval for ast::ModuleImport<'_> {
}
}
Value::Type(_) => {}
- other => {
- source = Value::Module(import(vm, other.clone(), source_span, true)?);
+ Value::Module(_) => {}
+ Value::Str(path) => {
+ source = Value::Module(import(&mut vm.engine, path, source_span)?);
+ }
+ v => {
+ bail!(
+ source_span,
+ "expected path, module, function, or type, found {}",
+ v.ty()
+ )
}
}
@@ -139,43 +148,34 @@ impl Eval for ast::ModuleInclude<'_> {
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.source().span();
let source = self.source().eval(vm)?;
- let module = import(vm, source, span, false)?;
+ let module = match source {
+ Value::Str(path) => import(&mut vm.engine, &path, span)?,
+ Value::Module(module) => module,
+ v => bail!(span, "expected path or module, found {}", v.ty()),
+ };
Ok(module.content())
}
}
-/// Process an import of a module relative to the current location.
-pub fn import(
- vm: &mut Vm,
- source: Value,
- span: Span,
- allow_scopes: bool,
-) -> SourceResult<Module> {
- let path = match source {
- Value::Str(path) => path,
- Value::Module(module) => return Ok(module),
- v if allow_scopes => {
- bail!(span, "expected path, module, function, or type, found {}", v.ty())
- }
- v => bail!(span, "expected path or module, found {}", v.ty()),
- };
-
- // Handle package and file imports.
- let path = path.as_str();
- if path.starts_with('@') {
- let spec = path.parse::<PackageSpec>().at(span)?;
- import_package(vm, spec, span)
+/// Process an import of a package or file relative to the current location.
+pub fn import(engine: &mut Engine, from: &str, span: Span) -> SourceResult<Module> {
+ if from.starts_with('@') {
+ let spec = from.parse::<PackageSpec>().at(span)?;
+ import_package(engine, spec, span)
} else {
- import_file(vm, path, span)
+ import_file(engine, from, span)
}
}
/// Import an external package.
-fn import_package(vm: &mut Vm, spec: PackageSpec, span: Span) -> SourceResult<Module> {
+fn import_package(
+ engine: &mut Engine,
+ spec: PackageSpec,
+ span: Span,
+) -> SourceResult<Module> {
// Evaluate the manifest.
- let world = vm.world();
let manifest_id = FileId::new(Some(spec.clone()), VirtualPath::new("typst.toml"));
- let bytes = world.file(manifest_id).at(span)?;
+ let bytes = engine.world.file(manifest_id).at(span)?;
let string = std::str::from_utf8(&bytes).map_err(FileError::from).at(span)?;
let manifest: PackageManifest = toml::from_str(string)
.map_err(|err| eco_format!("package manifest is malformed ({})", err.message()))
@@ -184,47 +184,47 @@ fn import_package(vm: &mut Vm, spec: PackageSpec, span: Span) -> SourceResult<Mo
// Evaluate the entry point.
let entrypoint_id = manifest_id.join(&manifest.package.entrypoint);
- let source = world.source(entrypoint_id).at(span)?;
+ let source = engine.world.source(entrypoint_id).at(span)?;
// Prevent cyclic importing.
- if vm.engine.route.contains(source.id()) {
+ if engine.route.contains(source.id()) {
bail!(span, "cyclic import");
}
let point = || Tracepoint::Import;
Ok(eval(
- vm.engine.routines,
- vm.engine.world,
- vm.engine.traced,
- TrackedMut::reborrow_mut(&mut vm.engine.sink),
- vm.engine.route.track(),
+ engine.routines,
+ engine.world,
+ engine.traced,
+ TrackedMut::reborrow_mut(&mut engine.sink),
+ engine.route.track(),
&source,
)
- .trace(world, point, span)?
+ .trace(engine.world, point, span)?
.with_name(manifest.package.name))
}
-/// Import a file from a path.
-fn import_file(vm: &mut Vm, path: &str, span: Span) -> SourceResult<Module> {
+/// Import a file from a path. The path is resolved relative to the given
+/// `span`.
+fn import_file(engine: &mut Engine, path: &str, span: Span) -> SourceResult<Module> {
// Load the source file.
- let world = vm.world();
let id = span.resolve_path(path).at(span)?;
- let source = world.source(id).at(span)?;
+ let source = engine.world.source(id).at(span)?;
// Prevent cyclic importing.
- if vm.engine.route.contains(source.id()) {
+ if engine.route.contains(source.id()) {
bail!(span, "cyclic import");
}
// Evaluate the file.
let point = || Tracepoint::Import;
eval(
- vm.engine.routines,
- vm.engine.world,
- vm.engine.traced,
- TrackedMut::reborrow_mut(&mut vm.engine.sink),
- vm.engine.route.track(),
+ engine.routines,
+ engine.world,
+ engine.traced,
+ TrackedMut::reborrow_mut(&mut engine.sink),
+ engine.route.track(),
&source,
)
- .trace(world, point, span)
+ .trace(engine.world, point, span)
}
diff --git a/crates/typst-ide/src/analyze.rs b/crates/typst-ide/src/analyze.rs
index ce7fe478..5e3dfd70 100644
--- a/crates/typst-ide/src/analyze.rs
+++ b/crates/typst-ide/src/analyze.rs
@@ -1,11 +1,8 @@
use comemo::Track;
use ecow::{eco_vec, EcoString, EcoVec};
-use typst::engine::{Engine, Route, Sink, Traced};
-use typst::foundations::{Context, Label, Scopes, Styles, Value};
-use typst::introspection::Introspector;
+use typst::foundations::{Label, Styles, Value};
use typst::model::{BibliographyElem, Document};
-use typst::syntax::{ast, LinkedNode, Span, SyntaxKind};
-use typst_eval::Vm;
+use typst::syntax::{ast, LinkedNode, SyntaxKind};
use crate::IdeWorld;
@@ -46,7 +43,7 @@ pub fn analyze_expr(
eco_vec![(val, None)]
}
-/// Try to load a module from the current source file.
+/// Tries to load a module from the given `source` node.
pub fn analyze_import(world: &dyn IdeWorld, source: &LinkedNode) -> Option<Value> {
// Use span in the node for resolving imports with relative paths.
let source_span = source.span();
@@ -55,29 +52,11 @@ pub fn analyze_import(world: &dyn IdeWorld, source: &LinkedNode) -> Option<Value
return Some(source);
}
- let introspector = Introspector::default();
- let traced = Traced::default();
- let mut sink = Sink::new();
- let engine = Engine {
- routines: &typst::ROUTINES,
- world: world.upcast().track(),
- introspector: introspector.track(),
- traced: traced.track(),
- sink: sink.track_mut(),
- route: Route::default(),
- };
-
- let context = Context::none();
- let mut vm = Vm::new(
- engine,
- context.track(),
- Scopes::new(Some(world.library())),
- Span::detached(),
- );
+ let Value::Str(path) = source else { return None };
- typst_eval::import(&mut vm, source, source_span, true)
- .ok()
- .map(Value::Module)
+ crate::utils::with_engine(world, |engine| {
+ typst_eval::import(engine, &path, source_span).ok().map(Value::Module)
+ })
}
/// Find all labels and details for them.
diff --git a/crates/typst-ide/src/utils.rs b/crates/typst-ide/src/utils.rs
index e5252d91..903fb2f3 100644
--- a/crates/typst-ide/src/utils.rs
+++ b/crates/typst-ide/src/utils.rs
@@ -1,8 +1,33 @@
use std::fmt::Write;
+use comemo::Track;
use ecow::{eco_format, EcoString};
+use typst::engine::{Engine, Route, Sink, Traced};
+use typst::introspection::Introspector;
use typst::text::{FontInfo, FontStyle};
+use crate::IdeWorld;
+
+/// Create a temporary engine and run a task on it.
+pub fn with_engine<F, T>(world: &dyn IdeWorld, f: F) -> T
+where
+ F: FnOnce(&mut Engine) -> T,
+{
+ let introspector = Introspector::default();
+ let traced = Traced::default();
+ let mut sink = Sink::new();
+ let mut engine = Engine {
+ routines: &typst::ROUTINES,
+ world: world.upcast().track(),
+ introspector: introspector.track(),
+ traced: traced.track(),
+ sink: sink.track_mut(),
+ route: Route::default(),
+ };
+
+ f(&mut engine)
+}
+
/// Extract the first sentence of plain text of a piece of documentation.
///
/// Removes Markdown formatting.