mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 7.4.1988
Problem: When updating viminfo with file marks there is no time order. Solution: Remember the time when a buffer was last used, store marks for the most recently used buffers.
This commit is contained in:
@@ -1619,6 +1619,9 @@ enter_buffer(buf_T *buf)
|
|||||||
if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
|
if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
|
||||||
(void)did_set_spelllang(curwin);
|
(void)did_set_spelllang(curwin);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_VIMINFO
|
||||||
|
curbuf->b_last_used = vim_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
redraw_later(NOT_VALID);
|
redraw_later(NOT_VALID);
|
||||||
}
|
}
|
||||||
|
@@ -2148,10 +2148,11 @@ viminfo_filename(char_u *file)
|
|||||||
static void
|
static void
|
||||||
do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
|
do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
|
||||||
{
|
{
|
||||||
int count = 0;
|
|
||||||
int eof = FALSE;
|
int eof = FALSE;
|
||||||
vir_T vir;
|
vir_T vir;
|
||||||
int merge = FALSE;
|
int merge = FALSE;
|
||||||
|
int do_copy_marks = FALSE;
|
||||||
|
garray_T buflist;
|
||||||
|
|
||||||
if ((vir.vir_line = alloc(LSIZE)) == NULL)
|
if ((vir.vir_line = alloc(LSIZE)) == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -2183,7 +2184,11 @@ do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
|
|||||||
while (!(eof = viminfo_readline(&vir))
|
while (!(eof = viminfo_readline(&vir))
|
||||||
&& vir.vir_line[0] != '>')
|
&& vir.vir_line[0] != '>')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
do_copy_marks = (flags &
|
||||||
|
(VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp_out != NULL)
|
if (fp_out != NULL)
|
||||||
{
|
{
|
||||||
/* Write the info: */
|
/* Write the info: */
|
||||||
@@ -2209,11 +2214,18 @@ do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
|
|||||||
finish_viminfo_marks();
|
finish_viminfo_marks();
|
||||||
write_viminfo_bufferlist(fp_out);
|
write_viminfo_bufferlist(fp_out);
|
||||||
write_viminfo_barlines(&vir, fp_out);
|
write_viminfo_barlines(&vir, fp_out);
|
||||||
count = write_viminfo_marks(fp_out);
|
|
||||||
|
if (do_copy_marks)
|
||||||
|
ga_init2(&buflist, sizeof(buf_T *), 50);
|
||||||
|
write_viminfo_marks(fp_out, do_copy_marks ? &buflist : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_copy_marks)
|
||||||
|
{
|
||||||
|
copy_viminfo_marks(&vir, fp_out, &buflist, eof, flags);
|
||||||
|
if (fp_out != NULL)
|
||||||
|
ga_clear(&buflist);
|
||||||
}
|
}
|
||||||
if (fp_in != NULL
|
|
||||||
&& (flags & (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT)))
|
|
||||||
copy_viminfo_marks(&vir, fp_out, count, eof, flags);
|
|
||||||
|
|
||||||
vim_free(vir.vir_line);
|
vim_free(vir.vir_line);
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
@@ -4287,6 +4299,10 @@ do_ecmd(
|
|||||||
msg_scrolled_ign = FALSE;
|
msg_scrolled_ign = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_VIMINFO
|
||||||
|
curbuf->b_last_used = vim_time();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (command != NULL)
|
if (command != NULL)
|
||||||
do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
|
do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
|
||||||
|
|
||||||
|
@@ -1272,6 +1272,9 @@ main_loop(
|
|||||||
#ifdef FEAT_TITLE
|
#ifdef FEAT_TITLE
|
||||||
if (need_maketitle)
|
if (need_maketitle)
|
||||||
maketitle();
|
maketitle();
|
||||||
|
#endif
|
||||||
|
#ifdef FEAT_VIMINFO
|
||||||
|
curbuf->b_last_used = vim_time();
|
||||||
#endif
|
#endif
|
||||||
/* display message after redraw */
|
/* display message after redraw */
|
||||||
if (keep_msg != NULL)
|
if (keep_msg != NULL)
|
||||||
|
189
src/mark.c
189
src/mark.c
@@ -1799,16 +1799,54 @@ removable(char_u *name)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_one_mark(FILE *fp_out, int c, pos_T *pos);
|
static void
|
||||||
|
write_one_mark(FILE *fp_out, int c, pos_T *pos)
|
||||||
|
{
|
||||||
|
if (pos->lnum != 0)
|
||||||
|
fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_buffer_marks(buf_T *buf, FILE *fp_out)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
pos_T pos;
|
||||||
|
|
||||||
|
home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
|
||||||
|
fprintf(fp_out, "\n> ");
|
||||||
|
viminfo_writestring(fp_out, IObuff);
|
||||||
|
|
||||||
|
/* Write the last used timestamp as the lnum of the non-existing mark '*'.
|
||||||
|
* Older Vims will ignore it and/or copy it. */
|
||||||
|
pos.lnum = (linenr_T)buf->b_last_used;
|
||||||
|
pos.col = 0;
|
||||||
|
write_one_mark(fp_out, '*', &pos);
|
||||||
|
|
||||||
|
write_one_mark(fp_out, '"', &buf->b_last_cursor);
|
||||||
|
write_one_mark(fp_out, '^', &buf->b_last_insert);
|
||||||
|
write_one_mark(fp_out, '.', &buf->b_last_change);
|
||||||
|
#ifdef FEAT_JUMPLIST
|
||||||
|
/* changelist positions are stored oldest first */
|
||||||
|
for (i = 0; i < buf->b_changelistlen; ++i)
|
||||||
|
{
|
||||||
|
/* skip duplicates */
|
||||||
|
if (i == 0 || !equalpos(buf->b_changelist[i - 1], buf->b_changelist[i]))
|
||||||
|
write_one_mark(fp_out, '+', &buf->b_changelist[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (i = 0; i < NMARKS; i++)
|
||||||
|
write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write all the named marks for all buffers.
|
* Write all the named marks for all buffers.
|
||||||
* Return the number of buffers for which marks have been written.
|
* When "buflist" is not NULL fill it with the buffers for which marks are to
|
||||||
|
* be written.
|
||||||
*/
|
*/
|
||||||
int
|
void
|
||||||
write_viminfo_marks(FILE *fp_out)
|
write_viminfo_marks(FILE *fp_out, garray_T *buflist)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
int is_mark_set;
|
int is_mark_set;
|
||||||
int i;
|
int i;
|
||||||
@@ -1826,7 +1864,6 @@ write_viminfo_marks(FILE *fp_out)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out);
|
fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out);
|
||||||
count = 0;
|
|
||||||
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
|
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -1850,42 +1887,35 @@ write_viminfo_marks(FILE *fp_out)
|
|||||||
if (is_mark_set && buf->b_ffname != NULL
|
if (is_mark_set && buf->b_ffname != NULL
|
||||||
&& buf->b_ffname[0] != NUL && !removable(buf->b_ffname))
|
&& buf->b_ffname[0] != NUL && !removable(buf->b_ffname))
|
||||||
{
|
{
|
||||||
home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
|
if (buflist == NULL)
|
||||||
fprintf(fp_out, "\n> ");
|
write_buffer_marks(buf, fp_out);
|
||||||
viminfo_writestring(fp_out, IObuff);
|
else if (ga_grow(buflist, 1) == OK)
|
||||||
write_one_mark(fp_out, '"', &buf->b_last_cursor);
|
((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf;
|
||||||
write_one_mark(fp_out, '^', &buf->b_last_insert);
|
|
||||||
write_one_mark(fp_out, '.', &buf->b_last_change);
|
|
||||||
#ifdef FEAT_JUMPLIST
|
|
||||||
/* changelist positions are stored oldest first */
|
|
||||||
for (i = 0; i < buf->b_changelistlen; ++i)
|
|
||||||
{
|
|
||||||
/* skip duplicates */
|
|
||||||
if (i == 0 || !equalpos(buf->b_changelist[i - 1],
|
|
||||||
buf->b_changelist[i]))
|
|
||||||
write_one_mark(fp_out, '+', &buf->b_changelist[i]);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare functions for qsort() below, that compares b_last_used.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
#ifdef __BORLANDC__
|
||||||
|
_RTLENTRYF
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < NMARKS; i++)
|
buf_compare(const void *s1, const void *s2)
|
||||||
write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_one_mark(FILE *fp_out, int c, pos_T *pos)
|
|
||||||
{
|
{
|
||||||
if (pos->lnum != 0)
|
buf_T *buf1 = *(buf_T **)s1;
|
||||||
fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
|
buf_T *buf2 = *(buf_T **)s2;
|
||||||
|
|
||||||
|
if (buf1->b_last_used == buf2->b_last_used)
|
||||||
|
return 0;
|
||||||
|
return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle marks in the viminfo file:
|
* Handle marks in the viminfo file:
|
||||||
* fp_out != NULL: copy marks for buffers not in buffer list
|
* fp_out != NULL: copy marks, in time order with buffers in "buflist".
|
||||||
* fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
|
* fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
|
||||||
* fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
|
* fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
|
||||||
*/
|
*/
|
||||||
@@ -1893,7 +1923,7 @@ write_one_mark(FILE *fp_out, int c, pos_T *pos)
|
|||||||
copy_viminfo_marks(
|
copy_viminfo_marks(
|
||||||
vir_T *virp,
|
vir_T *virp,
|
||||||
FILE *fp_out,
|
FILE *fp_out,
|
||||||
int count,
|
garray_T *buflist,
|
||||||
int eof,
|
int eof,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
@@ -1910,11 +1940,22 @@ copy_viminfo_marks(
|
|||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
list_T *list = NULL;
|
list_T *list = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
int count = 0;
|
||||||
|
int buflist_used = 0;
|
||||||
|
buf_T *buflist_buf = NULL;
|
||||||
|
|
||||||
if ((name_buf = alloc(LSIZE)) == NULL)
|
if ((name_buf = alloc(LSIZE)) == NULL)
|
||||||
return;
|
return;
|
||||||
*name_buf = NUL;
|
*name_buf = NUL;
|
||||||
|
|
||||||
|
if (fp_out != NULL && buflist->ga_len > 0)
|
||||||
|
{
|
||||||
|
/* Sort the list of buffers on b_last_used. */
|
||||||
|
qsort(buflist->ga_data, (size_t)buflist->ga_len,
|
||||||
|
sizeof(buf_T *), buf_compare);
|
||||||
|
buflist_buf = ((buf_T **)buflist->ga_data)[0];
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
|
if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
|
||||||
{
|
{
|
||||||
@@ -1986,14 +2027,70 @@ copy_viminfo_marks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy marks if the buffer has not been loaded
|
* Copy marks if the buffer has not been loaded.
|
||||||
*/
|
*/
|
||||||
if (buf == NULL || !buf->b_marks_read)
|
if (buf == NULL || !buf->b_marks_read)
|
||||||
{
|
{
|
||||||
copy_marks_out = TRUE;
|
int did_read_line = FALSE;
|
||||||
|
|
||||||
|
if (buflist_buf != NULL)
|
||||||
|
{
|
||||||
|
/* Read the next line. If it has the "*" mark compare the
|
||||||
|
* time stamps. Write entries from "buflist" that are
|
||||||
|
* newer. */
|
||||||
|
if (!(eof = viminfo_readline(virp)) && line[0] == TAB)
|
||||||
|
{
|
||||||
|
did_read_line = TRUE;
|
||||||
|
if (line[1] == '*')
|
||||||
|
{
|
||||||
|
long ltime;
|
||||||
|
|
||||||
|
sscanf((char *)line + 2, "%ld ", <ime);
|
||||||
|
while ((time_T)ltime < buflist_buf->b_last_used)
|
||||||
|
{
|
||||||
|
write_buffer_marks(buflist_buf, fp_out);
|
||||||
|
if (++count >= num_marked_files)
|
||||||
|
break;
|
||||||
|
if (++buflist_used == buflist->ga_len)
|
||||||
|
{
|
||||||
|
buflist_buf = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buflist_buf =
|
||||||
|
((buf_T **)buflist->ga_data)[buflist_used];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No timestamp, must be written by an older Vim.
|
||||||
|
* Assume all remaining buffers are older then
|
||||||
|
* ours. */
|
||||||
|
while (count < num_marked_files
|
||||||
|
&& buflist_used < buflist->ga_len)
|
||||||
|
{
|
||||||
|
buflist_buf = ((buf_T **)buflist->ga_data)
|
||||||
|
[buflist_used++];
|
||||||
|
write_buffer_marks(buflist_buf, fp_out);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
buflist_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count >= num_marked_files)
|
||||||
|
{
|
||||||
|
vim_free(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fputs("\n> ", fp_out);
|
fputs("\n> ", fp_out);
|
||||||
viminfo_writestring(fp_out, str);
|
viminfo_writestring(fp_out, str);
|
||||||
|
if (did_read_line)
|
||||||
|
fputs((char *)line, fp_out);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
copy_marks_out = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vim_free(str);
|
vim_free(str);
|
||||||
@@ -2031,6 +2128,11 @@ copy_viminfo_marks(
|
|||||||
curbuf->b_changelistlen - 1] = pos;
|
curbuf->b_changelistlen - 1] = pos;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Using the line number for the last-used
|
||||||
|
* timestamp. */
|
||||||
|
case '*': curbuf->b_last_used = pos.lnum; break;
|
||||||
|
|
||||||
default: if ((i = line[1] - 'a') >= 0 && i < NMARKS)
|
default: if ((i = line[1] - 'a') >= 0 && i < NMARKS)
|
||||||
curbuf->b_namedm[i] = pos;
|
curbuf->b_namedm[i] = pos;
|
||||||
}
|
}
|
||||||
@@ -2039,6 +2141,7 @@ copy_viminfo_marks(
|
|||||||
else if (copy_marks_out)
|
else if (copy_marks_out)
|
||||||
fputs((char *)line, fp_out);
|
fputs((char *)line, fp_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_marks)
|
if (load_marks)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_JUMPLIST
|
#ifdef FEAT_JUMPLIST
|
||||||
@@ -2053,6 +2156,16 @@ copy_viminfo_marks(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fp_out != NULL)
|
||||||
|
/* Write any remaining entries from buflist. */
|
||||||
|
while (count < num_marked_files && buflist_used < buflist->ga_len)
|
||||||
|
{
|
||||||
|
buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++];
|
||||||
|
write_buffer_marks(buflist_buf, fp_out);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
vim_free(name_buf);
|
vim_free(name_buf);
|
||||||
}
|
}
|
||||||
#endif /* FEAT_VIMINFO */
|
#endif /* FEAT_VIMINFO */
|
||||||
|
@@ -30,6 +30,6 @@ void finish_viminfo_marks(void);
|
|||||||
void handle_viminfo_mark(garray_T *values, int force);
|
void handle_viminfo_mark(garray_T *values, int force);
|
||||||
void write_viminfo_filemarks(FILE *fp);
|
void write_viminfo_filemarks(FILE *fp);
|
||||||
int removable(char_u *name);
|
int removable(char_u *name);
|
||||||
int write_viminfo_marks(FILE *fp_out);
|
void write_viminfo_marks(FILE *fp_out, garray_T *buflist);
|
||||||
void copy_viminfo_marks(vir_T *virp, FILE *fp_out, int count, int eof, int flags);
|
void copy_viminfo_marks(vir_T *virp, FILE *fp_out, garray_T *buflist, int eof, int flags);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -1771,6 +1771,10 @@ struct file_buffer
|
|||||||
long b_mtime_read; /* last change time when reading */
|
long b_mtime_read; /* last change time when reading */
|
||||||
off_T b_orig_size; /* size of original file in bytes */
|
off_T b_orig_size; /* size of original file in bytes */
|
||||||
int b_orig_mode; /* mode of original file */
|
int b_orig_mode; /* mode of original file */
|
||||||
|
#ifdef FEAT_VIMINFO
|
||||||
|
time_T b_last_used; /* time when the buffer was last used; used
|
||||||
|
* for viminfo */
|
||||||
|
#endif
|
||||||
|
|
||||||
pos_T b_namedm[NMARKS]; /* current named marks (mark.c) */
|
pos_T b_namedm[NMARKS]; /* current named marks (mark.c) */
|
||||||
|
|
||||||
|
@@ -395,3 +395,33 @@ func Test_viminfo_bad_syntax()
|
|||||||
call delete('Xviminfo')
|
call delete('Xviminfo')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_viminfo_file_marks()
|
||||||
|
silent! bwipe test_viminfo.vim
|
||||||
|
silent! bwipe Xviminfo
|
||||||
|
|
||||||
|
call test_settime(10)
|
||||||
|
edit ten
|
||||||
|
call test_settime(25)
|
||||||
|
edit again
|
||||||
|
call test_settime(30)
|
||||||
|
edit thirty
|
||||||
|
wviminfo Xviminfo
|
||||||
|
|
||||||
|
call test_settime(20)
|
||||||
|
edit twenty
|
||||||
|
call test_settime(35)
|
||||||
|
edit again
|
||||||
|
call test_settime(40)
|
||||||
|
edit fourty
|
||||||
|
wviminfo Xviminfo
|
||||||
|
|
||||||
|
sp Xviminfo
|
||||||
|
1
|
||||||
|
for name in ['fourty', 'again', 'thirty', 'twenty', 'ten']
|
||||||
|
/^>
|
||||||
|
call assert_equal(name, substitute(getline('.'), '.*/', '', ''))
|
||||||
|
endfor
|
||||||
|
close
|
||||||
|
|
||||||
|
call delete('Xviminfo')
|
||||||
|
endfunc
|
||||||
|
@@ -758,6 +758,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1988,
|
||||||
/**/
|
/**/
|
||||||
1987,
|
1987,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user