Skip to main content

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}