diff options
Diffstat (limited to 'crates/typst-ide')
| -rw-r--r-- | crates/typst-ide/src/analyze.rs | 10 | ||||
| -rw-r--r-- | crates/typst-ide/src/complete.rs | 19 | ||||
| -rw-r--r-- | crates/typst-ide/src/jump.rs | 18 | ||||
| -rw-r--r-- | crates/typst-ide/src/tooltip.rs | 15 |
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?)); } |
