mirror of
https://github.com/neovim/neovim.git
synced 2025-09-15 15:58:17 +00:00
shada: Add support for dumping/restoring bufs changes and win jumps
This commit is contained in:
@@ -23,6 +23,7 @@ class EntryTypes(Enum):
|
|||||||
Jump = 8
|
Jump = 8
|
||||||
BufferList = 9
|
BufferList = 9
|
||||||
LocalMark = 10
|
LocalMark = 10
|
||||||
|
Change = 11
|
||||||
|
|
||||||
|
|
||||||
def strtrans_errors(e):
|
def strtrans_errors(e):
|
||||||
|
@@ -562,6 +562,9 @@ static void free_buffer(buf_T *buf)
|
|||||||
for (size_t i = 0; i < NMARKS; i++) {
|
for (size_t i = 0; i < NMARKS; i++) {
|
||||||
free_fmark(buf->b_namedm[i]);
|
free_fmark(buf->b_namedm[i]);
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < buf->b_changelistlen; i++) {
|
||||||
|
free_fmark(buf->b_changelist[i]);
|
||||||
|
}
|
||||||
if (autocmd_busy) {
|
if (autocmd_busy) {
|
||||||
// Do not free the buffer structure while autocommands are executing,
|
// Do not free the buffer structure while autocommands are executing,
|
||||||
// it's still needed. Free it when autocmd_busy is reset.
|
// it's still needed. Free it when autocmd_busy is reset.
|
||||||
|
@@ -520,7 +520,7 @@ struct file_buffer {
|
|||||||
/*
|
/*
|
||||||
* the changelist contains old change positions
|
* the changelist contains old change positions
|
||||||
*/
|
*/
|
||||||
pos_T b_changelist[JUMPLISTSIZE];
|
fmark_T b_changelist[JUMPLISTSIZE];
|
||||||
int b_changelistlen; /* number of active entries */
|
int b_changelistlen; /* number of active entries */
|
||||||
bool b_new_change; /* set by u_savecommon() */
|
bool b_new_change; /* set by u_savecommon() */
|
||||||
|
|
||||||
|
@@ -577,6 +577,19 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
|
|||||||
code; \
|
code; \
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
/*! @function
|
||||||
|
@abstract Iterate over the keys in the hash table
|
||||||
|
@param h Pointer to the hash table [khash_t(name)*]
|
||||||
|
@param kvar Variable to which value will be assigned
|
||||||
|
@param code Block of code to execute
|
||||||
|
*/
|
||||||
|
#define kh_foreach_key(h, kvar, code) { khint_t __i; \
|
||||||
|
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
|
||||||
|
if (!kh_exist(h,__i)) continue; \
|
||||||
|
(kvar) = kh_key(h,__i); \
|
||||||
|
code; \
|
||||||
|
} }
|
||||||
|
|
||||||
/* More conenient interfaces */
|
/* More conenient interfaces */
|
||||||
|
|
||||||
/*! @function
|
/*! @function
|
||||||
|
@@ -59,14 +59,6 @@
|
|||||||
/// Global marks (marks with file number or name)
|
/// Global marks (marks with file number or name)
|
||||||
static xfmark_T namedfm[NGLOBALMARKS];
|
static xfmark_T namedfm[NGLOBALMARKS];
|
||||||
|
|
||||||
#define SET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \
|
|
||||||
do { \
|
|
||||||
xfmark_T *const xfmarkp__ = xfmarkp_; \
|
|
||||||
xfmarkp__->fname = fname_; \
|
|
||||||
RESET_FMARK(&(xfmarkp__->fmark), mark_, fnum_); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "mark.c.generated.h"
|
# include "mark.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -85,11 +77,12 @@ void free_fmark(fmark_T fm)
|
|||||||
if (fm.additional_data != NULL) {
|
if (fm.additional_data != NULL) {
|
||||||
api_free_dictionary(*fm.additional_data);
|
api_free_dictionary(*fm.additional_data);
|
||||||
free(fm.additional_data);
|
free(fm.additional_data);
|
||||||
|
fm.additional_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Free xfmark_T item
|
/// Free xfmark_T item
|
||||||
static inline void free_xfmark(xfmark_T fm)
|
void free_xfmark(xfmark_T fm)
|
||||||
{
|
{
|
||||||
xfree(fm.fname);
|
xfree(fm.fname);
|
||||||
fm.fname = NULL;
|
fm.fname = NULL;
|
||||||
@@ -157,8 +150,7 @@ int setmark_pos(int c, pos_T *pos, int fnum)
|
|||||||
if (isupper(c)) {
|
if (isupper(c)) {
|
||||||
assert(c >= 'A' && c <= 'Z');
|
assert(c >= 'A' && c <= 'Z');
|
||||||
i = c - 'A';
|
i = c - 'A';
|
||||||
free_xfmark(namedfm[i]);
|
RESET_XFMARK(namedfm + i, *pos, fnum, NULL);
|
||||||
SET_XFMARK(namedfm + i, *pos, fnum, NULL);
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -170,7 +162,6 @@ int setmark_pos(int c, pos_T *pos, int fnum)
|
|||||||
*/
|
*/
|
||||||
void setpcmark(void)
|
void setpcmark(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
xfmark_T *fm;
|
xfmark_T *fm;
|
||||||
|
|
||||||
/* for :global the mark is set only once */
|
/* for :global the mark is set only once */
|
||||||
@@ -184,8 +175,8 @@ void setpcmark(void)
|
|||||||
if (++curwin->w_jumplistlen > JUMPLISTSIZE) {
|
if (++curwin->w_jumplistlen > JUMPLISTSIZE) {
|
||||||
curwin->w_jumplistlen = JUMPLISTSIZE;
|
curwin->w_jumplistlen = JUMPLISTSIZE;
|
||||||
free_xfmark(curwin->w_jumplist[0]);
|
free_xfmark(curwin->w_jumplist[0]);
|
||||||
for (i = 1; i < JUMPLISTSIZE; ++i)
|
memmove(&curwin->w_jumplist[0], &curwin->w_jumplist[1],
|
||||||
curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
|
(JUMPLISTSIZE - 1) * sizeof(curwin->w_jumplist[0]));
|
||||||
}
|
}
|
||||||
curwin->w_jumplistidx = curwin->w_jumplistlen;
|
curwin->w_jumplistidx = curwin->w_jumplistlen;
|
||||||
fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
|
fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
|
||||||
@@ -284,7 +275,7 @@ pos_T *movechangelist(int count)
|
|||||||
} else
|
} else
|
||||||
n += count;
|
n += count;
|
||||||
curwin->w_changelistidx = n;
|
curwin->w_changelistidx = n;
|
||||||
return curbuf->b_changelist + n;
|
return &(curbuf->b_changelist[n].mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -829,7 +820,7 @@ void ex_changes(exarg_T *eap)
|
|||||||
MSG_PUTS_TITLE(_("\nchange line col text"));
|
MSG_PUTS_TITLE(_("\nchange line col text"));
|
||||||
|
|
||||||
for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i) {
|
for (i = 0; i < curbuf->b_changelistlen && !got_int; ++i) {
|
||||||
if (curbuf->b_changelist[i].lnum != 0) {
|
if (curbuf->b_changelist[i].mark.lnum != 0) {
|
||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
if (got_int)
|
if (got_int)
|
||||||
break;
|
break;
|
||||||
@@ -837,10 +828,10 @@ void ex_changes(exarg_T *eap)
|
|||||||
i == curwin->w_changelistidx ? '>' : ' ',
|
i == curwin->w_changelistidx ? '>' : ' ',
|
||||||
i > curwin->w_changelistidx ? i - curwin->w_changelistidx
|
i > curwin->w_changelistidx ? i - curwin->w_changelistidx
|
||||||
: curwin->w_changelistidx - i,
|
: curwin->w_changelistidx - i,
|
||||||
(long)curbuf->b_changelist[i].lnum,
|
(long)curbuf->b_changelist[i].mark.lnum,
|
||||||
curbuf->b_changelist[i].col);
|
curbuf->b_changelist[i].mark.col);
|
||||||
msg_outtrans(IObuff);
|
msg_outtrans(IObuff);
|
||||||
name = mark_line(&curbuf->b_changelist[i], 17);
|
name = mark_line(&curbuf->b_changelist[i].mark, 17);
|
||||||
msg_outtrans_attr(name, hl_attr(HLF_D));
|
msg_outtrans_attr(name, hl_attr(HLF_D));
|
||||||
xfree(name);
|
xfree(name);
|
||||||
os_breakcheck();
|
os_breakcheck();
|
||||||
@@ -926,7 +917,7 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after)
|
|||||||
|
|
||||||
/* list of change positions */
|
/* list of change positions */
|
||||||
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
||||||
one_adjust_nodel(&(curbuf->b_changelist[i].lnum));
|
one_adjust_nodel(&(curbuf->b_changelist[i].mark.lnum));
|
||||||
|
|
||||||
/* Visual area */
|
/* Visual area */
|
||||||
one_adjust_nodel(&(curbuf->b_visual.vi_start.lnum));
|
one_adjust_nodel(&(curbuf->b_visual.vi_start.lnum));
|
||||||
@@ -1073,7 +1064,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long col_a
|
|||||||
|
|
||||||
/* list of change positions */
|
/* list of change positions */
|
||||||
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
for (i = 0; i < curbuf->b_changelistlen; ++i)
|
||||||
col_adjust(&(curbuf->b_changelist[i]));
|
col_adjust(&(curbuf->b_changelist[i].mark));
|
||||||
|
|
||||||
/* Visual area */
|
/* Visual area */
|
||||||
col_adjust(&(curbuf->b_visual.vi_start));
|
col_adjust(&(curbuf->b_visual.vi_start));
|
||||||
@@ -1119,7 +1110,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long col_a
|
|||||||
* When deleting lines, this may create duplicate marks in the
|
* When deleting lines, this may create duplicate marks in the
|
||||||
* jumplist. They will be removed here for the current window.
|
* jumplist. They will be removed here for the current window.
|
||||||
*/
|
*/
|
||||||
static void cleanup_jumplist(void)
|
void cleanup_jumplist(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int from, to;
|
int from, to;
|
||||||
|
@@ -3,24 +3,49 @@
|
|||||||
|
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
#include "nvim/mark_defs.h"
|
#include "nvim/mark_defs.h"
|
||||||
|
#include "nvim/memory.h"
|
||||||
#include "nvim/pos.h"
|
#include "nvim/pos.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
|
|
||||||
/// Free and set fmark using given value
|
/// Set fmark using given value
|
||||||
#define RESET_FMARK(fmarkp_, mark_, fnum_) \
|
#define SET_FMARK(fmarkp_, mark_, fnum_) \
|
||||||
do { \
|
do { \
|
||||||
fmark_T *const fmarkp__ = fmarkp_; \
|
fmark_T *const fmarkp__ = fmarkp_; \
|
||||||
free_fmark(*fmarkp__); \
|
|
||||||
fmarkp__->mark = mark_; \
|
fmarkp__->mark = mark_; \
|
||||||
fmarkp__->fnum = fnum_; \
|
fmarkp__->fnum = fnum_; \
|
||||||
fmarkp__->timestamp = os_time(); \
|
fmarkp__->timestamp = os_time(); \
|
||||||
fmarkp__->additional_data = NULL; \
|
fmarkp__->additional_data = NULL; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/// Free and set fmark using given value
|
||||||
|
#define RESET_FMARK(fmarkp_, mark_, fnum_) \
|
||||||
|
do { \
|
||||||
|
fmark_T *const fmarkp___ = fmarkp_; \
|
||||||
|
free_fmark(*fmarkp___); \
|
||||||
|
SET_FMARK(fmarkp___, mark_, fnum_); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/// Clear given fmark
|
/// Clear given fmark
|
||||||
#define CLEAR_FMARK(fmarkp_) \
|
#define CLEAR_FMARK(fmarkp_) \
|
||||||
RESET_FMARK(fmarkp_, ((pos_T) {0, 0, 0}), 0)
|
RESET_FMARK(fmarkp_, ((pos_T) {0, 0, 0}), 0)
|
||||||
|
|
||||||
|
/// Set given extended mark (regular mark + file name)
|
||||||
|
#define SET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \
|
||||||
|
do { \
|
||||||
|
xfmark_T *const xfmarkp__ = xfmarkp_; \
|
||||||
|
xfmarkp__->fname = fname_; \
|
||||||
|
SET_FMARK(&(xfmarkp__->fmark), mark_, fnum_); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/// Free and set given extended mark (regular mark + file name)
|
||||||
|
#define RESET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \
|
||||||
|
do { \
|
||||||
|
xfmark_T *const xfmarkp__ = xfmarkp_; \
|
||||||
|
free_xfmark(*xfmarkp__); \
|
||||||
|
xfmarkp__->fname = fname_; \
|
||||||
|
SET_FMARK(&(xfmarkp__->fmark), mark_, fnum_); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "mark.h.generated.h"
|
# include "mark.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2053,7 +2053,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
|
|||||||
/* Don't create a new entry when the line number is the same
|
/* Don't create a new entry when the line number is the same
|
||||||
* as the last one and the column is not too far away. Avoids
|
* as the last one and the column is not too far away. Avoids
|
||||||
* creating many entries for typing "xxxxx". */
|
* creating many entries for typing "xxxxx". */
|
||||||
p = &curbuf->b_changelist[curbuf->b_changelistlen - 1];
|
p = &curbuf->b_changelist[curbuf->b_changelistlen - 1].mark;
|
||||||
if (p->lnum != lnum)
|
if (p->lnum != lnum)
|
||||||
add = TRUE;
|
add = TRUE;
|
||||||
else {
|
else {
|
||||||
@@ -2073,7 +2073,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
|
|||||||
/* changelist is full: remove oldest entry */
|
/* changelist is full: remove oldest entry */
|
||||||
curbuf->b_changelistlen = JUMPLISTSIZE - 1;
|
curbuf->b_changelistlen = JUMPLISTSIZE - 1;
|
||||||
memmove(curbuf->b_changelist, curbuf->b_changelist + 1,
|
memmove(curbuf->b_changelist, curbuf->b_changelist + 1,
|
||||||
sizeof(pos_T) * (JUMPLISTSIZE - 1));
|
sizeof(curbuf->b_changelist[0]) * (JUMPLISTSIZE - 1));
|
||||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||||
/* Correct position in changelist for other windows on
|
/* Correct position in changelist for other windows on
|
||||||
* this buffer. */
|
* this buffer. */
|
||||||
@@ -2094,7 +2094,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
curbuf->b_changelist[curbuf->b_changelistlen - 1] =
|
curbuf->b_changelist[curbuf->b_changelistlen - 1] =
|
||||||
curbuf->b_last_change.mark;
|
curbuf->b_last_change;
|
||||||
/* The current window is always after the last change, so that "g,"
|
/* The current window is always after the last change, so that "g,"
|
||||||
* takes you back to it. */
|
* takes you back to it. */
|
||||||
curwin->w_changelistidx = curbuf->b_changelistlen;
|
curwin->w_changelistidx = curbuf->b_changelistlen;
|
||||||
|
303
src/nvim/shada.c
303
src/nvim/shada.c
@@ -43,8 +43,20 @@
|
|||||||
#include "nvim/version.h"
|
#include "nvim/version.h"
|
||||||
#include "nvim/path.h"
|
#include "nvim/path.h"
|
||||||
#include "nvim/lib/ringbuf.h"
|
#include "nvim/lib/ringbuf.h"
|
||||||
|
#include "nvim/lib/khash.h"
|
||||||
|
|
||||||
|
// Note: when using bufset hash pointers are intentionally casted to uintptr_t
|
||||||
|
// and not to khint32_t or khint64_t: this way compiler must give a warning
|
||||||
|
// (-Wconversion) when types change.
|
||||||
|
#ifdef ARCH_32
|
||||||
|
KHASH_SET_INIT_INT(bufset)
|
||||||
|
#elif defined(ARCH_64)
|
||||||
|
KHASH_SET_INIT_INT64(bufset)
|
||||||
|
#else
|
||||||
|
# error Not a 64- or 32-bit architecture
|
||||||
|
#endif
|
||||||
|
KHASH_MAP_INIT_STR(fnamebufs, buf_T *)
|
||||||
|
|
||||||
#define buflist_nr2name(...) ((char *) buflist_nr2name(__VA_ARGS__))
|
|
||||||
#define copy_option_part(src, dest, ...) \
|
#define copy_option_part(src, dest, ...) \
|
||||||
((char *) copy_option_part((char_u **) src, (char_u *) dest, __VA_ARGS__))
|
((char *) copy_option_part((char_u **) src, (char_u *) dest, __VA_ARGS__))
|
||||||
#define find_viminfo_parameter(...) \
|
#define find_viminfo_parameter(...) \
|
||||||
@@ -112,7 +124,8 @@ typedef enum {
|
|||||||
kSDItemJump = 8, ///< Item from jump list.
|
kSDItemJump = 8, ///< Item from jump list.
|
||||||
kSDItemBufferList = 9, ///< Buffer list.
|
kSDItemBufferList = 9, ///< Buffer list.
|
||||||
kSDItemLocalMark = 10, ///< Buffer-local mark.
|
kSDItemLocalMark = 10, ///< Buffer-local mark.
|
||||||
#define SHADA_LAST_ENTRY ((uint64_t) kSDItemLocalMark)
|
kSDItemChange = 11, ///< Item from buffer change list.
|
||||||
|
#define SHADA_LAST_ENTRY ((uint64_t) kSDItemChange)
|
||||||
} ShadaEntryType;
|
} ShadaEntryType;
|
||||||
|
|
||||||
/// Structure defining a single ShaDa file entry
|
/// Structure defining a single ShaDa file entry
|
||||||
@@ -329,6 +342,40 @@ static void insert_history_entry(HistoryMergerState *const hms_p,
|
|||||||
hm_rb_insert(rb, (size_t) (hm_rb_find_idx(rb, insert_after) + 1), entry);
|
hm_rb_insert(rb, (size_t) (hm_rb_find_idx(rb, insert_after) + 1), entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find buffer for given buffer name (cached)
|
||||||
|
///
|
||||||
|
/// @param[in,out] fname_bufs Cache containing fname to buffer mapping.
|
||||||
|
/// @param[in] fname File name to find.
|
||||||
|
///
|
||||||
|
/// @return Pointer to the buffer or NULL.
|
||||||
|
static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs,
|
||||||
|
const char *const fname)
|
||||||
|
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
int kh_ret;
|
||||||
|
khint_t k = kh_put(fnamebufs, fname_bufs, fname, &kh_ret);
|
||||||
|
if (!kh_ret) {
|
||||||
|
return kh_val(fname_bufs, k);
|
||||||
|
}
|
||||||
|
kh_key(fname_bufs, k) = xstrdup(fname);
|
||||||
|
FOR_ALL_BUFFERS(buf) {
|
||||||
|
if (buf->b_ffname != NULL) {
|
||||||
|
if (fnamecmp(fname, buf->b_ffname) == 0) {
|
||||||
|
kh_val(fname_bufs, k) = buf;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kh_val(fname_bufs, k) = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare two marks
|
||||||
|
static inline bool marks_equal(const pos_T a, const pos_T b)
|
||||||
|
{
|
||||||
|
return (a.lnum == b.lnum) && (a.col == b.col);
|
||||||
|
}
|
||||||
|
|
||||||
/// Read data from ShaDa file
|
/// Read data from ShaDa file
|
||||||
///
|
///
|
||||||
/// @param[in] fp File to read from.
|
/// @param[in] fp File to read from.
|
||||||
@@ -346,9 +393,8 @@ static void shada_read(FILE *const fp, const int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShadaEntry cur_entry;
|
ShadaEntry cur_entry;
|
||||||
buf_T *local_mark_prev_buf = NULL;
|
khash_t(bufset) *cl_bufs = kh_init(bufset);
|
||||||
char *local_mark_prev_fname = NULL;
|
khash_t(fnamebufs) *fname_bufs = kh_init(fnamebufs);
|
||||||
size_t local_mark_prev_fname_len = 0;
|
|
||||||
while (shada_read_next_item(fp, &cur_entry, flags) == NOTDONE) {
|
while (shada_read_next_item(fp, &cur_entry, flags) == NOTDONE) {
|
||||||
switch (cur_entry.type) {
|
switch (cur_entry.type) {
|
||||||
case kSDItemMissing: {
|
case kSDItemMissing: {
|
||||||
@@ -455,71 +501,182 @@ static void shada_read(FILE *const fp, const int flags)
|
|||||||
shada_free_shada_entry(&cur_entry);
|
shada_free_shada_entry(&cur_entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSDItemJump:
|
||||||
case kSDItemGlobalMark: {
|
case kSDItemGlobalMark: {
|
||||||
if (!(flags & kShaDaWantMarks) || get_viminfo_parameter('f') == 0) {
|
if (!(flags & kShaDaWantMarks)
|
||||||
|
|| (cur_entry.type == kSDItemGlobalMark
|
||||||
|
&& get_viminfo_parameter('f') == 0)) {
|
||||||
shada_free_shada_entry(&cur_entry);
|
shada_free_shada_entry(&cur_entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mark_set_global(cur_entry.data.filemark.name, (xfmark_T) {
|
buf_T *buf = find_buffer(fname_bufs, cur_entry.data.filemark.fname);
|
||||||
.fname = (char_u *) cur_entry.data.filemark.fname,
|
if (buf != NULL) {
|
||||||
|
xfree(cur_entry.data.filemark.fname);
|
||||||
|
cur_entry.data.filemark.fname = NULL;
|
||||||
|
}
|
||||||
|
xfmark_T fm = (xfmark_T) {
|
||||||
|
.fname = (char_u *) (buf == NULL
|
||||||
|
? cur_entry.data.filemark.fname
|
||||||
|
: NULL),
|
||||||
.fmark = {
|
.fmark = {
|
||||||
.mark = cur_entry.data.filemark.mark,
|
.mark = cur_entry.data.filemark.mark,
|
||||||
.fnum = 0,
|
.fnum = (buf == NULL ? 0 : buf->b_fnum),
|
||||||
.timestamp = cur_entry.timestamp,
|
.timestamp = cur_entry.timestamp,
|
||||||
.additional_data = cur_entry.data.filemark.additional_data,
|
.additional_data = cur_entry.data.filemark.additional_data,
|
||||||
},
|
},
|
||||||
}, !(flags & kShaDaForceit));
|
};
|
||||||
|
if (cur_entry.type == kSDItemGlobalMark) {
|
||||||
|
mark_set_global(cur_entry.data.filemark.name, fm,
|
||||||
|
!(flags & kShaDaForceit));
|
||||||
|
} else {
|
||||||
|
if (flags & kShaDaForceit) {
|
||||||
|
if (curwin->w_jumplistlen == JUMPLISTSIZE) {
|
||||||
|
// Jump list items are ignored in this case.
|
||||||
|
free_xfmark(fm);
|
||||||
|
} else {
|
||||||
|
memmove(&curwin->w_jumplist[1], &curwin->w_jumplist[0],
|
||||||
|
sizeof(curwin->w_jumplist[0])
|
||||||
|
* (size_t) curwin->w_jumplistlen);
|
||||||
|
curwin->w_jumplistidx++;
|
||||||
|
curwin->w_jumplistlen++;
|
||||||
|
curwin->w_jumplist[0] = fm;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const int jl_len = curwin->w_jumplistlen;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < jl_len; i++) {
|
||||||
|
const xfmark_T jl_fm = curwin->w_jumplist[i];
|
||||||
|
if (jl_fm.fmark.timestamp >= cur_entry.timestamp) {
|
||||||
|
if (marks_equal(fm.fmark.mark, jl_fm.fmark.mark)
|
||||||
|
&& (buf == NULL
|
||||||
|
? (jl_fm.fname != NULL
|
||||||
|
&& STRCMP(fm.fname, jl_fm.fname) == 0)
|
||||||
|
: fm.fmark.fnum == jl_fm.fmark.fnum)) {
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i != -1) {
|
||||||
|
if (i < jl_len) {
|
||||||
|
if (jl_len == JUMPLISTSIZE) {
|
||||||
|
free_xfmark(curwin->w_jumplist[0]);
|
||||||
|
memmove(&curwin->w_jumplist[0], &curwin->w_jumplist[1],
|
||||||
|
sizeof(curwin->w_jumplist[0]) * (size_t) i);
|
||||||
|
} else {
|
||||||
|
memmove(&curwin->w_jumplist[i + 1], &curwin->w_jumplist[i],
|
||||||
|
sizeof(curwin->w_jumplist[0])
|
||||||
|
* (size_t) (jl_len - i));
|
||||||
|
}
|
||||||
|
} else if (i == jl_len) {
|
||||||
|
if (jl_len == JUMPLISTSIZE) {
|
||||||
|
i = -1;
|
||||||
|
} else if (jl_len > 0) {
|
||||||
|
memmove(&curwin->w_jumplist[1], &curwin->w_jumplist[0],
|
||||||
|
sizeof(curwin->w_jumplist[0])
|
||||||
|
* (size_t) jl_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i != -1) {
|
||||||
|
curwin->w_jumplist[i] = fm;
|
||||||
|
if (jl_len < JUMPLISTSIZE) {
|
||||||
|
curwin->w_jumplistlen++;
|
||||||
|
}
|
||||||
|
if (curwin->w_jumplistidx > i
|
||||||
|
&& curwin->w_jumplistidx + 1 < curwin->w_jumplistlen) {
|
||||||
|
curwin->w_jumplistidx++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shada_free_shada_entry(&cur_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Do not free shada entry: its allocated memory was saved above.
|
// Do not free shada entry: its allocated memory was saved above.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kSDItemJump: {
|
|
||||||
// FIXME
|
|
||||||
shada_free_shada_entry(&cur_entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kSDItemBufferList: {
|
case kSDItemBufferList: {
|
||||||
// FIXME
|
// FIXME
|
||||||
shada_free_shada_entry(&cur_entry);
|
shada_free_shada_entry(&cur_entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSDItemChange:
|
||||||
case kSDItemLocalMark: {
|
case kSDItemLocalMark: {
|
||||||
if (!(flags & kShaDaWantMarks)) {
|
if (!(flags & kShaDaWantMarks)) {
|
||||||
shada_free_shada_entry(&cur_entry);
|
shada_free_shada_entry(&cur_entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf_T *buf = NULL;
|
buf_T *buf = find_buffer(fname_bufs, cur_entry.data.filemark.fname);
|
||||||
if (local_mark_prev_fname != NULL
|
if (buf == NULL) {
|
||||||
&& strncmp(local_mark_prev_fname,
|
shada_free_shada_entry(&cur_entry);
|
||||||
cur_entry.data.filemark.fname,
|
break;
|
||||||
local_mark_prev_fname_len) == 0) {
|
}
|
||||||
buf = local_mark_prev_buf;
|
const fmark_T fm = (fmark_T) {
|
||||||
|
.mark = cur_entry.data.filemark.mark,
|
||||||
|
.fnum = 0,
|
||||||
|
.timestamp = cur_entry.timestamp,
|
||||||
|
.additional_data = cur_entry.data.filemark.additional_data,
|
||||||
|
};
|
||||||
|
if (cur_entry.type == kSDItemLocalMark) {
|
||||||
|
mark_set_local(cur_entry.data.filemark.name, buf, fm,
|
||||||
|
!(flags & kShaDaForceit));
|
||||||
} else {
|
} else {
|
||||||
FOR_ALL_BUFFERS(bp) {
|
int kh_ret;
|
||||||
if (bp->b_ffname != NULL && bp != local_mark_prev_buf) {
|
(void) kh_put(bufset, cl_bufs, (uintptr_t) buf, &kh_ret);
|
||||||
if (fnamecmp(cur_entry.data.filemark.fname, bp->b_ffname) == 0) {
|
if (flags & kShaDaForceit) {
|
||||||
buf = bp;
|
if (buf->b_changelistlen == JUMPLISTSIZE) {
|
||||||
|
free_fmark(buf->b_changelist[0]);
|
||||||
|
memmove(buf->b_changelist, buf->b_changelist + 1,
|
||||||
|
sizeof(buf->b_changelist[0]) * (JUMPLISTSIZE - 1));
|
||||||
|
} else {
|
||||||
|
buf->b_changelistlen++;
|
||||||
|
}
|
||||||
|
buf->b_changelist[buf->b_changelistlen - 1] = fm;
|
||||||
|
} else {
|
||||||
|
const int cl_len = buf->b_changelistlen;
|
||||||
|
int i;
|
||||||
|
for (i = cl_len; i > 0; i--) {
|
||||||
|
const fmark_T cl_fm = buf->b_changelist[i - 1];
|
||||||
|
if (cl_fm.timestamp <= cur_entry.timestamp) {
|
||||||
|
if (marks_equal(fm.mark, cl_fm.mark)) {
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
if (cl_len == JUMPLISTSIZE) {
|
||||||
|
free_fmark(buf->b_changelist[0]);
|
||||||
|
memmove(&buf->b_changelist[0], &buf->b_changelist[1],
|
||||||
|
sizeof(buf->b_changelist[0]) * (size_t) i);
|
||||||
|
} else {
|
||||||
|
memmove(&buf->b_changelist[i + 1], &buf->b_changelist[i],
|
||||||
|
sizeof(buf->b_changelist[0])
|
||||||
|
* (size_t) (cl_len - i));
|
||||||
|
}
|
||||||
|
} else if (i == 0) {
|
||||||
|
if (cl_len == JUMPLISTSIZE) {
|
||||||
|
i = -1;
|
||||||
|
} else if (cl_len > 0) {
|
||||||
|
memmove(&buf->b_changelist[1], &buf->b_changelist[0],
|
||||||
|
sizeof(buf->b_changelist[0])
|
||||||
|
* (size_t) cl_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i != -1) {
|
||||||
|
buf->b_changelist[i] = fm;
|
||||||
|
if (cl_len < JUMPLISTSIZE) {
|
||||||
|
buf->b_changelistlen++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shada_free_shada_entry(&cur_entry);
|
||||||
|
cur_entry.data.filemark.fname = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xfree(local_mark_prev_fname);
|
|
||||||
local_mark_prev_buf = buf;
|
|
||||||
local_mark_prev_fname_len = strlen(cur_entry.data.filemark.fname);
|
|
||||||
local_mark_prev_fname = xmemdupz(cur_entry.data.filemark.fname,
|
|
||||||
local_mark_prev_fname_len);
|
|
||||||
}
|
}
|
||||||
if (buf == NULL) {
|
// Do not free shada entry: except for fname, its allocated memory (i.e.
|
||||||
break;
|
// additional_data attribute contents if non-NULL) was saved above.
|
||||||
}
|
xfree(cur_entry.data.filemark.fname);
|
||||||
mark_set_local(
|
|
||||||
cur_entry.data.filemark.name, buf,
|
|
||||||
(fmark_T) {
|
|
||||||
.mark = cur_entry.data.filemark.mark,
|
|
||||||
.fnum = 0,
|
|
||||||
.timestamp = cur_entry.timestamp,
|
|
||||||
.additional_data = cur_entry.data.filemark.additional_data,
|
|
||||||
}, !(flags & kShaDaForceit));
|
|
||||||
free(cur_entry.data.filemark.fname);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -561,10 +718,18 @@ static void shada_read(FILE *const fp, const int flags)
|
|||||||
hm_rb_dealloc(&(hms[i].hmrb));
|
hm_rb_dealloc(&(hms[i].hmrb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree(local_mark_prev_fname);
|
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||||
FOR_ALL_BUFFERS(buf) {
|
(void) tp;
|
||||||
fmarks_check_names(buf);
|
if (kh_get(bufset, cl_bufs, (uintptr_t) wp->w_buffer) != kh_end(cl_bufs)) {
|
||||||
|
wp->w_changelistidx = wp->w_buffer->b_changelistlen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
kh_destroy(bufset, cl_bufs);
|
||||||
|
const char *key;
|
||||||
|
kh_foreach_key(fname_bufs, key, {
|
||||||
|
xfree((void *) key);
|
||||||
|
})
|
||||||
|
kh_destroy(fnamebufs, fname_bufs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ShaDa file name to use
|
/// Get the ShaDa file name to use
|
||||||
@@ -745,6 +910,7 @@ static void shada_pack_entry(msgpack_packer *const packer,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSDItemChange:
|
||||||
case kSDItemGlobalMark:
|
case kSDItemGlobalMark:
|
||||||
case kSDItemLocalMark:
|
case kSDItemLocalMark:
|
||||||
case kSDItemJump: {
|
case kSDItemJump: {
|
||||||
@@ -756,6 +922,7 @@ static void shada_pack_entry(msgpack_packer *const packer,
|
|||||||
+ (entry.data.filemark.mark.col != 0)
|
+ (entry.data.filemark.mark.col != 0)
|
||||||
// Mark name: defaults to '"'
|
// Mark name: defaults to '"'
|
||||||
+ (entry.type != kSDItemJump
|
+ (entry.type != kSDItemJump
|
||||||
|
&& entry.type != kSDItemChange
|
||||||
&& entry.data.filemark.name != '"')
|
&& entry.data.filemark.name != '"')
|
||||||
// Additional entries, if any:
|
// Additional entries, if any:
|
||||||
+ (entry.data.filemark.additional_data == NULL
|
+ (entry.data.filemark.additional_data == NULL
|
||||||
@@ -774,7 +941,8 @@ static void shada_pack_entry(msgpack_packer *const packer,
|
|||||||
PACK_STATIC_STR("col");
|
PACK_STATIC_STR("col");
|
||||||
msgpack_pack_long(spacker, entry.data.filemark.mark.col);
|
msgpack_pack_long(spacker, entry.data.filemark.mark.col);
|
||||||
}
|
}
|
||||||
if (entry.data.filemark.name != '"' && entry.type != kSDItemJump) {
|
if (entry.data.filemark.name != '"' && entry.type != kSDItemJump
|
||||||
|
&& entry.type != kSDItemChange) {
|
||||||
PACK_STATIC_STR("name");
|
PACK_STATIC_STR("name");
|
||||||
msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name);
|
msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name);
|
||||||
}
|
}
|
||||||
@@ -933,12 +1101,21 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
|
|||||||
const void *jump_iter = NULL;
|
const void *jump_iter = NULL;
|
||||||
do {
|
do {
|
||||||
xfmark_T fm;
|
xfmark_T fm;
|
||||||
|
cleanup_jumplist();
|
||||||
jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
|
jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
|
||||||
char *fname = (fm.fmark.fnum == 0
|
const buf_T *const buf = (fm.fmark.fnum == 0
|
||||||
? (fm.fname == NULL
|
? NULL
|
||||||
? NULL
|
: buflist_findnr(fm.fmark.fnum));
|
||||||
: xstrdup((char *) fm.fname))
|
if (buf != NULL
|
||||||
: buflist_nr2name(fm.fmark.fnum, true, false));
|
? shada_removable(buf->b_ffname)
|
||||||
|
: fm.fmark.fnum != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char *const fname = (char *) (fm.fmark.fnum == 0
|
||||||
|
? (fm.fname == NULL
|
||||||
|
? NULL
|
||||||
|
: fm.fname)
|
||||||
|
: buf->b_ffname);
|
||||||
shada_pack_entry(packer, (ShadaEntry) {
|
shada_pack_entry(packer, (ShadaEntry) {
|
||||||
.type = kSDItemJump,
|
.type = kSDItemJump,
|
||||||
.timestamp = fm.fmark.timestamp,
|
.timestamp = fm.fmark.timestamp,
|
||||||
@@ -946,12 +1123,11 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
|
|||||||
.filemark = {
|
.filemark = {
|
||||||
.name = NUL,
|
.name = NUL,
|
||||||
.mark = fm.fmark.mark,
|
.mark = fm.fmark.mark,
|
||||||
.fname = fname,
|
.fname = (char *) fname,
|
||||||
.additional_data = fm.fmark.additional_data,
|
.additional_data = fm.fmark.additional_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, max_kbyte);
|
}, max_kbyte);
|
||||||
xfree(fname);
|
|
||||||
} while (jump_iter != NULL);
|
} while (jump_iter != NULL);
|
||||||
|
|
||||||
// FIXME No merging currently
|
// FIXME No merging currently
|
||||||
@@ -1050,7 +1226,7 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
|
|||||||
xfree(global_marks);
|
xfree(global_marks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Buffer marks
|
// 8. Buffer marks and buffer change list
|
||||||
FOR_ALL_BUFFERS(buf) {
|
FOR_ALL_BUFFERS(buf) {
|
||||||
if (buf->b_ffname == NULL) {
|
if (buf->b_ffname == NULL) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1061,6 +1237,21 @@ static void shada_write(FILE *const newfp, FILE *const oldfp)
|
|||||||
shada_pack_entry(packer, *mark, max_kbyte);
|
shada_pack_entry(packer, *mark, max_kbyte);
|
||||||
}
|
}
|
||||||
xfree(buffer_marks);
|
xfree(buffer_marks);
|
||||||
|
|
||||||
|
for (int i = 0; i < buf->b_changelistlen; i++) {
|
||||||
|
const fmark_T fm = buf->b_changelist[i];
|
||||||
|
shada_pack_entry(packer, (ShadaEntry) {
|
||||||
|
.type = kSDItemChange,
|
||||||
|
.timestamp = fm.timestamp,
|
||||||
|
.data = {
|
||||||
|
.filemark = {
|
||||||
|
.mark = fm.mark,
|
||||||
|
.fname = (char *) buf->b_ffname,
|
||||||
|
.additional_data = fm.additional_data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, max_kbyte);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// FIXME: Copy previous marks, up to num_marked_files
|
// FIXME: Copy previous marks, up to num_marked_files
|
||||||
// size_t num_marked_files = get_viminfo_parameter('\'');
|
// size_t num_marked_files = get_viminfo_parameter('\'');
|
||||||
@@ -1180,6 +1371,7 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
|
|||||||
api_free_dictionary(entry->data.header);
|
api_free_dictionary(entry->data.header);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSDItemChange:
|
||||||
case kSDItemJump:
|
case kSDItemJump:
|
||||||
case kSDItemGlobalMark:
|
case kSDItemGlobalMark:
|
||||||
case kSDItemLocalMark: {
|
case kSDItemLocalMark: {
|
||||||
@@ -1433,6 +1625,7 @@ shada_read_next_item_start:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kSDItemBufferList:
|
case kSDItemBufferList:
|
||||||
|
case kSDItemChange:
|
||||||
case kSDItemJump:
|
case kSDItemJump:
|
||||||
case kSDItemVariable:
|
case kSDItemVariable:
|
||||||
case kSDItemRegister:
|
case kSDItemRegister:
|
||||||
@@ -1656,6 +1849,7 @@ shada_read_next_item_start:
|
|||||||
ga_clear(&ad_ga);
|
ga_clear(&ad_ga);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kSDItemChange:
|
||||||
case kSDItemJump:
|
case kSDItemJump:
|
||||||
case kSDItemGlobalMark:
|
case kSDItemGlobalMark:
|
||||||
case kSDItemLocalMark: {
|
case kSDItemLocalMark: {
|
||||||
@@ -1680,6 +1874,7 @@ shada_read_next_item_start:
|
|||||||
"mark", "name", " which is not an unsigned integer",
|
"mark", "name", " which is not an unsigned integer",
|
||||||
entry->data.filemark.name,
|
entry->data.filemark.name,
|
||||||
(type_u64 != kSDItemJump
|
(type_u64 != kSDItemJump
|
||||||
|
&& type_u64 != kSDItemChange
|
||||||
&& unpacked.data.via.map.ptr[i].val.type
|
&& unpacked.data.via.map.ptr[i].val.type
|
||||||
== MSGPACK_OBJECT_POSITIVE_INTEGER),
|
== MSGPACK_OBJECT_POSITIVE_INTEGER),
|
||||||
u64, TOCHAR)
|
u64, TOCHAR)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
-- ShaDa marks saving/reading support
|
-- ShaDa marks saving/reading support
|
||||||
local helpers = require('test.functional.helpers')
|
local helpers = require('test.functional.helpers')
|
||||||
local nvim, nvim_window, nvim_curwin, nvim_command, nvim_eval, eq =
|
local nvim, nvim_window, nvim_curwin, nvim_command, nvim_feed, nvim_eval, eq =
|
||||||
helpers.nvim, helpers.window, helpers.curwin, helpers.command, helpers.eval,
|
helpers.nvim, helpers.window, helpers.curwin, helpers.command, helpers.feed,
|
||||||
helpers.eq
|
helpers.eval, helpers.eq
|
||||||
|
|
||||||
local shada_helpers = require('test.functional.shada.helpers')
|
local shada_helpers = require('test.functional.shada.helpers')
|
||||||
local reset, set_additional_cmd, clear =
|
local reset, set_additional_cmd, clear =
|
||||||
@@ -15,16 +15,22 @@ end
|
|||||||
|
|
||||||
describe('ShaDa support code', function()
|
describe('ShaDa support code', function()
|
||||||
testfilename = 'Xtestfile-functional-shada-marks'
|
testfilename = 'Xtestfile-functional-shada-marks'
|
||||||
|
testfilename_2 = 'Xtestfile-functional-shada-marks-2'
|
||||||
before_each(function()
|
before_each(function()
|
||||||
reset()
|
reset()
|
||||||
local fd = io.open(testfilename, 'w')
|
local fd = io.open(testfilename, 'w')
|
||||||
fd:write('test\n')
|
fd:write('test\n')
|
||||||
fd:write('test2\n')
|
fd:write('test2\n')
|
||||||
fd:close()
|
fd:close()
|
||||||
|
local fd = io.open(testfilename_2, 'w')
|
||||||
|
fd:write('test3\n')
|
||||||
|
fd:write('test4\n')
|
||||||
|
fd:close()
|
||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
clear()
|
clear()
|
||||||
os.remove(testfilename)
|
os.remove(testfilename)
|
||||||
|
os.remove(testfilename_2)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('is able to dump and read back global mark', function()
|
it('is able to dump and read back global mark', function()
|
||||||
@@ -74,4 +80,72 @@ describe('ShaDa support code', function()
|
|||||||
nvim_command('normal! `b')
|
nvim_command('normal! `b')
|
||||||
eq(2, nvim_current_line())
|
eq(2, nvim_current_line())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('is able to dump and restore jump list', function()
|
||||||
|
nvim_command('edit ' .. testfilename_2)
|
||||||
|
nvim_feed('G')
|
||||||
|
nvim_feed('gg')
|
||||||
|
nvim_command('edit ' .. testfilename)
|
||||||
|
nvim_feed('G')
|
||||||
|
nvim_feed('gg')
|
||||||
|
-- nvim_command('redir! >/tmp/jumps.last | jumps | redir END')
|
||||||
|
-- nvim_command('wviminfo /tmp/foo')
|
||||||
|
nvim_command('qall')
|
||||||
|
reset()
|
||||||
|
nvim_command('redraw')
|
||||||
|
-- nvim_command('redir! >/tmp/jumps.init | jumps | redir END')
|
||||||
|
nvim_command('edit ' .. testfilename)
|
||||||
|
-- nvim_command('redir! >/tmp/jumps | jumps | redir END')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(2, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename_2, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename_2, nvim_eval('bufname("%")'))
|
||||||
|
eq(2, nvim_current_line())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('is able to dump and restore jump list with different times (slow!)',
|
||||||
|
function()
|
||||||
|
nvim_command('edit ' .. testfilename_2)
|
||||||
|
nvim_command('sleep 2')
|
||||||
|
nvim_feed('G')
|
||||||
|
nvim_command('sleep 2')
|
||||||
|
nvim_feed('gg')
|
||||||
|
nvim_command('sleep 2')
|
||||||
|
nvim_command('edit ' .. testfilename)
|
||||||
|
nvim_command('sleep 2')
|
||||||
|
nvim_feed('G')
|
||||||
|
nvim_command('sleep 2')
|
||||||
|
nvim_feed('gg')
|
||||||
|
-- nvim_command('redir! >/tmp/jumps.last | jumps | redir END')
|
||||||
|
-- nvim_command('wviminfo /tmp/foo')
|
||||||
|
nvim_command('qall')
|
||||||
|
reset()
|
||||||
|
nvim_command('redraw')
|
||||||
|
-- nvim_command('redir! >/tmp/jumps.init | jumps | redir END')
|
||||||
|
nvim_command('edit ' .. testfilename)
|
||||||
|
-- nvim_command('redir! >/tmp/jumps | jumps | redir END')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename, nvim_eval('bufname("%")'))
|
||||||
|
eq(2, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename_2, nvim_eval('bufname("%")'))
|
||||||
|
eq(1, nvim_current_line())
|
||||||
|
nvim_command('execute "normal! \\<C-o>"')
|
||||||
|
eq(testfilename_2, nvim_eval('bufname("%")'))
|
||||||
|
eq(2, nvim_current_line())
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Reference in New Issue
Block a user