Hi,
On Sat, Feb 10, 2018 at 6:51 PM, vim-dev ML <[email protected]> wrote:
> Hi,
>
> On Sat, Feb 10, 2018 at 3:38 PM, lacygoill <[email protected]>
> wrote:
>>
>> Consider this snippet whose purpose is to populate the location list of
>> the
>> current window with the locations in the jumplist:
>>
>> nno <silent> g:j :<c-u>call <sid>qf_jumplist()<cr>
>> fu! s:qf_jumplist() abort
>> let jumplist = get(getjumplist(), 0, [])
>> call setloclist(0, jumplist)
>> lopen
>> endfu
>>
>> If I press the keys g:j of the mapping, it raises the following error:
>>
>> Error detected while processing function <SNR>173_qf_jumplist:
>> line 2:
>> E92: Buffer 1 not found
>>
>> I need to filter the output getjumplist() to remove any location matching
>> a
>> buffer which doesn't exist:
>>
>> nno <silent> g:j :<c-u>call <sid>qf_jumplist()<cr>
>> fu! s:qf_jumplist() abort
>> let jumplist = get(getjumplist(), 0, [])
>> call filter(jumplist, {i,v -> bufexists(v.bufnr)})
>> call setloclist(0, jumplist)
>> lopen
>> endfu
>>
>> But even then, the length of the location list is much bigger than the one
>> of the jumplist displayed by :jumps. So, I need to silently execute :jumps
>> before invoking getjumplist() to get the same result:
>>
>> nno <silent> g:j :<c-u>call <sid>qf_jumplist()<cr>
>> fu! s:qf_jumplist() abort
>> sil jumps
>> let jumplist = get(getjumplist(), 0, [])
>> call filter(jumplist, {i,v -> bufexists(v.bufnr)})
>> call setloclist(0, jumplist)
>> call setloclist(0, [], 'a', { 'title': ':jumps'})
>> lopen
>> endfu
>>
>> It seems that initially, without you having executed a :jumps command to
>> display the jumplist nor pressing C-o and C-i, getjumplist() includes in
>> the
>> list one or several identical locations matching (bufnr, lnum, col) = (1,
>> 0,
>> 0); as many as needed to get a list whose size is 100, no matter the
>> current
>> size of the jumplist.
>> Usually this location doesn't exist on my machine, because when I start
>> Vim,
>> it automatically restores a saved session from an unnamed buffer 1, and
>> the
>> latter is probably wiped in the process.
>> Which is why I need to invoke filter() in the previous snippet to check
>> whether every buffer currently exists.
>>
>> I don't think this location should be present, because I can't find it in
>> the output of :jumps.
>> If it was there, I think I should find something like this:
>>
>> jump line col file/text
>> x 1 0
>> ^ ^
>> some number no filename/no text, because buffer 1 was an unnamed/empty
>> buffer
>>
>> Besides, initially some (all?) entries are present several times in the
>> output of getjumplist(), which explains why the location list is bigger
>> than
>> the jumplist, even after removing locations matching non-existing buffers.
>>
>> Shouldn't getjumplist() return the same locations as :jumps, regardless of
>> whether the latter has been invoked, or whether we've already moved in the
>> jumplist?
>>
>
> Thanks for reporting the problem. Can you try the attached patch?
>
I am attaching an updated patch.
- Yegappan
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/evalfunc.c b/src/evalfunc.c
index da870c67b..f30dd9b54 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -4871,8 +4871,13 @@ f_getjumplist(typval_T *argvars, typval_T *rettv)
return;
list_append_number(rettv->vval.v_list, (varnumber_T)wp->w_jumplistidx);
+ cleanup_jumplist(wp);
for (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]);
if ((d = dict_alloc()) == NULL)
return;
if (list_append_dict(l, d) == FAIL)
@@ -4886,7 +4891,7 @@ f_getjumplist(typval_T *argvars, typval_T *rettv)
NULL);
# endif
dict_add_nr_str(d, "bufnr", (long)wp->w_jumplist[i].fmark.fnum, NULL);
- if (wp->w_jumplist[i].fmark.fnum == 0)
+ if (wp->w_jumplist[i].fname != NULL)
dict_add_nr_str(d, "filename", 0L, wp->w_jumplist[i].fname);
}
#endif
diff --git a/src/mark.c b/src/mark.c
index 1acdd12d6..810175a74 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -27,13 +27,9 @@
#define EXTRA_MARKS 10 /* marks 0-9 */
static xfmark_T namedfm[NMARKS + EXTRA_MARKS]; /* marks with file nr */
-static void fname2fnum(xfmark_T *fm);
static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf);
static char_u *mark_line(pos_T *mp, int lead_len);
static void show_one_mark(int, char_u *, pos_T *, char_u *, int current);
-#ifdef FEAT_JUMPLIST
-static void cleanup_jumplist(void);
-#endif
#ifdef FEAT_VIMINFO
static void write_one_filemark(FILE *fp, xfmark_T *fm, int c1, int c2);
#endif
@@ -225,7 +221,7 @@ movemark(int count)
pos_T *pos;
xfmark_T *jmp;
- cleanup_jumplist();
+ cleanup_jumplist(curwin);
if (curwin->w_jumplistlen == 0) /* nothing to jump to */
return (pos_T *)NULL;
@@ -519,7 +515,7 @@ getnextmark(
* This is used for marks obtained from the .viminfo file. It's postponed
* until the mark is used to avoid a long startup delay.
*/
- static void
+ void
fname2fnum(xfmark_T *fm)
{
char_u *p;
@@ -895,7 +891,7 @@ ex_jumps(exarg_T *eap UNUSED)
int i;
char_u *name;
- cleanup_jumplist();
+ cleanup_jumplist(curwin);
/* Highlight title */
MSG_PUTS_TITLE(_("\n jump line col file/text"));
for (i = 0; i < curwin->w_jumplistlen && !got_int; ++i)
@@ -1305,34 +1301,34 @@ mark_col_adjust(
#ifdef FEAT_JUMPLIST
/*
* 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 specified window.
*/
- static void
-cleanup_jumplist(void)
+ void
+cleanup_jumplist(win_T *wp)
{
int i;
int from, to;
to = 0;
- for (from = 0; from < curwin->w_jumplistlen; ++from)
+ for (from = 0; from < wp->w_jumplistlen; ++from)
{
- if (curwin->w_jumplistidx == from)
- curwin->w_jumplistidx = to;
- for (i = from + 1; i < curwin->w_jumplistlen; ++i)
- if (curwin->w_jumplist[i].fmark.fnum
- == curwin->w_jumplist[from].fmark.fnum
- && curwin->w_jumplist[from].fmark.fnum != 0
- && curwin->w_jumplist[i].fmark.mark.lnum
- == curwin->w_jumplist[from].fmark.mark.lnum)
+ if (wp->w_jumplistidx == from)
+ wp->w_jumplistidx = to;
+ for (i = from + 1; i < wp->w_jumplistlen; ++i)
+ if (wp->w_jumplist[i].fmark.fnum
+ == wp->w_jumplist[from].fmark.fnum
+ && wp->w_jumplist[from].fmark.fnum != 0
+ && wp->w_jumplist[i].fmark.mark.lnum
+ == wp->w_jumplist[from].fmark.mark.lnum)
break;
- if (i >= curwin->w_jumplistlen) /* no duplicate */
- curwin->w_jumplist[to++] = curwin->w_jumplist[from];
+ if (i >= wp->w_jumplistlen) /* no duplicate */
+ wp->w_jumplist[to++] = wp->w_jumplist[from];
else
- vim_free(curwin->w_jumplist[from].fname);
+ vim_free(wp->w_jumplist[from].fname);
}
- if (curwin->w_jumplistidx == curwin->w_jumplistlen)
- curwin->w_jumplistidx = to;
- curwin->w_jumplistlen = to;
+ if (wp->w_jumplistidx == wp->w_jumplistlen)
+ wp->w_jumplistidx = to;
+ wp->w_jumplistlen = to;
}
/*
@@ -1741,7 +1737,7 @@ write_viminfo_filemarks(FILE *fp)
/* Write the jumplist with -' */
fputs(_("\n# Jumplist (newest first):\n"), fp);
setpcmark(); /* add current cursor position */
- cleanup_jumplist();
+ cleanup_jumplist(curwin);
vi_idx = 0;
idx = curwin->w_jumplistlen - 1;
for (i = 0; i < JUMPLISTSIZE; ++i)
diff --git a/src/proto/mark.pro b/src/proto/mark.pro
index ff1f441e8..aa6f44efc 100644
--- a/src/proto/mark.pro
+++ b/src/proto/mark.pro
@@ -9,6 +9,7 @@ pos_T *getmark_buf(buf_T *buf, int c, int changefile);
pos_T *getmark(int c, int changefile);
pos_T *getmark_buf_fnum(buf_T *buf, int c, int changefile, int *fnum);
pos_T *getnextmark(pos_T *startpos, int dir, int begin_line);
+void fname2fnum(xfmark_T *fm);
void fmarks_check_names(buf_T *buf);
int check_mark(pos_T *pos);
void clrallmarks(buf_T *buf);
@@ -23,6 +24,7 @@ void mark_adjust_nofold(linenr_T line1, linenr_T line2, long
amount, long amount
void mark_col_adjust(linenr_T lnum, colnr_T mincol, long lnum_amount, long
col_amount);
void copy_jumplist(win_T *from, win_T *to);
void free_jumplist(win_T *wp);
+void cleanup_jumplist(win_T *wp);
void set_last_cursor(win_T *win);
void free_all_marks(void);
int read_viminfo_filemark(vir_T *virp, int force);
diff --git a/src/testdir/test_jumplist.vim b/src/testdir/test_jumplist.vim
index 7079d21aa..02dbd7619 100644
--- a/src/testdir/test_jumplist.vim
+++ b/src/testdir/test_jumplist.vim
@@ -29,7 +29,6 @@ func Test_getjumplist()
normal gg
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': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 4],
@@ -48,17 +47,16 @@ func Test_getjumplist()
call assert_equal([[
\ {'lnum': 1, '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': 100, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 5],
\ getjumplist())
let l = getjumplist()
call test_garbagecollect_now()
- call assert_equal(5, l[1])
+ call assert_equal(4, l[1])
clearjumps
call test_garbagecollect_now()
- call assert_equal(5, l[1])
+ call assert_equal(4, l[1])
call delete("Xtest")
endfunc