editor_core/decorations.rs
1//! First-class decorations (virtual text) data model.
2//!
3//! Decorations represent UI-facing annotations anchored to document character offsets, without
4//! modifying the document text. Common examples:
5//!
6//! - LSP inlay hints (inline type hints)
7//! - code lens (line-level virtual text)
8//! - document links
9//! - match highlights / bracket highlights (when not represented as pure style intervals)
10//!
11//! Decorations are derived editor state. They typically originate from integrations via
12//! [`ProcessingEdit`](crate::processing::ProcessingEdit) and are rendered by the host.
13
14use crate::intervals::StyleId;
15
16/// A source/layer identifier for decorations.
17///
18/// This mirrors `StyleLayerId`, but for non-text, non-style derived state.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct DecorationLayerId(pub u32);
21
22impl DecorationLayerId {
23 /// Decorations produced from LSP `textDocument/inlayHint`.
24 pub const INLAY_HINTS: Self = Self(1);
25 /// Decorations produced from LSP `textDocument/codeLens`.
26 pub const CODE_LENS: Self = Self(2);
27 /// Decorations representing document links (e.g. URIs, file paths).
28 pub const DOCUMENT_LINKS: Self = Self(3);
29 /// Decorations representing match highlights (search matches, bracket matches, etc.).
30 pub const MATCH_HIGHLIGHTS: Self = Self(4);
31
32 /// Create a new layer id.
33 pub fn new(id: u32) -> Self {
34 Self(id)
35 }
36}
37
38/// A half-open character-offset range (`start..end`) in the document.
39///
40/// For point-anchored decorations, use `start == end`.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub struct DecorationRange {
43 /// Range start offset (inclusive), in Unicode scalar values (`char`) from the start of the document.
44 pub start: usize,
45 /// Range end offset (exclusive), in Unicode scalar values (`char`) from the start of the document.
46 pub end: usize,
47}
48
49impl DecorationRange {
50 /// Create a new decoration range.
51 pub fn new(start: usize, end: usize) -> Self {
52 Self { start, end }
53 }
54}
55
56/// Where to render a decoration relative to its anchor range.
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum DecorationPlacement {
59 /// Render before the anchor (in logical order).
60 Before,
61 /// Render after the anchor (in logical order).
62 After,
63 /// Render above the anchor line (e.g. code lens).
64 AboveLine,
65}
66
67/// A coarse decoration kind tag.
68#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
69pub enum DecorationKind {
70 /// Inline inlay hint (usually from LSP).
71 InlayHint,
72 /// Code lens (usually above a line).
73 CodeLens,
74 /// Document link (clickable range).
75 DocumentLink,
76 /// Highlight decoration (e.g. match/bracket highlights).
77 Highlight,
78 /// A custom, integration-defined kind.
79 Custom(u32),
80}
81
82/// A single decoration item.
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct Decoration {
85 /// Anchor range in character offsets.
86 pub range: DecorationRange,
87 /// Relative placement (before/after/above).
88 pub placement: DecorationPlacement,
89 /// A coarse decoration kind.
90 pub kind: DecorationKind,
91 /// Optional virtual text to render.
92 pub text: Option<String>,
93 /// Optional style ids to apply when rendering this decoration.
94 pub styles: Vec<StyleId>,
95 /// Optional tooltip payload (plain text; markup is host-defined).
96 pub tooltip: Option<String>,
97 /// Optional integration-specific payload (JSON text).
98 pub data_json: Option<String>,
99}