aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria José Solano <majosolano99@gmail.com>2023-08-30 19:15:49 -0700
committerGitHub <noreply@github.com>2023-08-31 10:15:49 +0800
commitee56daebb6468075e743db0d605cb3f2a1699419 (patch)
treeee662a8897eec0b372f880d514f5f3fe2e325988
parent67fba9affa14f2f3cd30371568c01d39f3e5f4d4 (diff)
downloadrneovim-ee56daebb6468075e743db0d605cb3f2a1699419.tar.gz
rneovim-ee56daebb6468075e743db0d605cb3f2a1699419.tar.bz2
rneovim-ee56daebb6468075e743db0d605cb3f2a1699419.zip
fix(shada): update deleted marks (#24936)
Fix #4295 Close #16067 Co-authored-by: chentau <tchen1998@gmail.com>
-rw-r--r--src/nvim/mark.c18
-rw-r--r--src/nvim/mark_defs.h3
-rw-r--r--src/nvim/shada.c24
-rw-r--r--test/functional/shada/marks_spec.lua21
4 files changed, 59 insertions, 7 deletions
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 39fc623676..6480a47344 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -51,9 +51,6 @@
// There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
// shada).
-/// Global marks (marks with file number or name)
-static xfmark_T namedfm[NGLOBALMARKS];
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mark.c.generated.h"
#endif
@@ -935,6 +932,7 @@ void ex_delmarks(exarg_T *eap)
emsg(_(e_argreq));
} else {
// clear specified marks only
+ const Timestamp timestamp = os_time();
for (p = eap->arg; *p != NUL; p++) {
lower = ASCII_ISLOWER(*p);
digit = ascii_isdigit(*p);
@@ -959,6 +957,7 @@ void ex_delmarks(exarg_T *eap)
for (int i = from; i <= to; i++) {
if (lower) {
curbuf->b_namedm[i - 'a'].mark.lnum = 0;
+ curbuf->b_namedm[i - 'a'].timestamp = timestamp;
} else {
if (digit) {
n = i - '0' + NMARKS;
@@ -967,17 +966,24 @@ void ex_delmarks(exarg_T *eap)
}
namedfm[n].fmark.mark.lnum = 0;
namedfm[n].fmark.fnum = 0;
+ namedfm[n].fmark.timestamp = timestamp;
XFREE_CLEAR(namedfm[n].fname);
}
}
} else {
switch (*p) {
case '"':
- CLEAR_FMARK(&curbuf->b_last_cursor); break;
+ curbuf->b_last_cursor.timestamp = timestamp;
+ CLEAR_FMARK(&curbuf->b_last_cursor);
+ break;
case '^':
- CLEAR_FMARK(&curbuf->b_last_insert); break;
+ curbuf->b_last_insert.timestamp = timestamp;
+ CLEAR_FMARK(&curbuf->b_last_insert);
+ break;
case '.':
- CLEAR_FMARK(&curbuf->b_last_change); break;
+ curbuf->b_last_change.timestamp = timestamp;
+ CLEAR_FMARK(&curbuf->b_last_change);
+ break;
case '[':
curbuf->b_op_start.lnum = 0; break;
case ']':
diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h
index cfe19eac6f..6be919a7ab 100644
--- a/src/nvim/mark_defs.h
+++ b/src/nvim/mark_defs.h
@@ -86,4 +86,7 @@ typedef struct xfilemark {
#define INIT_XFMARK { INIT_FMARK, NULL }
+/// Global marks (marks with file number or name)
+EXTERN xfmark_T namedfm[NGLOBALMARKS] INIT(= { 0 });
+
#endif // NVIM_MARK_DEFS_H
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index f8c448dce0..49136402ac 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -2160,6 +2160,12 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
shada_free_shada_entry(&entry);
break;
}
+ if (wms->global_marks[idx].data.type == kSDItemMissing) {
+ if (namedfm[idx].fmark.timestamp >= entry.timestamp) {
+ shada_free_shada_entry(&entry);
+ break;
+ }
+ }
COMPARE_WITH_ENTRY(&wms->global_marks[idx], entry);
}
break;
@@ -2189,6 +2195,7 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
entry;
} else {
PossiblyFreedShadaEntry *const wms_entry = &filemarks->marks[idx];
+ bool set_wms = true;
if (wms_entry->data.type != kSDItemMissing) {
if (wms_entry->data.timestamp >= entry.timestamp) {
shada_free_shada_entry(&entry);
@@ -2200,8 +2207,23 @@ static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_re
}
shada_free_shada_entry(&wms_entry->data);
}
+ } else {
+ FOR_ALL_BUFFERS(buf) {
+ if (buf->b_ffname != NULL
+ && path_fnamecmp(entry.data.filemark.fname, buf->b_ffname) == 0) {
+ fmark_T fm;
+ mark_get(buf, curwin, &fm, kMarkBufLocal, (int)entry.data.filemark.name);
+ if (fm.timestamp >= entry.timestamp) {
+ set_wms = false;
+ shada_free_shada_entry(&entry);
+ break;
+ }
+ }
+ }
+ }
+ if (set_wms) {
+ *wms_entry = pfs_entry;
}
- *wms_entry = pfs_entry;
}
} else {
#define AFTERFREE_DUMMY(entry)
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index a91be18841..07364382e8 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq =
helpers.meths, helpers.curwinmeths, helpers.curbufmeths, helpers.command,
helpers.funcs, helpers.eq
+local feed = helpers.feed
local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
local expect_exit = helpers.expect_exit
@@ -248,4 +249,24 @@ describe('ShaDa support code', function()
eq('', funcs.system(argv))
eq(0, exc_exec('rshada'))
end)
+
+ it('updates deleted marks', function()
+ nvim_command('edit ' .. testfilename)
+
+ nvim_command('mark A')
+ nvim_command('mark a')
+ -- create a change to set the '.' mark,
+ -- since it can't be set via :mark
+ feed('ggifoobar<esc>')
+ nvim_command('wshada')
+ nvim_command('normal! `A`a`.')
+
+ nvim_command('delmarks A a .')
+ nvim_command('wshada')
+
+ reset()
+ eq('Vim(normal):E20: Mark not set', exc_exec('normal! `A'))
+ eq('Vim(normal):E20: Mark not set', exc_exec('normal! `a'))
+ eq('Vim(normal):E20: Mark not set', exc_exec('normal! `.'))
+ end)
end)