mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	fix(shada): update deleted marks (#24936)
Fix #4295 Close #16067 Co-authored-by: chentau <tchen1998@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							67fba9affa
						
					
				
				
					commit
					ee56daebb6
				
			@@ -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 ']':
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user