vim-patch:8.0.1498: getjumplist() returns duplicate entries

Problem:    Getjumplist() returns duplicate entries. (lacygoill)
Solution:   Call cleanup_jumplist(). (Yegappan Lakshmanan)
a7e18d237f
This commit is contained in:
Jan Edmund Lazo 2019-05-19 08:22:05 -04:00
parent 41828a7302
commit d6d9596b38
4 changed files with 40 additions and 37 deletions

View File

@ -10055,7 +10055,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
tv_list_alloc_ret(rettv, kListLenMayKnow); tv_list_alloc_ret(rettv, kListLenMayKnow);
const win_T *const wp = find_tabwin(&argvars[0], &argvars[1]); win_T *const wp = find_tabwin(&argvars[0], &argvars[1]);
if (wp == NULL) { if (wp == NULL) {
return; return;
} }
@ -10064,14 +10064,21 @@ static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_append_list(rettv->vval.v_list, l); tv_list_append_list(rettv->vval.v_list, l);
tv_list_append_number(rettv->vval.v_list, wp->w_jumplistidx); tv_list_append_number(rettv->vval.v_list, wp->w_jumplistidx);
cleanup_jumplist(wp);
for (int i = 0; i < wp->w_jumplistlen; i++) { for (int i = 0; i < wp->w_jumplistlen; i++) {
if (wp->w_jumplist[i].fmark.mark.lnum == 0) {
continue;
}
if (wp->w_jumplist[i].fmark.fnum == 0) {
fname2fnum(&wp->w_jumplist[i]);
}
dict_T *const d = tv_dict_alloc(); dict_T *const d = tv_dict_alloc();
tv_list_append_dict(l, d); tv_list_append_dict(l, d);
tv_dict_add_nr(d, S_LEN("lnum"), wp->w_jumplist[i].fmark.mark.lnum); tv_dict_add_nr(d, S_LEN("lnum"), wp->w_jumplist[i].fmark.mark.lnum);
tv_dict_add_nr(d, S_LEN("col"), wp->w_jumplist[i].fmark.mark.col); tv_dict_add_nr(d, S_LEN("col"), wp->w_jumplist[i].fmark.mark.col);
tv_dict_add_nr(d, S_LEN("coladd"), wp->w_jumplist[i].fmark.mark.coladd); tv_dict_add_nr(d, S_LEN("coladd"), wp->w_jumplist[i].fmark.mark.coladd);
tv_dict_add_nr(d, S_LEN("bufnr"), wp->w_jumplist[i].fmark.fnum); tv_dict_add_nr(d, S_LEN("bufnr"), wp->w_jumplist[i].fmark.fnum);
if (wp->w_jumplist[i].fmark.fnum == 0) { if (wp->w_jumplist[i].fname != NULL) {
tv_dict_add_str(d, S_LEN("filename"), (char *)wp->w_jumplist[i].fname); tv_dict_add_str(d, S_LEN("filename"), (char *)wp->w_jumplist[i].fname);
} }
} }

View File

