aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c5
-rw-r--r--src/nvim/auevents.lua2
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/change.c2
-rw-r--r--src/nvim/decoration.c4
-rw-r--r--src/nvim/edit.c8
-rw-r--r--src/nvim/eval/encode.c7
-rw-r--r--src/nvim/ex_cmds.c12
-rw-r--r--src/nvim/extmark.c1
-rw-r--r--src/nvim/marktree.c68
-rw-r--r--src/nvim/normal.c11
11 files changed, 78 insertions, 45 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 5050f1842d..cf822782d8 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -805,7 +805,7 @@ ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
}
int flags = DIP_START | (all ? DIP_ALL : 0);
- do_in_runtimepath(name.size ? (char_u *)name.data : NULL,
+ do_in_runtimepath((char_u *)name.data,
flags, find_runtime_cb, &rv);
return rv;
}
@@ -2687,6 +2687,9 @@ void nvim__screenshot(String path)
static void clear_provider(DecorProvider *p)
{
+ if (p == NULL) {
+ return;
+ }
NLUA_CLEAR_REF(p->redraw_start);
NLUA_CLEAR_REF(p->redraw_buf);
NLUA_CLEAR_REF(p->redraw_win);
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 9c28398f5b..6be51c504c 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -7,6 +7,7 @@ return {
'BufFilePre', -- before renaming a buffer
'BufHidden', -- just after buffer becomes hidden
'BufLeave', -- before leaving a buffer
+ 'BufModifiedSet', -- after the 'modified' state of a buffer changes
'BufNew', -- after creating any buffer
'BufNewFile', -- when creating a buffer for a new file
'BufReadCmd', -- read buffer using command
@@ -124,6 +125,7 @@ return {
-- List of nvim-specific events or aliases for the purpose of generating
-- syntax file
nvim_specific = {
+ BufModifiedSet=true,
DirChanged=true,
Signal=true,
TabClosed=true,
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 0b89dff92f..93fe37b585 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -541,6 +541,9 @@ struct file_buffer {
int b_changed; // 'modified': Set to true if something in the
// file has been changed and not written out.
+ bool b_changed_invalid; // Set if BufModified autocmd has not been
+ // triggered since the last time b_changed was
+ // modified.
/// Change-identifier incremented for each change, including undo.
///
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 9ee987b45d..271d350967 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -129,6 +129,7 @@ void changed(void)
void changed_internal(void)
{
curbuf->b_changed = true;
+ curbuf->b_changed_invalid = true;
ml_setflags(curbuf);
check_status(curbuf);
redraw_tabline = true;
@@ -502,6 +503,7 @@ void unchanged(buf_T *buf, int ff, bool always_inc_changedtick)
{
if (buf->b_changed || (ff && file_ff_differs(buf, false))) {
buf->b_changed = false;
+ buf->b_changed_invalid = true;
ml_setflags(buf);
if (ff) {
save_file_ff(buf);
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index d411f22e7a..0721c0c57b 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -182,7 +182,7 @@ bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
Decoration *decor = item->decor;
if ((!(mark.id&MARKTREE_END_FLAG) && altpos.row < top_row
- && item && !kv_size(decor->virt_text))
+ && !kv_size(decor->virt_text))
|| ((mark.id&MARKTREE_END_FLAG) && altpos.row >= top_row)) {
goto next_mark;
}
@@ -251,7 +251,7 @@ int decor_redraw_col(buf_T *buf, int col, DecorState *state)
if (endpos.row < mark.row
|| (endpos.row == mark.row && endpos.col <= mark.col)) {
- if (item && !kv_size(decor->virt_text)) {
+ if (!kv_size(decor->virt_text)) {
goto next_mark;
}
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index d7cca9ba36..9c8d64a6b2 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1488,6 +1488,14 @@ static void ins_redraw(
do_autocmd_winscrolled(curwin);
}
+ // Trigger BufModified if b_changed_invalid is set.
+ if (ready && has_event(EVENT_BUFMODIFIEDSET)
+ && curbuf->b_changed_invalid == true
+ && !pum_visible()) {
+ apply_autocmds(EVENT_BUFMODIFIEDSET, NULL, NULL, false, curbuf);
+ curbuf->b_changed_invalid = false;
+ }
+
if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin)
&& conceal_cursor_moved) {
redrawWinline(curwin, curwin->w_cursor.lnum);
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 137f099df6..9a9f2e4287 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -159,8 +159,11 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
vim_snprintf((char *)IObuff, IOSIZE, idx_msg, idx);
ga_concat(&msg_ga, IObuff);
} else {
- typval_T key_tv = *TV_LIST_ITEM_TV(
- tv_list_first(TV_LIST_ITEM_TV(li)->vval.v_list));
+ assert(li != NULL);
+ listitem_T *const first_item =
+ tv_list_first(TV_LIST_ITEM_TV(li)->vval.v_list);
+ assert(first_item != NULL);
+ typval_T key_tv = *TV_LIST_ITEM_TV(first_item);
char *const key = encode_tv2echo(&key_tv, NULL);
vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx);
xfree(key);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 3e49d7845d..55366842b0 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3451,13 +3451,13 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
sub_firstline = NULL;
- /*
- * ~ in the substitute pattern is replaced with the old pattern.
- * We do it here once to avoid it to be replaced over and over again.
- * But don't do it when it starts with "\=", then it's an expression.
- */
- if (!(sub[0] == '\\' && sub[1] == '='))
+ // ~ in the substitute pattern is replaced with the old pattern.
+ // We do it here once to avoid it to be replaced over and over again.
+ // But don't do it when it starts with "\=", then it's an expression.
+ assert(sub != NULL);
+ if (!(sub[0] == '\\' && sub[1] == '=')) {
sub = regtilde(sub, p_magic);
+ }
// Check for a match on each line.
// If preview: limit to max('cmdwinheight', viewport).
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 413ea4116a..ba685b158e 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -74,6 +74,7 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
Decoration *decor, ExtmarkOp op)
{
ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true);
+ assert(ns != NULL);
mtpos_t old_pos;
uint64_t mark = 0;
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 6dd452b5af..e9ea2cbba9 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -326,38 +326,37 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
x->n--;
// 4.
- if (adjustment) {
- if (adjustment == 1) {
- abort();
- } else { // adjustment == -1
- int ilvl = itr->lvl-1;
- mtnode_t *lnode = x;
- do {
- mtnode_t *p = lnode->parent;
- if (ilvl < 0) {
- abort();
- }
- int i = itr->s[ilvl].i;
- assert(p->ptr[i] == lnode);
- if (i > 0) {
- unrelative(p->key[i-1].pos, &intkey.pos);
- }
- lnode = p;
- ilvl--;
- } while (lnode != cur);
-
- mtkey_t deleted = cur->key[curi];
- cur->key[curi] = intkey;
- refkey(b, cur, curi);
- relative(intkey.pos, &deleted.pos);
- mtnode_t *y = cur->ptr[curi+1];
- if (deleted.pos.row || deleted.pos.col) {
- while (y) {
- for (int k = 0; k < y->n; k++) {
- unrelative(deleted.pos, &y->key[k].pos);
- }
- y = y->level ? y->ptr[0] : NULL;
+ // if (adjustment == 1) {
+ // abort();
+ // }
+ if (adjustment == -1) {
+ int ilvl = itr->lvl-1;
+ const mtnode_t *lnode = x;
+ do {
+ const mtnode_t *const p = lnode->parent;
+ if (ilvl < 0) {
+ abort();
+ }
+ const int i = itr->s[ilvl].i;
+ assert(p->ptr[i] == lnode);
+ if (i > 0) {
+ unrelative(p->key[i-1].pos, &intkey.pos);
+ }
+ lnode = p;
+ ilvl--;
+ } while (lnode != cur);
+
+ mtkey_t deleted = cur->key[curi];
+ cur->key[curi] = intkey;
+ refkey(b, cur, curi);
+ relative(intkey.pos, &deleted.pos);
+ mtnode_t *y = cur->ptr[curi+1];
+ if (deleted.pos.row || deleted.pos.col) {
+ while (y) {
+ for (int k = 0; k < y->n; k++) {
+ unrelative(deleted.pos, &y->key[k].pos);
}
+ y = y->level ? y->ptr[0] : NULL;
}
}
}
@@ -435,9 +434,10 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
// BONUS STEP: fix the iterator, so that it points to the key afterwards
// TODO(bfredl): with "rev" should point before
- if (adjustment == 1) {
- abort();
- } else if (adjustment == -1) {
+ // if (adjustment == 1) {
+ // abort();
+ // }
+ if (adjustment == -1) {
// tricky: we stand at the deleted space in the previous leaf node.
// But the inner key is now the previous key we stole, so we need
// to skip that one as well.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 771ca732f4..2805a7d74e 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1229,6 +1229,16 @@ static void normal_check_text_changed(NormalState *s)
}
}
+static void normal_check_buffer_modified(NormalState *s)
+{
+ // Trigger BufModified if b_modified changed
+ if (!finish_op && has_event(EVENT_BUFMODIFIEDSET)
+ && curbuf->b_changed_invalid == true) {
+ apply_autocmds(EVENT_BUFMODIFIEDSET, NULL, NULL, false, curbuf);
+ curbuf->b_changed_invalid = false;
+ }
+}
+
static void normal_check_folds(NormalState *s)
{
// Include a closed fold completely in the Visual area.
@@ -1336,6 +1346,7 @@ static int normal_check(VimState *state)
normal_check_cursor_moved(s);
normal_check_text_changed(s);
normal_check_window_scrolled(s);
+ normal_check_buffer_modified(s);
// Updating diffs from changed() does not always work properly,
// esp. updating folds. Do an update just before redrawing if