summaryrefslogtreecommitdiff
path: root/crates/typst-ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/typst-ide')
-rw-r--r--crates/typst-ide/src/analyze.rs10
-rw-r--r--crates/typst-ide/src/complete.rs19
-rw-r--r--crates/typst-ide/src/jump.rs18
-rw-r--r--crates/typst-ide/src/tooltip.rs15
4 files changed, 33 insertions, 29 deletions
diff --git a/crates/typst-ide/src/analyze.rs b/crates/typst-ide/src/analyze.rs
index 8c5117f7..e78f0c12 100644
--- a/crates/typst-ide/src/analyze.rs
+++ b/crates/typst-ide/src/analyze.rs
@@ -4,8 +4,7 @@ use typst::engine::{Engine, Route};
use typst::eval::{Tracer, Vm};
use typst::foundations::{Label, Scopes, Value};
use typst::introspection::{Introspector, Locator};
-use typst::layout::Frame;
-use typst::model::BibliographyElem;
+use typst::model::{BibliographyElem, Document};
use typst::syntax::{ast, LinkedNode, Span, SyntaxKind};
use typst::World;
@@ -75,12 +74,11 @@ pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option<Value> {
/// - All labels and descriptions for them, if available
/// - A split offset: All labels before this offset belong to nodes, all after
/// belong to a bibliography.
-pub fn analyze_labels(frames: &[Frame]) -> (Vec<(Label, Option<EcoString>)>, usize) {
+pub fn analyze_labels(document: &Document) -> (Vec<(Label, Option<EcoString>)>, usize) {
let mut output = vec![];
- let introspector = Introspector::new(frames);
// Labels in the document.
- for elem in introspector.all() {
+ for elem in document.introspector.all() {
let Some(label) = elem.label() else { continue };
let details = elem
.get_by_name("caption")
@@ -98,7 +96,7 @@ pub fn analyze_labels(frames: &[Frame]) -> (Vec<(Label, Option<EcoString>)>, usi
let split = output.len();
// Bibliography keys.
- for (key, detail) in BibliographyElem::keys(introspector.track()) {
+ for (key, detail) in BibliographyElem::keys(document.introspector.track()) {
output.push((Label::new(&key), detail));
}
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs
index 6e94ee6a..8acf1540 100644
--- a/crates/typst-ide/src/complete.rs
+++ b/crates/typst-ide/src/complete.rs
@@ -8,7 +8,7 @@ use typst::foundations::{
fields_on, format_str, mutable_methods_on, repr, AutoValue, CastInfo, Func, Label,
NoneValue, Repr, Scope, Type, Value,
};
-use typst::layout::Frame;
+use typst::model::Document;
use typst::syntax::{
ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind,
};
@@ -27,14 +27,18 @@ use crate::{plain_docs_sentence, summarize_font_family};
///
/// When `explicit` is `true`, the user requested the completion by pressing
/// control and space or something similar.
+///
+/// Passing a `document` (from a previous compilation) is optional, but enhances
+/// the autocompletions. Label completions, for instance, are only generated
+/// when the document is available.
pub fn autocomplete(
world: &dyn World,
- frames: &[Frame],
+ document: Option<&Document>,
source: &Source,
cursor: usize,
explicit: bool,
) -> Option<(usize, Vec<Completion>)> {
- let mut ctx = CompletionContext::new(world, frames, source, cursor, explicit)?;
+ let mut ctx = CompletionContext::new(world, document, source, cursor, explicit)?;
let _ = complete_comments(&mut ctx)
|| complete_field_accesses(&mut ctx)
@@ -966,7 +970,7 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) {
/// Context for autocompletion.
struct CompletionContext<'a> {
world: &'a (dyn World + 'a),
- frames: &'a [Frame],
+ document: Option<&'a Document>,
global: &'a Scope,
math: &'a Scope,
text: &'a str,
@@ -984,7 +988,7 @@ impl<'a> CompletionContext<'a> {
/// Create a new autocompletion context.
fn new(
world: &'a (dyn World + 'a),
- frames: &'a [Frame],
+ document: Option<&'a Document>,
source: &'a Source,
cursor: usize,
explicit: bool,
@@ -994,7 +998,7 @@ impl<'a> CompletionContext<'a> {
let leaf = LinkedNode::new(source.root()).leaf_at(cursor)?;
Some(Self {
world,
- frames,
+ document,
global: library.global.scope(),
math: library.math.scope(),
text,
@@ -1094,7 +1098,8 @@ impl<'a> CompletionContext<'a> {
/// Add completions for labels and references.
fn label_completions(&mut self) {
- let (labels, split) = analyze_labels(self.frames);
+ let Some(document) = self.document else { return };
+ let (labels, split) = analyze_labels(document);
let head = &self.text[..self.from];
let at = head.ends_with('@');
diff --git a/crates/typst-ide/src/jump.rs b/crates/typst-ide/src/jump.rs
index 700f475f..8612ffc3 100644
--- a/crates/typst-ide/src/jump.rs
+++ b/crates/typst-ide/src/jump.rs
@@ -1,9 +1,9 @@
use std::num::NonZeroUsize;
use ecow::EcoString;
-use typst::introspection::{Introspector, Meta};
+use typst::introspection::Meta;
use typst::layout::{Frame, FrameItem, Point, Position, Size};
-use typst::model::Destination;
+use typst::model::{Destination, Document};
use typst::syntax::{FileId, LinkedNode, Source, Span, SyntaxKind};
use typst::visualize::Geometry;
use typst::World;
@@ -31,12 +31,10 @@ impl Jump {
/// Determine where to jump to based on a click in a frame.
pub fn jump_from_click(
world: &dyn World,
- frames: &[Frame],
+ document: &Document,
frame: &Frame,
click: Point,
) -> Option<Jump> {
- let mut introspector = None;
-
// Try to find a link first.
for (pos, item) in frame.items() {
if let FrameItem::Meta(Meta::Link(dest), size) = item {
@@ -44,11 +42,9 @@ pub fn jump_from_click(
return Some(match dest {
Destination::Url(url) => Jump::Url(url.clone()),
Destination::Position(pos) => Jump::Position(*pos),
- Destination::Location(loc) => Jump::Position(
- introspector
- .get_or_insert_with(|| Introspector::new(frames))
- .position(*loc),
- ),
+ Destination::Location(loc) => {
+ Jump::Position(document.introspector.position(*loc))
+ }
});
}
}
@@ -60,7 +56,7 @@ pub fn jump_from_click(
FrameItem::Group(group) => {
// TODO: Handle transformation.
if let Some(span) =
- jump_from_click(world, frames, &group.frame, click - pos)
+ jump_from_click(world, document, &group.frame, click - pos)
{
return Some(span);
}
diff --git a/crates/typst-ide/src/tooltip.rs b/crates/typst-ide/src/tooltip.rs
index 4f079166..67614b9e 100644
--- a/crates/typst-ide/src/tooltip.rs
+++ b/crates/typst-ide/src/tooltip.rs
@@ -4,7 +4,8 @@ use ecow::{eco_format, EcoString};
use if_chain::if_chain;
use typst::eval::{CapturesVisitor, Tracer};
use typst::foundations::{repr, CastInfo, Repr, Value};
-use typst::layout::{Frame, Length};
+use typst::layout::Length;
+use typst::model::Document;
use typst::syntax::{ast, LinkedNode, Source, SyntaxKind};
use typst::util::{round_2, Numeric};
use typst::World;
@@ -13,9 +14,13 @@ use crate::analyze::{analyze_expr, analyze_labels};
use crate::{plain_docs_sentence, summarize_font_family};
/// Describe the item under the cursor.
+///
+/// Passing a `document` (from a previous compilation) is optional, but enhances
+/// the autocompletions. Label completions, for instance, are only generated
+/// when the document is available.
pub fn tooltip(
world: &dyn World,
- frames: &[Frame],
+ document: Option<&Document>,
source: &Source,
cursor: usize,
) -> Option<Tooltip> {
@@ -26,7 +31,7 @@ pub fn tooltip(
named_param_tooltip(world, &leaf)
.or_else(|| font_tooltip(world, &leaf))
- .or_else(|| label_tooltip(frames, &leaf))
+ .or_else(|| document.and_then(|doc| label_tooltip(doc, &leaf)))
.or_else(|| expr_tooltip(world, &leaf))
.or_else(|| closure_tooltip(&leaf))
}
@@ -145,14 +150,14 @@ fn length_tooltip(length: Length) -> Option<Tooltip> {
}
/// Tooltip for a hovered reference or label.
-fn label_tooltip(frames: &[Frame], leaf: &LinkedNode) -> Option<Tooltip> {
+fn label_tooltip(document: &Document, leaf: &LinkedNode) -> Option<Tooltip> {
let target = match leaf.kind() {
SyntaxKind::RefMarker => leaf.text().trim_start_matches('@'),
SyntaxKind::Label => leaf.text().trim_start_matches('<').trim_end_matches('>'),
_ => return None,
};
- for (label, detail) in analyze_labels(frames).0 {
+ for (label, detail) in analyze_labels(document).0 {
if label.as_str() == target {
return Some(Tooltip::Text(detail?));
}