Mercurial > vim
comparison src/change.c @ 16636:0daf9eca3541 v8.1.1320
patch 8.1.1320: it is not possible to track changes to a buffer
commit https://github.com/vim/vim/commit/6d2399bd1053b367e13cc2b8991d3ff0bf724c7c
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat May 11 19:14:16 2019 +0200
patch 8.1.1320: it is not possible to track changes to a buffer
Problem: It is not possible to track changes to a buffer.
Solution: Add listener_add() and listener_remove(). No docs or tests yet.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 11 May 2019 19:15:05 +0200 |
parents | 7217a9c5adb3 |
children | 4790302965fc |
comparison
equal
deleted
inserted
replaced
16635:3f496519cc23 | 16636:0daf9eca3541 |
---|---|
149 #ifdef FEAT_TITLE | 149 #ifdef FEAT_TITLE |
150 need_maketitle = TRUE; // set window title later | 150 need_maketitle = TRUE; // set window title later |
151 #endif | 151 #endif |
152 } | 152 } |
153 | 153 |
154 #ifdef FEAT_EVAL | |
155 static list_T *recorded_changes = NULL; | |
156 static long next_listener_id = 0; | |
157 | |
158 /* | |
159 * Record a change for listeners added with listener_add(). | |
160 */ | |
161 static void | |
162 may_record_change( | |
163 linenr_T lnum, | |
164 colnr_T col, | |
165 linenr_T lnume, | |
166 long xtra) | |
167 { | |
168 dict_T *dict; | |
169 | |
170 if (curbuf->b_listener == NULL) | |
171 return; | |
172 if (recorded_changes == NULL) | |
173 { | |
174 recorded_changes = list_alloc(); | |
175 if (recorded_changes == NULL) // out of memory | |
176 return; | |
177 ++recorded_changes->lv_refcount; | |
178 recorded_changes->lv_lock = VAR_FIXED; | |
179 } | |
180 | |
181 dict = dict_alloc(); | |
182 if (dict == NULL) | |
183 return; | |
184 dict_add_number(dict, "lnum", (varnumber_T)lnum); | |
185 dict_add_number(dict, "end", (varnumber_T)lnume); | |
186 dict_add_number(dict, "added", (varnumber_T)xtra); | |
187 dict_add_number(dict, "col", (varnumber_T)col); | |
188 | |
189 list_append_dict(recorded_changes, dict); | |
190 } | |
191 | |
192 /* | |
193 * listener_add() function | |
194 */ | |
195 void | |
196 f_listener_add(typval_T *argvars, typval_T *rettv) | |
197 { | |
198 char_u *callback; | |
199 partial_T *partial; | |
200 listener_T *lnr; | |
201 | |
202 callback = get_callback(&argvars[0], &partial); | |
203 if (callback == NULL) | |
204 return; | |
205 | |
206 lnr = (listener_T *)alloc_clear((sizeof(listener_T))); | |
207 if (lnr == NULL) | |
208 { | |
209 free_callback(callback, partial); | |
210 return; | |
211 } | |
212 lnr->lr_next = curbuf->b_listener; | |
213 curbuf->b_listener = lnr; | |
214 | |
215 if (partial == NULL) | |
216 lnr->lr_callback = vim_strsave(callback); | |
217 else | |
218 lnr->lr_callback = callback; // pointer into the partial | |
219 lnr->lr_partial = partial; | |
220 | |
221 lnr->lr_id = ++next_listener_id; | |
222 rettv->vval.v_number = lnr->lr_id; | |
223 } | |
224 | |
225 /* | |
226 * listener_remove() function | |
227 */ | |
228 void | |
229 f_listener_remove(typval_T *argvars, typval_T *rettv UNUSED) | |
230 { | |
231 listener_T *lnr; | |
232 listener_T *next; | |
233 listener_T *prev = NULL; | |
234 int id = tv_get_number(argvars); | |
235 buf_T *buf = curbuf; | |
236 | |
237 for (lnr = buf->b_listener; lnr != NULL; lnr = next) | |
238 { | |
239 next = lnr->lr_next; | |
240 if (lnr->lr_id == id) | |
241 { | |
242 if (prev != NULL) | |
243 prev->lr_next = lnr->lr_next; | |
244 else | |
245 buf->b_listener = lnr->lr_next; | |
246 free_callback(lnr->lr_callback, lnr->lr_partial); | |
247 vim_free(lnr); | |
248 } | |
249 prev = lnr; | |
250 } | |
251 } | |
252 | |
253 /* | |
254 * Called when a sequence of changes is done: invoke listeners added with | |
255 * listener_add(). | |
256 */ | |
257 void | |
258 invoke_listeners(void) | |
259 { | |
260 listener_T *lnr; | |
261 typval_T rettv; | |
262 int dummy; | |
263 typval_T argv[2]; | |
264 | |
265 if (recorded_changes == NULL) // nothing changed | |
266 return; | |
267 argv[0].v_type = VAR_LIST; | |
268 argv[0].vval.v_list = recorded_changes; | |
269 | |
270 for (lnr = curbuf->b_listener; lnr != NULL; lnr = lnr->lr_next) | |
271 { | |
272 call_func(lnr->lr_callback, -1, &rettv, | |
273 1, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL); | |
274 clear_tv(&rettv); | |
275 } | |
276 | |
277 list_unref(recorded_changes); | |
278 recorded_changes = NULL; | |
279 } | |
280 #endif | |
281 | |
154 /* | 282 /* |
155 * Common code for when a change was made. | 283 * Common code for when a change was made. |
156 * See changed_lines() for the arguments. | 284 * See changed_lines() for the arguments. |
157 * Careful: may trigger autocommands that reload the buffer. | 285 * Careful: may trigger autocommands that reload the buffer. |
158 */ | 286 */ |
173 #endif | 301 #endif |
174 | 302 |
175 // mark the buffer as modified | 303 // mark the buffer as modified |
176 changed(); | 304 changed(); |
177 | 305 |
306 #ifdef FEAT_EVAL | |
307 may_record_change(lnum, col, lnume, xtra); | |
308 #endif | |
178 #ifdef FEAT_DIFF | 309 #ifdef FEAT_DIFF |
179 if (curwin->w_p_diff && diff_internal()) | 310 if (curwin->w_p_diff && diff_internal()) |
180 curtab->tp_diff_update = TRUE; | 311 curtab->tp_diff_update = TRUE; |
181 #endif | 312 #endif |
182 | 313 |