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