To: vim_dev@googlegroups.com Subject: Patch 7.4.1988 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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. Files: src/buffer.c, src/structs.h, src/mark.c, src/main.c, src/ex_cmds.c, src/proto/mark.pro, src/testdir/test_viminfo.vim *** ../vim-7.4.1987/src/buffer.c 2016-07-01 17:17:13.270267053 +0200 --- src/buffer.c 2016-07-03 14:43:54.434420824 +0200 *************** *** 1619,1624 **** --- 1619,1627 ---- if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) (void)did_set_spelllang(curwin); #endif + #ifdef FEAT_VIMINFO + curbuf->b_last_used = vim_time(); + #endif redraw_later(NOT_VALID); } *** ../vim-7.4.1987/src/structs.h 2016-07-01 18:16:47.497936191 +0200 --- src/structs.h 2016-07-03 14:43:52.018456420 +0200 *************** *** 1771,1776 **** --- 1771,1780 ---- long b_mtime_read; /* last change time when reading */ off_T b_orig_size; /* size of original file in bytes */ 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) */ *** ../vim-7.4.1987/src/mark.c 2016-07-02 19:20:02.152849060 +0200 --- src/mark.c 2016-07-03 17:27:43.520476505 +0200 *************** *** 1799,1814 **** return retval; } ! static void write_one_mark(FILE *fp_out, int c, pos_T *pos); /* * Write all the named marks for all buffers. ! * Return the number of buffers for which marks have been written. */ ! int ! write_viminfo_marks(FILE *fp_out) { - int count; buf_T *buf; int is_mark_set; int i; --- 1799,1852 ---- return retval; } ! 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. ! * When "buflist" is not NULL fill it with the buffers for which marks are to ! * be written. */ ! void ! write_viminfo_marks(FILE *fp_out, garray_T *buflist) { buf_T *buf; int is_mark_set; int i; *************** *** 1826,1832 **** #endif fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out); - count = 0; for (buf = firstbuf; buf != NULL; buf = buf->b_next) { /* --- 1864,1869 ---- *************** *** 1850,1891 **** if (is_mark_set && buf->b_ffname != NULL && buf->b_ffname[0] != NUL && !removable(buf->b_ffname)) { ! home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE); ! fprintf(fp_out, "\n> "); ! viminfo_writestring(fp_out, IObuff); ! 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]); ! count++; } } } - - return count; } ! 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); } /* * Handle marks in the viminfo file: ! * fp_out != NULL: copy marks for buffers not in buffer list * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles */ --- 1887,1921 ---- if (is_mark_set && buf->b_ffname != NULL && buf->b_ffname[0] != NUL && !removable(buf->b_ffname)) { ! if (buflist == NULL) ! write_buffer_marks(buf, fp_out); ! else if (ga_grow(buflist, 1) == OK) ! ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf; } } } } ! /* ! * Compare functions for qsort() below, that compares b_last_used. ! */ ! static int ! #ifdef __BORLANDC__ ! _RTLENTRYF ! #endif ! buf_compare(const void *s1, const void *s2) { ! buf_T *buf1 = *(buf_T **)s1; ! 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: ! * 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_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles */ *************** *** 1893,1899 **** copy_viminfo_marks( vir_T *virp, FILE *fp_out, ! int count, int eof, int flags) { --- 1923,1929 ---- copy_viminfo_marks( vir_T *virp, FILE *fp_out, ! garray_T *buflist, int eof, int flags) { *************** *** 1910,1920 **** --- 1940,1961 ---- #ifdef FEAT_EVAL list_T *list = NULL; #endif + int count = 0; + int buflist_used = 0; + buf_T *buflist_buf = NULL; if ((name_buf = alloc(LSIZE)) == NULL) return; *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 if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT))) { *************** *** 1986,1999 **** } /* ! * copy marks if the buffer has not been loaded */ if (buf == NULL || !buf->b_marks_read) { ! copy_marks_out = TRUE; fputs("\n> ", fp_out); viminfo_writestring(fp_out, str); count++; } } vim_free(str); --- 2027,2096 ---- } /* ! * Copy marks if the buffer has not been loaded. */ if (buf == NULL || !buf->b_marks_read) { ! 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); viminfo_writestring(fp_out, str); + if (did_read_line) + fputs((char *)line, fp_out); + count++; + copy_marks_out = TRUE; } } vim_free(str); *************** *** 2031,2036 **** --- 2128,2138 ---- curbuf->b_changelistlen - 1] = pos; #endif 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) curbuf->b_namedm[i] = pos; } *************** *** 2039,2044 **** --- 2141,2147 ---- else if (copy_marks_out) fputs((char *)line, fp_out); } + if (load_marks) { #ifdef FEAT_JUMPLIST *************** *** 2053,2058 **** --- 2156,2171 ---- 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); } #endif /* FEAT_VIMINFO */ *** ../vim-7.4.1987/src/main.c 2016-07-02 20:27:29.953436359 +0200 --- src/main.c 2016-07-03 14:45:57.640605919 +0200 *************** *** 1273,1278 **** --- 1273,1281 ---- if (need_maketitle) maketitle(); #endif + #ifdef FEAT_VIMINFO + curbuf->b_last_used = vim_time(); + #endif /* display message after redraw */ if (keep_msg != NULL) { *** ../vim-7.4.1987/src/ex_cmds.c 2016-07-02 22:33:42.697309329 +0200 --- src/ex_cmds.c 2016-07-03 17:21:27.574130345 +0200 *************** *** 2148,2157 **** static void do_viminfo(FILE *fp_in, FILE *fp_out, int flags) { - int count = 0; int eof = FALSE; vir_T vir; int merge = FALSE; if ((vir.vir_line = alloc(LSIZE)) == NULL) return; --- 2148,2158 ---- static void do_viminfo(FILE *fp_in, FILE *fp_out, int flags) { int eof = FALSE; vir_T vir; int merge = FALSE; + int do_copy_marks = FALSE; + garray_T buflist; if ((vir.vir_line = alloc(LSIZE)) == NULL) return; *************** *** 2183,2189 **** --- 2184,2194 ---- while (!(eof = viminfo_readline(&vir)) && vir.vir_line[0] != '>') ; + + do_copy_marks = (flags & + (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT)); } + if (fp_out != NULL) { /* Write the info: */ *************** *** 2209,2219 **** finish_viminfo_marks(); write_viminfo_bufferlist(fp_out); write_viminfo_barlines(&vir, fp_out); ! count = write_viminfo_marks(fp_out); } - 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); #ifdef FEAT_MBYTE --- 2214,2231 ---- finish_viminfo_marks(); write_viminfo_bufferlist(fp_out); write_viminfo_barlines(&vir, 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); } vim_free(vir.vir_line); #ifdef FEAT_MBYTE *************** *** 4287,4292 **** --- 4299,4308 ---- msg_scrolled_ign = FALSE; } + #ifdef FEAT_VIMINFO + curbuf->b_last_used = vim_time(); + #endif + if (command != NULL) do_cmdline(command, NULL, NULL, DOCMD_VERBOSE); *** ../vim-7.4.1987/src/proto/mark.pro 2016-06-12 21:20:50.941837428 +0200 --- src/proto/mark.pro 2016-07-03 15:56:55.001566461 +0200 *************** *** 30,35 **** void handle_viminfo_mark(garray_T *values, int force); void write_viminfo_filemarks(FILE *fp); int removable(char_u *name); ! int write_viminfo_marks(FILE *fp_out); ! void copy_viminfo_marks(vir_T *virp, FILE *fp_out, int count, int eof, int flags); /* vim: set ft=c : */ --- 30,35 ---- void handle_viminfo_mark(garray_T *values, int force); void write_viminfo_filemarks(FILE *fp); int removable(char_u *name); ! void write_viminfo_marks(FILE *fp_out, garray_T *buflist); ! void copy_viminfo_marks(vir_T *virp, FILE *fp_out, garray_T *buflist, int eof, int flags); /* vim: set ft=c : */ *** ../vim-7.4.1987/src/testdir/test_viminfo.vim 2016-06-15 21:44:47.645388277 +0200 --- src/testdir/test_viminfo.vim 2016-07-03 17:32:49.739875626 +0200 *************** *** 395,397 **** --- 395,427 ---- call delete('Xviminfo') 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 *** ../vim-7.4.1987/src/version.c 2016-07-02 22:33:42.697309329 +0200 --- src/version.c 2016-07-03 14:45:03.829398486 +0200 *************** *** 760,761 **** --- 760,763 ---- { /* Add new patch number below this line */ + /**/ + 1988, /**/ -- hundred-and-one symptoms of being an internet addict: 192. Your boss asks you to "go fer" coffee and you come up with 235 FTP sites. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///