nvim_oxi_api/opts/
set_extmark.rs

1use types::{Array, Integer};
2
3use crate::trait_utils::StringOrListOfStrings;
4use crate::types::{ExtmarkHlMode, ExtmarkVirtTextPosition};
5
6/// Options passed to [`Buffer::set_extmark()`](crate::Buffer::set_extmark).
7#[cfg(not(feature = "neovim-0-10"))] // 0nly on 0.9.
8#[derive(Clone, Debug, Default)]
9#[repr(C)]
10pub struct SetExtmarkOpts {
11    id: types::Object,
12    spell: types::Object,
13    hl_eol: types::Object,
14    strict: types::Object,
15    end_col: types::Object,
16    conceal: types::Object,
17    hl_mode: types::Object,
18    end_row: types::Object,
19    /// The docs don't mention this but it's there.
20    end_line: types::Object,
21    hl_group: types::Object,
22    priority: types::Object,
23    ephemeral: types::Object,
24    sign_text: types::Object,
25    virt_text: types::Object,
26    ui_watched: types::Object,
27    virt_lines: types::Object,
28    line_hl_group: types::Object,
29    right_gravity: types::Object,
30    sign_hl_group: types::Object,
31    virt_text_pos: types::Object,
32    virt_text_hide: types::Object,
33    number_hl_group: types::Object,
34    virt_lines_above: types::Object,
35    end_right_gravity: types::Object,
36    virt_text_win_col: types::Object,
37    virt_lines_leftcol: types::Object,
38    cursorline_hl_group: types::Object,
39}
40
41#[cfg(not(feature = "neovim-0-10"))] // 0nly on 0.9.
42#[derive(Clone, Default)]
43pub struct SetExtmarkOptsBuilder(SetExtmarkOpts);
44
45#[cfg(not(feature = "neovim-0-10"))] // 0nly on 0.9.
46impl SetExtmarkOpts {
47    #[inline(always)]
48    pub fn builder() -> SetExtmarkOptsBuilder {
49        SetExtmarkOptsBuilder::default()
50    }
51}
52
53#[cfg(not(feature = "neovim-0-10"))] // 0nly on 0.9.
54impl SetExtmarkOptsBuilder {
55    /// Enable concealing symilar to `:syn-conceal`. If a character is supplied
56    /// it is used as `:syn-cchar`.
57    ///
58    /// [`hl_group`](SetExtmarkOptsBuilder::hl_group) is used to highlight the
59    /// character if provided, otherwise it defaults to `hl-Conceal`.
60    #[inline]
61    pub fn conceal(&mut self, conceal: Option<char>) -> &mut Self {
62        let ch = conceal.map(types::String::from).unwrap_or_default();
63        self.0.conceal = ch.into();
64        self
65    }
66
67    /// Name of the highlight group used to highlight the line when the cursor
68    /// is on the same line as the mark and `cursorline` is enabled.
69    #[inline]
70    pub fn cursorline_hl_group(
71        &mut self,
72        cursorline_hl_group: &str,
73    ) -> &mut Self {
74        self.0.cursorline_hl_group =
75            types::String::from(cursorline_hl_group).into();
76        self
77    }
78
79    /// Ending line of the mark. 0-indexed and exclusive.
80    #[inline]
81    pub fn end_col(&mut self, end_col: usize) -> &mut Self {
82        let end_col = end_col as Integer;
83        self.0.end_col = end_col.into();
84        self
85    }
86
87    /// Indicates the direction the extmark's end position (if it exists) will
88    /// be shifted in when new text is inserted (`true` for right, `false` for
89    /// left). Defaults to left.
90    #[inline]
91    pub fn end_right_gravity(&mut self, end_right_gravity: bool) -> &mut Self {
92        self.0.end_right_gravity = end_right_gravity.into();
93        self
94    }
95
96    /// Ending line of the mark. 0-indexed and inclusive.
97    #[inline]
98    pub fn end_row(&mut self, end_row: usize) -> &mut Self {
99        let end_row = end_row as Integer;
100        self.0.end_row = end_row.into();
101        self
102    }
103
104    /// For use with
105    /// [`set_decoration_provider()`](crate::set_decoration_provider)
106    /// callbacks. The mark will only be used for the current redraw cycle, and
107    /// not be permanently stored in the buffer.
108    #[inline]
109    pub fn ephemeral(&mut self, ephemeral: bool) -> &mut Self {
110        self.0.ephemeral = ephemeral.into();
111        self
112    }
113
114    /// Whether to continue the highlight for the rest of the screen line for
115    /// multiline highlights covering the EOL of a line.
116    #[inline]
117    pub fn hl_eol(&mut self, hl_eol: bool) -> &mut Self {
118        self.0.hl_eol = hl_eol.into();
119        self
120    }
121
122    /// Name of the highlight group used to highlight this mark.
123    #[inline]
124    pub fn hl_group(&mut self, hl_group: &str) -> &mut Self {
125        self.0.hl_group = types::String::from(hl_group).into();
126        self
127    }
128
129    /// Controls how highlights are combined with the highlights of the text.
130    #[inline]
131    pub fn hl_mode(&mut self, hl_mode: ExtmarkHlMode) -> &mut Self {
132        let hl_mode = types::String::from(hl_mode);
133        self.0.hl_mode = hl_mode.into();
134        self
135    }
136
137    /// Id of the extmark to edit.
138    #[inline]
139    pub fn id(&mut self, id: u32) -> &mut Self {
140        let id = id as Integer;
141        self.0.id = id.into();
142        self
143    }
144
145    /// Name of the highlight group used to highlight the whole line.
146    #[inline]
147    pub fn line_hl_group(&mut self, line_hl_group: &str) -> &mut Self {
148        self.0.line_hl_group = types::String::from(line_hl_group).into();
149        self
150    }
151
152    /// Name of the highlight group used to highlight the number column.
153    #[inline]
154    pub fn number_hl_group(&mut self, number_hl_group: &str) -> &mut Self {
155        self.0.number_hl_group = types::String::from(number_hl_group).into();
156        self
157    }
158
159    /// A priority value for the highlight group. For example, treesitter
160    /// highlights use a value of 100.
161    #[inline]
162    pub fn priority(&mut self, priority: u32) -> &mut Self {
163        let priority = priority as Integer;
164        self.0.priority = priority.into();
165        self
166    }
167
168    /// Indicates the direction the extmark will be shifted in when new text is
169    /// inserted (`true` for right, `false` for left). Defaults to right.
170    #[inline]
171    pub fn right_gravity(&mut self, right_gravity: bool) -> &mut Self {
172        self.0.right_gravity = right_gravity.into();
173        self
174    }
175
176    /// Name of the highlight group used to highlight the sign column text.
177    #[inline]
178    pub fn sign_hl_group(&mut self, sign_hl_group: &str) -> &mut Self {
179        self.0.sign_hl_group = types::String::from(sign_hl_group).into();
180        self
181    }
182
183    /// Text to display in the sign column. Should take up 1-2 display cells.
184    #[inline]
185    pub fn sign_text(&mut self, sign_text: &str) -> &mut Self {
186        let sign_text = types::String::from(sign_text);
187        self.0.sign_text = sign_text.into();
188        self
189    }
190
191    /// Whether the extmark should not be placed if the line or column value is
192    /// past the end of the buffer or end of the line, respectively. Defaults
193    /// to `true`.
194    #[inline]
195    pub fn strict(&mut self, strict: bool) -> &mut Self {
196        self.0.strict = strict.into();
197        self
198    }
199
200    /// Whether the mark should be drawn by an external UI. When `true` the UI
201    /// will receive `win_extmark` events.
202    #[inline]
203    pub fn ui_watched(&mut self, ui_watched: bool) -> &mut Self {
204        self.0.ui_watched = ui_watched.into();
205        self
206    }
207
208    /// Virtual lines to add next to the mark.
209    #[inline]
210    pub fn virt_lines<Txt, Hl, Cnk, ChunkyCnk>(
211        &mut self,
212        virt_lines: ChunkyCnk,
213    ) -> &mut Self
214    where
215        ChunkyCnk: IntoIterator<Item = Cnk>,
216        Cnk: IntoIterator<Item = (Txt, Hl)>,
217        Txt: Into<types::String>,
218        Hl: StringOrListOfStrings,
219    {
220        let mut virt = types::Array::default();
221        set_virt_lines(&mut virt, virt_lines);
222        self.0.virt_lines = virt.into();
223        self
224    }
225
226    /// Whether to place virtual lines above the buffer line containing the
227    /// mark.
228    #[inline]
229    pub fn virt_lines_above(&mut self, virt_lines_above: bool) -> &mut Self {
230        self.0.virt_lines_above = virt_lines_above.into();
231        self
232    }
233
234    /// Whether to place extmarks in the leftmost column of the ewindow,
235    /// bypassing sign and number columns.
236    #[inline]
237    pub fn virt_lines_leftcol(
238        &mut self,
239        virt_lines_leftcol: bool,
240    ) -> &mut Self {
241        self.0.virt_lines_leftcol = virt_lines_leftcol.into();
242        self
243    }
244
245    /// Virtual text to link to this mark. Every `(text, highlights)` tuple
246    /// represents a text chunk with a specified highlight. The highlights
247    /// specified in `highlights` will be combined together, with the highest
248    /// priority highlight beign applied last. Each highlight group can either
249    /// be a string or an integer, the latter obtained using
250    /// [`get_hl_id_by_name()`](crate::get_hl_id_by_name).
251    #[inline]
252    pub fn virt_text<Txt, Hl, Cnk>(&mut self, virt_text: Cnk) -> &mut Self
253    where
254        Cnk: IntoIterator<Item = (Txt, Hl)>,
255        Txt: Into<types::String>,
256        Hl: StringOrListOfStrings,
257    {
258        let mut array = types::Array::default();
259        set_virt_text(&mut array, virt_text);
260        self.0.virt_text = array.into();
261        self
262    }
263
264    /// Whether to hide the virtual text when the background text is selected
265    /// or hidden due to horizontal scroll.
266    #[inline]
267    pub fn virt_text_hide(&mut self, virt_text_hide: bool) -> &mut Self {
268        self.0.virt_text_hide = virt_text_hide.into();
269        self
270    }
271
272    /// Position of the virtual text.
273    #[inline]
274    pub fn virt_text_pos(
275        &mut self,
276        virt_text_pos: ExtmarkVirtTextPosition,
277    ) -> &mut Self {
278        let virt_text_pos = types::String::from(virt_text_pos);
279        self.0.virt_text_pos = virt_text_pos.into();
280        self
281    }
282
283    /// Position the virtual text at a fixed window column (starting from the
284    /// first text column).
285    #[inline]
286    pub fn virt_text_win_col(&mut self, virt_text_win_col: u32) -> &mut Self {
287        let virt_text_win_col = virt_text_win_col as Integer;
288        self.0.virt_text_win_col = virt_text_win_col.into();
289        self
290    }
291
292    #[inline]
293    pub fn build(&mut self) -> SetExtmarkOpts {
294        std::mem::take(&mut self.0)
295    }
296}
297
298/// Options passed to [`Buffer::set_extmark()`](crate::Buffer::set_extmark).
299#[cfg(feature = "neovim-0-10")] // On 0.10 and nightly.
300#[derive(Clone, Debug, Default, macros::OptsBuilder)]
301#[repr(C)]
302pub struct SetExtmarkOpts {
303    #[builder(mask)]
304    mask: u64,
305
306    /// Id of the extmark to edit.
307    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
308    id: types::Integer,
309
310    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
311    end_line: types::Integer,
312
313    /// Ending line of the mark. 0-indexed and inclusive.
314    #[builder(argtype = "usize", inline = "{0} as types::Integer")]
315    end_row: types::Integer,
316
317    /// Ending line of the mark. 0-indexed and exclusive.
318    #[builder(argtype = "usize", inline = "{0} as types::Integer")]
319    end_col: types::Integer,
320
321    /// Name of the highlight group used to highlight this mark.
322    #[builder(
323        generics = "Hl: crate::HlGroup",
324        argtype = "Hl",
325        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
326    )]
327    hl_group: types::HlGroupId,
328
329    /// Virtual text to link to this mark. Every `(text, highlights)` tuple
330    /// represents a text chunk with a specified highlight. The highlights
331    /// specified in `highlights` will be combined together, with the highest
332    /// priority highlight beign applied last. Each highlight group can either
333    /// be a string or an integer, the latter obtained using
334    /// [`get_hl_id_by_name()`](crate::get_hl_id_by_name).
335    #[builder(
336        generics = r#"Txt: Into<types::String>, Hl: StringOrListOfStrings, Cnk: IntoIterator<Item = (Txt, Hl)>"#,
337        argtype = "Cnk",
338        setter = "set_virt_text"
339    )]
340    virt_text: types::Array,
341
342    /// Position of the virtual text.
343    #[builder(
344        argtype = "ExtmarkVirtTextPosition",
345        inline = "types::String::from({0})"
346    )]
347    virt_text_pos: types::String,
348
349    /// Position the virtual text at a fixed window column (starting from the
350    /// first text column).
351    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
352    virt_text_win_col: Integer,
353
354    /// Whether to hide the virtual text when the background text is selected
355    /// or hidden due to horizontal scroll.
356    #[builder(argtype = "bool")]
357    virt_text_hide: types::Boolean,
358
359    /// Whether to repeat the virtual text on wrapped lines.
360    #[builder(argtype = "bool")]
361    virt_text_repeat_linebreak: types::Boolean,
362
363    /// Whether to continue the highlight for the rest of the screen line for
364    /// multiline highlights covering the EOL of a line.
365    #[builder(argtype = "bool")]
366    hl_eol: types::Boolean,
367
368    /// Controls how highlights are combined with the highlights of the text.
369    #[builder(argtype = "ExtmarkHlMode", inline = "types::String::from({0})")]
370    hl_mode: types::String,
371
372    #[builder(argtype = "bool")]
373    invalidate: types::Boolean,
374
375    /// For use with
376    /// [`set_decoration_provider()`](crate::set_decoration_provider)
377    /// callbacks. The mark will only be used for the current redraw cycle, and
378    /// not be permanently stored in the buffer.
379    #[builder(argtype = "bool")]
380    ephemeral: types::Boolean,
381
382    /// A priority value for the highlight group. For example, treesitter
383    /// highlights use a value of 100.
384    #[builder(argtype = "u32", inline = "{0} as types::Integer")]
385    priority: Integer,
386
387    /// Indicates the direction the extmark will be shifted in when new text is
388    /// inserted (`true` for right, `false` for left). Defaults to right.
389    #[builder(argtype = "bool")]
390    right_gravity: types::Boolean,
391
392    /// Indicates the direction the extmark's end position (if it exists) will
393    /// be shifted in when new text is inserted (`true` for right, `false` for
394    /// left). Defaults to left.
395    #[builder(argtype = "bool")]
396    end_right_gravity: types::Boolean,
397
398    /// Virtual lines to add next to the mark.
399    #[builder(
400        generics = r#"Txt: Into<types::String>, Hl: StringOrListOfStrings, Cnk: IntoIterator<Item = (Txt, Hl)>, ChunkyCnk: IntoIterator<Item = Cnk>"#,
401        argtype = "ChunkyCnk",
402        setter = "set_virt_lines"
403    )]
404    virt_lines: types::Array,
405
406    /// Whether to place virtual lines above the buffer line containing the
407    /// mark.
408    #[builder(argtype = "bool")]
409    virt_lines_above: types::Boolean,
410
411    /// Whether to place extmarks in the leftmost column of the ewindow,
412    /// bypassing sign and number columns.
413    #[builder(argtype = "bool")]
414    virt_lines_leftcol: types::Boolean,
415
416    /// Whether the extmark should not be placed if the line or column value is
417    /// past the end of the buffer or end of the line, respectively. Defaults
418    /// to `true`.
419    #[builder(argtype = "bool")]
420    strict: types::Boolean,
421
422    /// Text to display in the sign column. Should take up 1-2 display cells.
423    #[builder(argtype = "&str", inline = "types::String::from({0})")]
424    sign_text: types::String,
425
426    /// Name of the highlight group used to highlight the sign column text.
427    #[builder(
428        generics = "Hl: crate::HlGroup",
429        argtype = "Hl",
430        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
431    )]
432    sign_hl_group: types::HlGroupId,
433
434    /// Name of the highlight group used to highlight the number column.
435    #[builder(
436        generics = "Hl: crate::HlGroup",
437        argtype = "Hl",
438        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
439    )]
440    number_hl_group: types::HlGroupId,
441
442    /// Name of the highlight group used to highlight the whole line.
443    #[builder(
444        generics = "Hl: crate::HlGroup",
445        argtype = "Hl",
446        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
447    )]
448    line_hl_group: types::HlGroupId,
449
450    /// Name of the highlight group used to highlight the line when the cursor
451    /// is on the same line as the mark and `cursorline` is enabled.
452    #[builder(
453        generics = "Hl: crate::HlGroup",
454        argtype = "Hl",
455        inline = r#"{ let Ok(hl_id) = {0}.to_hl_id() else { return self; }; hl_id }"#
456    )]
457    cursorline_hl_group: types::HlGroupId,
458
459    /// Enable concealing symilar to `:syn-conceal`. If a character is supplied
460    /// it is used as `:syn-cchar`.
461    ///
462    /// [`hl_group`](SetExtmarkOptsBuilder::hl_group) is used to highlight the
463    /// character if provided, otherwise it defaults to `hl-Conceal`.
464    #[builder(
465        argtype = "Option<char>",
466        inline = "{0}.map(types::String::from).unwrap_or_default()"
467    )]
468    conceal: types::String,
469
470    #[builder(argtype = "bool")]
471    spell: types::Boolean,
472
473    /// Whether the mark should be drawn by an external UI. When `true` the UI
474    /// will receive `win_extmark` events.
475    #[builder(argtype = "bool")]
476    ui_watched: types::Boolean,
477
478    /// Whether to restore the exact position of the mark if text around the
479    /// mark was deleted and then restored by undo.
480    ///
481    /// Defaults to `true`.
482    #[builder(argtype = "bool")]
483    #[cfg_attr(
484        docsrs,
485        doc(cfg(any(feature = "neovim-0-10", feature = "neovim-nightly")))
486    )]
487    undo_restore: types::Boolean,
488
489    /// A URL to associate with this extmark.
490    ///
491    /// In the TUI, the OSC 8 control sequence is used to generate a clickable
492    /// hyperlink to this URL.
493    #[builder(argtype = "&str", inline = "types::String::from({0})")]
494    url: types::String,
495
496    // This was an experimental option in Neovim 0.10, and was removed on
497    // nightly. We only include it when compiling for 0.10, without ever
498    // defining a builder method for it.
499    #[cfg(all(feature = "neovim-0-10", not(feature = "neovim-nightly")))]
500    // Only on 0.10.
501    scoped: types::Boolean,
502}
503
504#[inline]
505fn set_virt_lines<Txt, Hl, Cnk, ChunkyCnk>(
506    field: &mut Array,
507    virt_lines: ChunkyCnk,
508) where
509    ChunkyCnk: IntoIterator<Item = Cnk>,
510    Cnk: IntoIterator<Item = (Txt, Hl)>,
511    Txt: Into<types::String>,
512    Hl: StringOrListOfStrings,
513{
514    *field = virt_lines
515        .into_iter()
516        .map(|chnky| {
517            Array::from_iter(chnky.into_iter().map(|(txt, hl)| {
518                Array::from_iter([txt.into().into(), hl.to_object()])
519            }))
520        })
521        .collect::<Array>();
522}
523
524#[inline]
525fn set_virt_text<Txt, Hl, Cnk>(field: &mut Array, virt_text: Cnk)
526where
527    Cnk: IntoIterator<Item = (Txt, Hl)>,
528    Txt: Into<types::String>,
529    Hl: StringOrListOfStrings,
530{
531    *field = virt_text
532        .into_iter()
533        .map(|(txt, hl)| Array::from_iter([txt.into().into(), hl.to_object()]))
534        .collect::<Array>();
535}