nvim_api/opts/buf_attach.rs
1use derive_builder::Builder;
2use nvim_types::{Dictionary, Object};
3
4use crate::Buffer;
5use crate::ToFunction;
6
7/// Arguments passed to the callback registered to
8/// [`on_lines`](BufAttachOptsBuilder::on_lines). The `(a, b, c, d, e, f, g, h,
9/// i)` tuple represents:
10///
11/// - `a`: the string literal `"lines"`;
12/// - `b`: the [`Buffer`] that triggered the callback;
13/// - `c`: the value of the buffer-local `b:changedtick` variable;
14/// - `d`: first row that changed (0-indexed);
15/// - `e`: last row that was changed;
16/// - `f`: last row in the updated range;
17/// - `g`: byte count of previous contents;
18/// - `h`: deleted UTF-32 codepoints (if
19/// [`utf_sizes`](BufAttachOptsBuilder::utf_sizes) was `true`);
20/// - `i`: deleted UTF-16 codeunits (if
21/// [`utf_sizes`](BufAttachOptsBuilder::utf_sizes) was `true`);
22pub type OnLinesArgs = (
23 String,
24 Buffer,
25 u32,
26 usize,
27 usize,
28 usize,
29 usize,
30 Option<usize>,
31 Option<usize>,
32);
33
34/// Arguments passed to the callback registered to [`on_bytes`](BufAttachOptsBuilder::on_bytes). The `(a, b, c, d, e, f, g, h, i, j, k, l)`
35/// - `a`: the string literal `"bytes"`;
36/// - `b`: the [`Buffer`] that triggered the callback;
37/// - `c`: the value of the buffer-local `b:changedtick` variable;
38/// - `d`: start row of the changed text (0-indexed);
39/// - `e`: start column of the changed text;
40/// - `f`: byte offset of the changed text from the start of the buffer;
41/// - `g`: number of rows deleted;
42/// - `h`: number of columns deleted;
43/// - `i`: number of bytes deleted;
44/// - `j`: number of rows added;
45/// - `k`: number of columns added;
46/// - `l`: number of bytes added;
47pub type OnBytesArgs = (
48 String,
49 Buffer,
50 u32,
51 usize,
52 usize,
53 usize,
54 usize,
55 usize,
56 usize,
57 usize,
58 usize,
59 usize,
60);
61
62/// Arguments passed to the callback registered to
63/// [`on_changedtick`](BufAttachOptsBuilder::on_changedtick). The first tuple
64/// element is the string literal `"changedtick"`, the second is the [`Buffer`]
65/// that triggered the callback and the third is current value of the
66/// buffer-local
67/// [`b:changedtick`](https://neovim.io/doc/user/eval.html#b:changedtick)
68/// variable.
69pub type OnChangedtickArgs = (String, Buffer, u32);
70
71/// Arguments passed to the callback registered to
72/// [`on_detach`](BufAttachOptsBuilder::on_detach). The first tuple element is
73/// the string literal `"detach"`, the second is the [`Buffer`] that triggered
74/// the callback.
75pub type OnDetachArgs = (String, Buffer);
76
77/// Arguments passed to the callback registered to
78/// [`on_reload`](BufAttachOptsBuilder::on_reload). The first tuple element is
79/// the string literal `"reload"`, the second is the [`Buffer`] that triggered
80/// the callback.
81pub type OnReloadArgs = (String, Buffer);
82
83/// All the registered callbacks can detach by returning `true`, as described
84/// in `:h api-lua-detach`.
85pub type ShouldDetach = bool;
86
87/// Options passed to [`Buffer::attach`](crate::Buffer::attach).
88#[derive(Clone, Debug, Default, Builder)]
89#[builder(default, build_fn(private, name = "fallible_build"))]
90pub struct BufAttachOpts {
91 #[builder(setter(custom))]
92 on_bytes: Object,
93
94 #[builder(setter(custom))]
95 on_changedtick: Object,
96
97 #[builder(setter(custom))]
98 on_detach: Object,
99
100 #[builder(setter(custom))]
101 on_lines: Object,
102
103 #[builder(setter(custom))]
104 on_reload: Object,
105
106 /// Whether to also attach to command preview (i.e.
107 /// [`inccommand`](https://neovim.io/doc/user/options.html#'inccommand'))
108 /// events.
109 preview: bool,
110
111 /// Whether to include the UTF-32 and UTF-16 sizes of the replaced region
112 /// as the last arguments of the
113 /// [`on_lines`](BufAttachOptsBuilder::on_lines) callback.
114 utf_sizes: bool,
115}
116
117impl BufAttachOpts {
118 #[inline(always)]
119 /// Creates a new [`BufAttachOptsBuilder`].
120 pub fn builder() -> BufAttachOptsBuilder {
121 BufAttachOptsBuilder::default()
122 }
123}
124
125impl BufAttachOptsBuilder {
126 /// Callback invoked on change. It receives more granular information about
127 /// the change compared to [`on_lines`](BufAttachOptsBuilder::on_lines).
128 pub fn on_bytes<F>(&mut self, fun: F) -> &mut Self
129 where
130 F: ToFunction<OnBytesArgs, ShouldDetach>,
131 {
132 self.on_bytes = Some(fun.to_object());
133 self
134 }
135
136 /// Callback invoked on changedtick increment without text change.
137 pub fn on_changedtick<F>(&mut self, fun: F) -> &mut Self
138 where
139 F: ToFunction<OnChangedtickArgs, ShouldDetach>,
140 {
141 self.on_changedtick = Some(fun.to_object());
142 self
143 }
144
145 /// Callback invoked on detach.
146 pub fn on_detach<F>(&mut self, fun: F) -> &mut Self
147 where
148 F: ToFunction<OnDetachArgs, ShouldDetach>,
149 {
150 self.on_detach = Some(fun.to_object());
151 self
152 }
153
154 /// Callback invoked on change.
155 pub fn on_lines<F>(&mut self, fun: F) -> &mut Self
156 where
157 F: ToFunction<OnLinesArgs, ShouldDetach>,
158 {
159 self.on_lines = Some(fun.to_object());
160 self
161 }
162
163 /// Callback invoked on reload. The entire buffer content should be
164 /// considered changed.
165 pub fn on_reload<F>(&mut self, fun: F) -> &mut Self
166 where
167 F: ToFunction<OnReloadArgs, ShouldDetach>,
168 {
169 self.on_reload = Some(fun.to_object());
170 self
171 }
172
173 pub fn build(&mut self) -> BufAttachOpts {
174 self.fallible_build().expect("never fails, all fields have defaults")
175 }
176}
177
178impl From<&BufAttachOpts> for Dictionary {
179 fn from(opts: &BufAttachOpts) -> Self {
180 // TODO: don't clone by making non-owning version of Dictionary
181 Self::from_iter([
182 ("on_bytes", opts.on_bytes.clone()),
183 ("on_changedtick", opts.on_changedtick.clone()),
184 ("on_detach", opts.on_detach.clone()),
185 ("on_lines", opts.on_lines.clone()),
186 ("on_reload", opts.on_reload.clone()),
187 ("preview", opts.preview.into()),
188 ("utf_sizes", opts.utf_sizes.into()),
189 ])
190 }
191}