summaryrefslogtreecommitdiff
path: root/src/ide
diff options
context:
space:
mode:
Diffstat (limited to 'src/ide')
-rw-r--r--src/ide/analyze.rs15
-rw-r--r--src/ide/complete.rs4
-rw-r--r--src/ide/jump.rs54
3 files changed, 46 insertions, 27 deletions
diff --git a/src/ide/analyze.rs b/src/ide/analyze.rs
index 68b82b05..27c6c2a4 100644
--- a/src/ide/analyze.rs
+++ b/src/ide/analyze.rs
@@ -81,6 +81,11 @@ pub fn analyze_import(
}
/// Find all labels and details for them.
+///
+/// Returns:
+/// - 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(
world: &(dyn World + 'static),
frames: &[Frame],
@@ -90,16 +95,16 @@ pub fn analyze_labels(
let items = &world.library().items;
// Labels in the document.
- for node in introspector.all() {
- let Some(label) = node.label() else { continue };
- let details = node
+ for elem in introspector.all() {
+ let Some(label) = elem.label() else { continue };
+ let details = elem
.field("caption")
- .or_else(|| node.field("body"))
+ .or_else(|| elem.field("body"))
.and_then(|field| match field {
Value::Content(content) => Some(content),
_ => None,
})
- .and_then(|content| (items.text_str)(content));
+ .and_then(|content| (items.text_str)(&content));
output.push((label.clone(), details));
}
diff --git a/src/ide/complete.rs b/src/ide/complete.rs
index 4a1f0216..886c1245 100644
--- a/src/ide/complete.rs
+++ b/src/ide/complete.rs
@@ -373,7 +373,7 @@ fn field_access_completions(ctx: &mut CompletionContext, value: &Value) {
}
Value::Content(content) => {
for (name, value) in content.fields() {
- ctx.value_completion(Some(name.clone()), value, false, None);
+ ctx.value_completion(Some(name.clone()), &value, false, None);
}
}
Value::Dict(dict) => {
@@ -509,7 +509,7 @@ fn set_rule_completions(ctx: &mut CompletionContext) {
fn show_rule_selector_completions(ctx: &mut CompletionContext) {
ctx.scope_completions(
false,
- |value| matches!(value, Value::Func(func) if func.select(None).is_ok()),
+ |value| matches!(value, Value::Func(func) if func.element().is_some()),
);
ctx.enrich("", ": ");
diff --git a/src/ide/jump.rs b/src/ide/jump.rs
index 17e318a7..d123ac06 100644
--- a/src/ide/jump.rs
+++ b/src/ide/jump.rs
@@ -1,6 +1,8 @@
use std::num::NonZeroUsize;
-use crate::doc::{Destination, Element, Frame, Location, Meta};
+use ecow::EcoString;
+
+use crate::doc::{Destination, Frame, FrameItem, Meta, Position};
use crate::geom::{Geometry, Point, Size};
use crate::model::Introspector;
use crate::syntax::{LinkedNode, Source, SourceId, Span, SyntaxKind};
@@ -11,8 +13,10 @@ use crate::World;
pub enum Jump {
/// Jump to a position in a source file.
Source(SourceId, usize),
- /// Jump to position in the output or to an external URL.
- Dest(Destination),
+ /// Jump to an external URL.
+ Url(EcoString),
+ /// Jump to a point on a page.
+ Position(Position),
}
impl Jump {
@@ -32,20 +36,27 @@ pub fn jump_from_click(
) -> Option<Jump> {
let mut introspector = None;
- // Prefer metadata.
- for (pos, element) in frame.elements() {
- if let Element::Meta(Meta::Link(link), size) = element {
+ // Try to find a link first.
+ for (pos, item) in frame.items() {
+ if let FrameItem::Meta(Meta::Link(dest), size) = item {
if is_in_rect(*pos, *size, click) {
- return Some(Jump::Dest(link.resolve(|| {
- introspector.get_or_insert_with(|| Introspector::new(frames))
- })));
+ 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),
+ ),
+ });
}
}
}
- for (mut pos, element) in frame.elements().rev() {
- match element {
- Element::Group(group) => {
+ // If there's no link, search for a jump target.
+ for (mut pos, item) in frame.items().rev() {
+ match item {
+ FrameItem::Group(group) => {
// TODO: Handle transformation.
if let Some(span) =
jump_from_click(world, frames, &group.frame, click - pos)
@@ -54,7 +65,7 @@ pub fn jump_from_click(
}
}
- Element::Text(text) => {
+ FrameItem::Text(text) => {
for glyph in &text.glyphs {
if glyph.span.is_detached() {
continue;
@@ -85,14 +96,14 @@ pub fn jump_from_click(
}
}
- Element::Shape(shape, span) => {
+ FrameItem::Shape(shape, span) => {
let Geometry::Rect(size) = shape.geometry else { continue };
if is_in_rect(pos, size, click) {
return Some(Jump::from_span(world, *span));
}
}
- Element::Image(_, size, span) if is_in_rect(pos, *size, click) => {
+ FrameItem::Image(_, size, span) if is_in_rect(pos, *size, click) => {
return Some(Jump::from_span(world, *span));
}
@@ -108,7 +119,7 @@ pub fn jump_from_cursor(
frames: &[Frame],
source: &Source,
cursor: usize,
-) -> Option<Location> {
+) -> Option<Position> {
let node = LinkedNode::new(source.root()).leaf_at(cursor)?;
if node.kind() != SyntaxKind::Text {
return None;
@@ -117,7 +128,10 @@ pub fn jump_from_cursor(
let span = node.span();
for (i, frame) in frames.iter().enumerate() {
if let Some(pos) = find_in_frame(frame, span) {
- return Some(Location { page: NonZeroUsize::new(i + 1).unwrap(), pos });
+ return Some(Position {
+ page: NonZeroUsize::new(i + 1).unwrap(),
+ point: pos,
+ });
}
}
@@ -126,15 +140,15 @@ pub fn jump_from_cursor(
/// Find the position of a span in a frame.
fn find_in_frame(frame: &Frame, span: Span) -> Option<Point> {
- for (mut pos, element) in frame.elements() {
- if let Element::Group(group) = element {
+ for (mut pos, item) in frame.items() {
+ if let FrameItem::Group(group) = item {
// TODO: Handle transformation.
if let Some(point) = find_in_frame(&group.frame, span) {
return Some(point + pos);
}
}
- if let Element::Text(text) = element {
+ if let FrameItem::Text(text) = item {
for glyph in &text.glyphs {
if glyph.span == span {
return Some(pos);