@ -214,7 +214,7 @@ pos_T *movemark(int count)
pos_T *pos; pos_T *pos;
xfmark_T *jmp; xfmark_T *jmp;
cleanup_jumplist(); cleanup_jumplist(curwin);
if (curwin->w_jumplistlen == 0) /* nothing to jump to */ if (curwin->w_jumplistlen == 0) /* nothing to jump to */
return (pos_T *)NULL; return (pos_T *)NULL;
@ -463,7 +463,7 @@ getnextmark (
* This is used for marks obtained from the .shada file. It's postponed * This is used for marks obtained from the .shada file. It's postponed
* until the mark is used to avoid a long startup delay. * until the mark is used to avoid a long startup delay.
*/ */
static void fname2fnum(xfmark_T *fm) void fname2fnum(xfmark_T *fm)
{ {
char_u *p; char_u *p;
@ -781,7 +781,7 @@ void ex_jumps(exarg_T *eap)
int i; int i;
char_u *name; char_u *name;
cleanup_jumplist(); cleanup_jumplist(curwin);
/* Highlight title */ /* Highlight title */
MSG_PUTS_TITLE(_("\n jump line col file/text")); MSG_PUTS_TITLE(_("\n jump line col file/text"));
for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i) { for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i) {
@ -1156,53 +1156,51 @@ void mark_col_adjust(
} }
} }
/* // 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 specified window.
* jumplist. They will be removed here for the current window. void cleanup_jumplist(win_T *wp)
*/
void cleanup_jumplist(void)
{ {
int i; int i;
int from, to; int from, to;
to = 0; to = 0;
for (from = 0; from < curwin->w_jumplistlen; ++from) { for (from = 0; from < wp->w_jumplistlen; ++from) {
if (curwin->w_jumplistidx == from) if (wp->w_jumplistidx == from)
curwin->w_jumplistidx = to; wp->w_jumplistidx = to;
for (i = from + 1; i < curwin->w_jumplistlen; ++i) for (i = from + 1; i < wp->w_jumplistlen; ++i)
if (curwin->w_jumplist[i].fmark.fnum if (wp->w_jumplist[i].fmark.fnum
== curwin->w_jumplist[from].fmark.fnum == wp->w_jumplist[from].fmark.fnum
&& curwin->w_jumplist[from].fmark.fnum != 0 && wp->w_jumplist[from].fmark.fnum != 0
&& curwin->w_jumplist[i].fmark.mark.lnum && wp->w_jumplist[i].fmark.mark.lnum
== curwin->w_jumplist[from].fmark.mark.lnum) == wp->w_jumplist[from].fmark.mark.lnum)
break; break;
if (i >= curwin->w_jumplistlen) { // no duplicate if (i >= wp->w_jumplistlen) { // no duplicate
if (to != from) { if (to != from) {
// Not using curwin->w_jumplist[to++] = curwin->w_jumplist[from] because // Not using wp->w_jumplist[to++] = wp->w_jumplist[from] because
// this way valgrind complains about overlapping source and destination // this way valgrind complains about overlapping source and destination
// in memcpy() call. (clang-3.6.0, debug build with -DEXITFREE). // in memcpy() call. (clang-3.6.0, debug build with -DEXITFREE).
curwin->w_jumplist[to] = curwin->w_jumplist[from]; wp->w_jumplist[to] = wp->w_jumplist[from];
} }
to++; to++;
} else { } else {
xfree(curwin->w_jumplist[from].fname); xfree(wp->w_jumplist[from].fname);
} }
} }
if (curwin->w_jumplistidx == curwin->w_jumplistlen) { if (wp->w_jumplistidx == wp->w_jumplistlen) {
curwin->w_jumplistidx = to; wp->w_jumplistidx = to;
} }
curwin->w_jumplistlen = to; wp->w_jumplistlen = to;
// When pointer is below last jump, remove the jump if it matches the current // When pointer is below last jump, remove the jump if it matches the current
// line. This avoids useless/phantom jumps. #9805 // line. This avoids useless/phantom jumps. #9805
if (curwin->w_jumplistlen if (wp->w_jumplistlen
&& curwin->w_jumplistidx == curwin->w_jumplistlen) { && wp->w_jumplistidx == wp->w_jumplistlen) {
const xfmark_T *fm_last = &curwin->w_jumplist[curwin->w_jumplistlen - 1]; const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1];
if (fm_last->fmark.fnum == curbuf->b_fnum if (fm_last->fmark.fnum == curbuf->b_fnum
&& fm_last->fmark.mark.lnum == curwin->w_cursor.lnum) { && fm_last->fmark.mark.lnum == wp->w_cursor.lnum) {
xfree(fm_last->fname); xfree(fm_last->fname);
curwin->w_jumplistlen--; wp->w_jumplistlen--;
curwin->w_jumplistidx--; wp->w_jumplistidx--;
} }
} }
} }

View File

@ -2739,7 +2739,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer,
// Initialize jump list // Initialize jump list
const void *jump_iter = NULL; const void *jump_iter = NULL;
cleanup_jumplist(); cleanup_jumplist(curwin);
setpcmark(); setpcmark();
do { do {
xfmark_T fm; xfmark_T fm;

View File

@ -29,7 +29,6 @@ func Test_getjumplist()
normal gg normal gg
call assert_equal([[ call assert_equal([[
\ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0}, \ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 50, 'bufnr': bnr, 'col': 0, 'coladd': 0}, \ {'lnum': 50, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 4], \ {'lnum': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 4],
@ -48,17 +47,16 @@ func Test_getjumplist()
call assert_equal([[ call assert_equal([[
\ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0}, \ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 50, 'bufnr': bnr, 'col': 0, 'coladd': 0}, \ {'lnum': 50, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 5, 'bufnr': bnr, 'col': 0, 'coladd': 0}, \ {'lnum': 5, 'bufnr': bnr, 'col': 0, 'coladd': 0},
\ {'lnum': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 5], \ {'lnum': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 5],
\ getjumplist()) \ getjumplist())
let l = getjumplist() let l = getjumplist()
call test_garbagecollect_now() call test_garbagecollect_now()
call assert_equal(5, l[1]) call assert_equal(4, l[1])
clearjumps clearjumps
call test_garbagecollect_now() call test_garbagecollect_now()
call assert_equal(5, l[1]) call assert_equal(4, l[1])
call delete("Xtest") call delete("Xtest")
endfunc endfunc