mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
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.
This commit is contained in:
parent
6ed8819822
commit
6d2399bd10
131
src/change.c
131
src/change.c
@ -151,6 +151,134 @@ changed_internal(void)
|
||||
#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,6 +303,9 @@ changed_common(
|
||||
// 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;
|
||||
|
@ -2,6 +2,9 @@
|
||||
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);
|
||||
|
@ -1873,6 +1873,19 @@ typedef struct
|
||||
#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,6 +2437,8 @@ struct file_buffer
|
||||
#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
|
||||
|
@ -767,6 +767,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1320,
|
||||
/**/
|
||||
1319,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user