nvim_oxi_api/opts/
set_extmark.rs

1use types::{Array, Integer};
2
3use crate::trait_utils::StringOrListOfStrings;
4#[cfg(feature = "neovim-0-11")] // On 0.11 and Nightly.
5use crate::types::VirtLinesOverflow;
6use crate::types::{ExtmarkHlMode, ExtmarkVirtTextPosition};
7
8/// Options passed to [`Buffer::set_extmark()`](crate::Buffer::set_extmark).
9#[derive(Clone, Debug, Default, macros::OptsBuilder)]
10#[repr(C)]
11pub struct SetExtmarkOpts {
12    #[builder(mask)]
13    mask: u64,
14
15    /// Id of the extmark to edit.
16    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
17    id: types::Integer,
18
19    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
20    end_line: types::Integer,
21
22    /// Ending line of the mark. 0-indexed and inclusive.
23    #[builder(argtype = "usize", inline = "{0} as types::Integer")]
24    end_row: types::Integer,
25
26    /// Ending line of the mark. 0-indexed and exclusive.
27    #[builder(argtype = "usize", inline = "{0} as types::Integer")]
28    end_col: types::Integer,
29
30    /// Name of the highlight group used to highlight this mark.
31    #[cfg(not(feature = "neovim-0-11"))] // Only on 0.10.
32    #[cfg_attr(docsrs, doc(cfg(not(feature = "neovim-0-11"))))]
33    #[builder(
34        generics = "Hl: crate::HlGroup",
35        argtype = "Hl",
36        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
37    )]
38    hl_group: types::HlGroupId,
39
40    /// Name of the highlight group used to highlight this mark.
41    #[cfg(feature = "neovim-0-11")] // Only on Nightly.
42    #[cfg_attr(docsrs, doc(cfg(feature = "neovim-0-11")))]
43    #[builder(
44        generics = "Hl: crate::SetExtmarkHlGroup",
45        argtype = "Hl",
46        inline = r#"{0}.into_object()"#
47    )]
48    hl_group: types::Object,
49
50    /// Virtual text to link to this mark. Every `(text, highlights)` tuple
51    /// represents a text chunk with a specified highlight. The highlights
52    /// specified in `highlights` will be combined together, with the highest
53    /// priority highlight beign applied last. Each highlight group can either
54    /// be a string or an integer, the latter obtained using
55    /// [`get_hl_id_by_name()`](crate::get_hl_id_by_name).
56    #[builder(
57        generics = r#"Txt: Into<types::String>, Hl: StringOrListOfStrings, Cnk: IntoIterator<Item = (Txt, Hl)>"#,
58        argtype = "Cnk",
59        setter = "set_virt_text"
60    )]
61    virt_text: types::Array,
62
63    /// Position of the virtual text.
64    #[builder(
65        argtype = "ExtmarkVirtTextPosition",
66        inline = "types::String::from({0})"
67    )]
68    virt_text_pos: types::String,
69
70    /// Position the virtual text at a fixed window column (starting from the
71    /// first text column).
72    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
73    virt_text_win_col: Integer,
74
75    /// Whether to hide the virtual text when the background text is selected
76    /// or hidden due to horizontal scroll.
77    #[builder(argtype = "bool")]
78    virt_text_hide: types::Boolean,
79
80    /// Whether to repeat the virtual text on wrapped lines.
81    #[builder(argtype = "bool")]
82    virt_text_repeat_linebreak: types::Boolean,
83
84    /// Whether to continue the highlight for the rest of the screen line for
85    /// multiline highlights covering the EOL of a line.
86    #[builder(argtype = "bool")]
87    hl_eol: types::Boolean,
88
89    /// Controls how highlights are combined with the highlights of the text.
90    #[builder(argtype = "ExtmarkHlMode", inline = "types::String::from({0})")]
91    hl_mode: types::String,
92
93    #[builder(argtype = "bool")]
94    invalidate: types::Boolean,
95
96    /// For use with
97    /// [`set_decoration_provider()`](crate::set_decoration_provider)
98    /// callbacks. The mark will only be used for the current redraw cycle, and
99    /// not be permanently stored in the buffer.
100    #[builder(argtype = "bool")]
101    ephemeral: types::Boolean,
102
103    /// A priority value for the highlight group. For example, treesitter
104    /// highlights use a value of 100.
105    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
106    priority: Integer,
107
108    /// Indicates the direction the extmark will be shifted in when new text is
109    /// inserted (`true` for right, `false` for left). Defaults to right.
110    #[builder(argtype = "bool")]
111    right_gravity: types::Boolean,
112
113    /// Indicates the direction the extmark's end position (if it exists) will
114    /// be shifted in when new text is inserted (`true` for right, `false` for
115    /// left). Defaults to left.
116    #[builder(argtype = "bool")]
117    end_right_gravity: types::Boolean,
118
119    /// Virtual lines to add next to the mark.
120    #[builder(
121        generics = r#"Txt: Into<types::String>, Hl: StringOrListOfStrings, Cnk: IntoIterator<Item = (Txt, Hl)>, ChunkyCnk: IntoIterator<Item = Cnk>"#,
122        argtype = "ChunkyCnk",
123        setter = "set_virt_lines"
124    )]
125    virt_lines: types::Array,
126
127    /// Whether to place virtual lines above the buffer line containing the
128    /// mark.
129    #[builder(argtype = "bool")]
130    virt_lines_above: types::Boolean,
131
132    /// Whether to place extmarks in the leftmost column of the ewindow,
133    /// bypassing sign and number columns.
134    #[builder(argtype = "bool")]
135    virt_lines_leftcol: types::Boolean,
136
137    /// Controls how to handle virtual lines wider than the window.
138    #[cfg_attr(docsrs, doc(cfg(feature = "neovim-0-11")))]
139    #[cfg(feature = "neovim-0-11")] // On 0.11 and Nightly.
140    #[builder(argtype = "VirtLinesOverflow", inline = "{0}.into()")]
141    virt_lines_overflow: types::String,
142
143    /// Whether the extmark should not be placed if the line or column value is
144    /// past the end of the buffer or end of the line, respectively. Defaults
145    /// to `true`.
146    #[builder(argtype = "bool")]
147    strict: types::Boolean,
148
149    /// Text to display in the sign column. Should take up 1-2 display cells.
150    #[builder(argtype = "&str", inline = "types::String::from({0})")]
151    sign_text: types::String,
152
153    /// Name of the highlight group used to highlight the sign column text.
154    #[builder(
155        generics = "Hl: crate::HlGroup",
156        argtype = "Hl",
157        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
158    )]
159    sign_hl_group: types::HlGroupId,
160
161    /// Name of the highlight group used to highlight the number column.
162    #[builder(
163        generics = "Hl: crate::HlGroup",
164        argtype = "Hl",
165        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
166    )]
167    number_hl_group: types::HlGroupId,
168
169    /// Name of the highlight group used to highlight the whole line.
170    #[builder(
171        generics = "Hl: crate::HlGroup",
172        argtype = "Hl",
173        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
174    )]
175    line_hl_group: types::HlGroupId,
176
177    /// Name of the highlight group used to highlight the line when the cursor
178    /// is on the same line as the mark and `cursorline` is enabled.
179    #[builder(
180        generics = "Hl: crate::HlGroup",
181        argtype = "Hl",
182        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
183    )]
184    cursorline_hl_group: types::HlGroupId,
185
186    /// Enable concealing symilar to `:syn-conceal`. If a character is supplied
187    /// it is used as `:syn-cchar`.
188    ///
189    /// [`hl_group`](SetExtmarkOptsBuilder::hl_group) is used to highlight the
190    /// character if provided, otherwise it defaults to `hl-Conceal`.
191    #[builder(
192        argtype = "Option<char>",
193        inline = "{0}.map(types::String::from).unwrap_or_default()"
194    )]
195    conceal: types::String,
196
197    /// When called, lines in the range are not drawn at all (according to
198    /// `conceallevel`); the next unconcealed line is drawn instead.
199    #[cfg_attr(docsrs, doc(cfg(feature = "neovim-0-11")))]
200    #[cfg(feature = "neovim-0-11")] // On 0.11 and Nightly.
201    #[builder(argtype = "()", inline = "{let _ = {0}; types::String::new()}")]
202    conceal_lines: types::String,
203
204    #[builder(argtype = "bool")]
205    spell: types::Boolean,
206
207    /// Whether the mark should be drawn by an external UI. When `true` the UI
208    /// will receive `win_extmark` events.
209    #[builder(argtype = "bool")]
210    ui_watched: types::Boolean,
211
212    /// Whether to restore the exact position of the mark if text around the
213    /// mark was deleted and then restored by undo.
214    ///
215    /// Defaults to `true`.
216    #[builder(argtype = "bool")]
217    undo_restore: types::Boolean,
218
219    /// A URL to associate with this extmark.
220    ///
221    /// In the TUI, the OSC 8 control sequence is used to generate a clickable
222    /// hyperlink to this URL.
223    #[builder(argtype = "&str", inline = "types::String::from({0})")]
224    url: types::String,
225
226    // This was an experimental option in Neovim 0.10 but has been removed from
227    // the public API on nightly, even though it's still included in the opts.
228    scoped: types::Boolean,
229}
230
231#[inline]
232fn set_virt_lines<Txt, Hl, Cnk, ChunkyCnk>(
233    field: &mut Array,
234    virt_lines: ChunkyCnk,
235) where
236    ChunkyCnk: IntoIterator<Item = Cnk>,
237    Cnk: IntoIterator<Item = (Txt, Hl)>,
238    Txt: Into<types::String>,
239    Hl: StringOrListOfStrings,
240{
241    *field = virt_lines
242        .into_iter()
243        .map(|chnky| {
244            Array::from_iter(chnky.into_iter().map(|(txt, hl)| {
245                Array::from_iter([txt.into().into(), hl.to_object()])
246            }))
247        })
248        .collect::<Array>();
249}
250
251#[inline]
252fn set_virt_text<Txt, Hl, Cnk>(field: &mut Array, virt_text: Cnk)
253where
254    Cnk: IntoIterator<Item = (Txt, Hl)>,
255    Txt: Into<types::String>,
256    Hl: StringOrListOfStrings,
257{
258    *field = virt_text
259        .into_iter()
260        .map(|(txt, hl)| Array::from_iter([txt.into().into(), hl.to_object()]))
261        .collect::<Array>();
262}