Patch 8.1.1320
Problem: It is not possible to track changes to a buffer.
Solution: Add listener_add() and listener_remove(). No docs or tests yet.
Files: src/structs.h, src/change.c, src/proto/change.pro
*** ../vim-8.1.1319/src/structs.h 2019-05-09 21:08:53.764083394 +0200
--- src/structs.h 2019-05-11 18:25:06.736904482 +0200
***************
*** 1873,1878 ****
--- 1873,1891 ----
#endif
} jobopt_T;
+ #ifdef FEAT_EVAL
+ /*
+ * Structure used for listeners added with listener_add().
+ */
+ typedef struct listener_S listener_T;
+ struct listener_S
+ {
+ listener_T *lr_next;
+ int lr_id;
+ char_u *lr_callback;
+ partial_T *lr_partial;
+ };
+ #endif
/* structure used for explicit stack while garbage collecting hash tables */
typedef struct ht_stack_S
***************
*** 2424,2429 ****
--- 2437,2444 ----
#ifdef FEAT_EVAL
dictitem_T b_bufvar; /* variable for "b:" Dictionary */
dict_T *b_vars; /* internal variables, local to buffer */
+
+ listener_T *b_listener;
#endif
#ifdef FEAT_TEXT_PROP
int b_has_textprop; // TRUE when text props were added
*** ../vim-8.1.1319/src/change.c 2019-05-11 17:03:55.170019762 +0200
--- src/change.c 2019-05-11 19:11:46.862043029 +0200
***************
*** 151,156 ****
--- 151,284 ----
#endif
}
+ #ifdef FEAT_EVAL
+ static list_T *recorded_changes = NULL;
+ static long next_listener_id = 0;
+
+ /*
+ * Record a change for listeners added with listener_add().
+ */
+ static void
+ may_record_change(
+ linenr_T lnum,
+ colnr_T col,
+ linenr_T lnume,
+ long xtra)
+ {
+ dict_T *dict;
+
+ if (curbuf->b_listener == NULL)
+ return;
+ if (recorded_changes == NULL)
+ {
+ recorded_changes = list_alloc();
+ if (recorded_changes == NULL) // out of memory
+ return;
+ ++recorded_changes->lv_refcount;
+ recorded_changes->lv_lock = VAR_FIXED;
+ }
+
+ dict = dict_alloc();
+ if (dict == NULL)
+ return;
+ dict_add_number(dict, "lnum", (varnumber_T)lnum);
+ dict_add_number(dict, "end", (varnumber_T)lnume);
+ dict_add_number(dict, "added", (varnumber_T)xtra);
+ dict_add_number(dict, "col", (varnumber_T)col);
+
+ list_append_dict(recorded_changes, dict);
+ }
+
+ /*
+ * listener_add() function
+ */
+ void
+ f_listener_add(typval_T *argvars, typval_T *rettv)
+ {
+ char_u *callback;
+ partial_T *partial;
+ listener_T *lnr;
+
+ callback = get_callback(&argvars[0], &partial);
+ if (callback == NULL)
+ return;
+
+ lnr = (listener_T *)alloc_clear((sizeof(listener_T)));
+ if (lnr == NULL)
+ {
+ free_callback(callback, partial);
+ return;
+ }
+ lnr->lr_next = curbuf->b_listener;
+ curbuf->b_listener = lnr;
+
+ if (partial == NULL)
+ lnr->lr_callback = vim_strsave(callback);
+ else
+ lnr->lr_callback = callback; // pointer into the partial
+ lnr->lr_partial = partial;
+
+ lnr->lr_id = ++next_listener_id;
+ rettv->vval.v_number = lnr->lr_id;
+ }
+
+ /*
+ * listener_remove() function
+ */
+ void
+ f_listener_remove(typval_T *argvars, typval_T *rettv UNUSED)
+ {
+ listener_T *lnr;
+ listener_T *next;
+ listener_T *prev = NULL;
+ int id = tv_get_number(argvars);
+ buf_T *buf = curbuf;
+
+ for (lnr = buf->b_listener; lnr != NULL; lnr = next)
+ {
+ next = lnr->lr_next;
+ if (lnr->lr_id == id)
+ {
+ if (prev != NULL)
+ prev->lr_next = lnr->lr_next;
+ else
+ buf->b_listener = lnr->lr_next;
+ free_callback(lnr->lr_callback, lnr->lr_partial);
+ vim_free(lnr);
+ }
+ prev = lnr;
+ }
+ }
+
+ /*
+ * Called when a sequence of changes is done: invoke listeners added with
+ * listener_add().
+ */
+ void
+ invoke_listeners(void)
+ {
+ listener_T *lnr;
+ typval_T rettv;
+ int dummy;
+ typval_T argv[2];
+
+ if (recorded_changes == NULL) // nothing changed
+ return;
+ argv[0].v_type = VAR_LIST;
+ argv[0].vval.v_list = recorded_changes;
+
+ for (lnr = curbuf->b_listener; lnr != NULL; lnr = lnr->lr_next)
+ {
+ call_func(lnr->lr_callback, -1, &rettv,
+ 1, argv, NULL, 0L, 0L, &dummy, TRUE, lnr->lr_partial, NULL);
+ clear_tv(&rettv);
+ }
+
+ list_unref(recorded_changes);
+ recorded_changes = NULL;
+ }
+ #endif
+
/*
* Common code for when a change was made.
* See changed_lines() for the arguments.
***************
*** 175,180 ****
--- 303,311 ----
// mark the buffer as modified
changed();
+ #ifdef FEAT_EVAL
+ may_record_change(lnum, col, lnume, xtra);
+ #endif
#ifdef FEAT_DIFF
if (curwin->w_p_diff && diff_internal())
curtab->tp_diff_update = TRUE;
*** ../vim-8.1.1319/src/proto/change.pro 2019-05-11 17:03:55.170019762
+0200
--- src/proto/change.pro 2019-05-11 18:24:29.733104385 +0200
***************
*** 2,7 ****
--- 2,10 ----
void change_warning(int col);
void changed(void);
void changed_internal(void);
+ void f_listener_add(typval_T *argvars, typval_T *rettv);
+ void f_listener_remove(typval_T *argvars, typval_T *rettv);
+ void invoke_listeners(void);
void changed_bytes(linenr_T lnum, colnr_T col);
void inserted_bytes(linenr_T lnum, colnr_T col, int added);
void appended_lines(linenr_T lnum, long count);
*** ../vim-8.1.1319/src/version.c 2019-05-11 18:28:41.351611622 +0200
--- src/version.c 2019-05-11 19:12:16.001896710 +0200
***************
*** 769,770 ****
--- 769,772 ----
{ /* Add new patch number below this line */
+ /**/
+ 1320,
/**/
--
It might look like I'm doing nothing, but at the cellular level
I'm really quite busy.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/201905111715.x4BHF4Px021582%40masaka.moolenaar.net.
For more options, visit https://groups.google.com/d/optout.