Patch 8.1.2225
Problem: The "last used" info of a buffer is under used.
Solution: Add "lastused" to getbufinfo(). List buffers sorted by last-used
field. (Andi Massimino, closes #4722)
Files: runtime/doc/eval.txt, runtime/doc/options.txt,
runtime/doc/windows.txt, src/buffer.c, src/evalbuffer.c,
src/ex_getln.c, src/misc1.c, src/option.c, src/option.h,
src/proto/misc1.pro, src/proto/viminfo.pro,
src/testdir/test_bufwintabinfo.vim, src/testdir/test_cmdline.vim,
src/testdir/test_excmd.vim, src/undo.c, src/vim.h, src/viminfo.c
*** ../vim-8.1.2224/runtime/doc/eval.txt 2019-09-26 23:08:10.501926883
+0200
--- runtime/doc/eval.txt 2019-10-27 04:59:15.196935852 +0100
***************
*** 4772,4777 ****
--- 4778,4787 ----
changed TRUE if the buffer is modified.
changedtick number of changes made to the buffer.
hidden TRUE if the buffer is hidden.
+ lastused timestamp in seconds, like
+ |localtime()|, when the buffer was
+ last used.
+ {only with the |+viminfo| feature}
listed TRUE if the buffer is listed.
lnum current line number in buffer.
loaded TRUE if the buffer is loaded.
*** ../vim-8.1.2224/runtime/doc/options.txt 2019-10-20 18:17:08.363431719
+0200
--- runtime/doc/options.txt 2019-10-27 04:59:47.304750399 +0100
***************
*** 8689,8694 ****
--- 8689,8696 ----
complete first match.
"list:longest" When more than one match, list all matches and
complete till longest common string.
+ "list:lastused" When more than one buffer matches, sort buffers
+ by time last used (other than the current buffer).
When there is only a single match, it is fully completed in all cases.
Examples: >
*** ../vim-8.1.2224/runtime/doc/windows.txt 2019-08-04 20:42:39.815198862
+0200
--- runtime/doc/windows.txt 2019-10-27 04:43:57.249937909 +0100
***************
*** 1088,1093 ****
--- 1090,1096 ----
R terminal buffers with a running job
F terminal buffers with a finished job
? terminal buffers without a job: `:terminal NONE`
+ t show time last used and sort buffers
Combining flags means they are "and"ed together, e.g.:
h+ hidden buffers which are modified
a+ active buffers which are modified
*** ../vim-8.1.2224/src/buffer.c 2019-10-01 17:01:56.342282818 +0200
--- src/buffer.c 2019-10-27 05:04:22.887244105 +0100
***************
*** 2601,2606 ****
--- 2601,2613 ----
return match;
}
+ #ifdef FEAT_VIMINFO
+ typedef struct {
+ buf_T *buf;
+ char_u *match;
+ } bufmatch_T;
+ #endif
+
/*
* Find all buffer names that match.
* For command line expansion of ":buf" and ":sbuf".
***************
*** 2619,2624 ****
--- 2626,2634 ----
char_u *p;
int attempt;
char_u *patc;
+ #ifdef FEAT_VIMINFO
+ bufmatch_T *matches = NULL;
+ #endif
*num_file = 0; /* return values in case of FAIL */
*file = NULL;
***************
*** 2675,2681 ****
p = home_replace_save(buf, p);
else
p = vim_strsave(p);
! (*file)[count++] = p;
}
}
}
--- 2685,2700 ----
p = home_replace_save(buf, p);
else
p = vim_strsave(p);
! #ifdef FEAT_VIMINFO
! if (matches != NULL)
! {
! matches[count].buf = buf;
! matches[count].match = p;
! count++;
! }
! else
! #endif
! (*file)[count++] = p;
}
}
}
***************
*** 2691,2696 ****
--- 2710,2719 ----
vim_free(patc);
return FAIL;
}
+ #ifdef FEAT_VIMINFO
+ if (options & WILD_BUFLASTUSED)
+ matches = ALLOC_MULT(bufmatch_T, count);
+ #endif
}
}
vim_regfree(regmatch.regprog);
***************
*** 2701,2706 ****
--- 2724,2751 ----
if (patc != pat)
vim_free(patc);
+ #ifdef FEAT_VIMINFO
+ if (matches != NULL)
+ {
+ int i;
+ if (count > 1)
+ qsort(matches, count, sizeof(bufmatch_T), buf_compare);
+ // if the current buffer is first in the list, place it at the end
+ if (matches[0].buf == curbuf)
+ {
+ for (i = 1; i < count; i++)
+ (*file)[i-1] = matches[i].match;
+ (*file)[count-1] = matches[0].match;
+ }
+ else
+ {
+ for (i = 0; i < count; i++)
+ (*file)[i] = matches[i].match;
+ }
+ vim_free(matches);
+ }
+ #endif
+
*num_file = count;
return (count == 0 ? FAIL : OK);
}
***************
*** 3016,3022 ****
void
buflist_list(exarg_T *eap)
{
! buf_T *buf;
int len;
int i;
int ro_char;
--- 3061,3067 ----
void
buflist_list(exarg_T *eap)
{
! buf_T *buf = firstbuf;
int len;
int i;
int ro_char;
***************
*** 3026,3032 ****
--- 3071,3102 ----
int job_none_open;
#endif
+ #ifdef FEAT_VIMINFO
+ garray_T buflist;
+ buf_T **buflist_data = NULL, **p;
+
+ if (vim_strchr(eap->arg, 't'))
+ {
+ ga_init2(&buflist, sizeof(buf_T *), 50);
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+ {
+ if (ga_grow(&buflist, 1) == OK)
+ ((buf_T **)buflist.ga_data)[buflist.ga_len++] = buf;
+ }
+
+ qsort(buflist.ga_data, (size_t)buflist.ga_len,
+ sizeof(buf_T *), buf_compare);
+
+ p = buflist_data = (buf_T **)buflist.ga_data;
+ buf = *p;
+ }
+
+ for (; buf != NULL && !got_int; buf = buflist_data
+ ? (++p < buflist_data + buflist.ga_len ? *p : NULL)
+ : buf->b_next)
+ #else
for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next)
+ #endif
{
#ifdef FEAT_TERMINAL
job_running = term_job_running(buf->b_term);
***************
*** 3100,3112 ****
do
IObuff[len++] = ' ';
while (--i > 0 && len < IOSIZE - 18);
! vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len),
! _("line %ld"), buf == curbuf ? curwin->w_cursor.lnum
: (long)buflist_findlnum(buf));
msg_outtrans(IObuff);
out_flush(); /* output one line at a time */
ui_breakcheck();
}
}
/*
--- 3170,3192 ----
do
IObuff[len++] = ' ';
while (--i > 0 && len < IOSIZE - 18);
! #ifdef FEAT_VIMINFO
! if (vim_strchr(eap->arg, 't') && buf->b_last_used)
! add_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used);
! else
! #endif
! vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len),
! _("line %ld"), buf == curbuf ? curwin->w_cursor.lnum
: (long)buflist_findlnum(buf));
msg_outtrans(IObuff);
out_flush(); /* output one line at a time */
ui_breakcheck();
}
+
+ #ifdef FEAT_VIMINFO
+ if (buflist_data)
+ ga_clear(&buflist);
+ #endif
}
/*
*** ../vim-8.1.2224/src/evalbuffer.c 2019-09-07 15:45:09.977228927 +0200
--- src/evalbuffer.c 2019-10-27 04:43:57.253937893 +0100
***************
*** 595,600 ****
--- 595,604 ----
}
#endif
+ #ifdef FEAT_VIMINFO
+ dict_add_number(dict, "lastused", buf->b_last_used);
+ #endif
+
return dict;
}
*** ../vim-8.1.2224/src/ex_getln.c 2019-10-26 20:45:11.450026374 +0200
--- src/ex_getln.c 2019-10-27 04:43:57.253937893 +0100
***************
*** 1407,1412 ****
--- 1407,1415 ----
*/
if ((c == p_wc && !gotesc && KeyTyped) || c == p_wcm)
{
+ int options = WILD_NO_BEEP;
+ if (wim_flags[wim_index] & WIM_BUFLASTUSED)
+ options |= WILD_BUFLASTUSED;
if (xpc.xp_numfiles > 0) /* typed p_wc at least twice */
{
/* if 'wildmode' contains "list" may still need to list */
***************
*** 1419,1428 ****
did_wild_list = TRUE;
}
if (wim_flags[wim_index] & WIM_LONGEST)
! res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP,
firstc != '@');
else if (wim_flags[wim_index] & WIM_FULL)
! res = nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP,
firstc != '@');
else
res = OK; /* don't insert 'wildchar' now */
--- 1422,1431 ----
did_wild_list = TRUE;
}
if (wim_flags[wim_index] & WIM_LONGEST)
! res = nextwild(&xpc, WILD_LONGEST, options,
firstc != '@');
else if (wim_flags[wim_index] & WIM_FULL)
! res = nextwild(&xpc, WILD_NEXT, options,
firstc != '@');
else
res = OK; /* don't insert 'wildchar' now */
***************
*** 1434,1443 ****
/* if 'wildmode' first contains "longest", get longest
* common part */
if (wim_flags[0] & WIM_LONGEST)
! res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP,
firstc != '@');
else
! res = nextwild(&xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP,
firstc != '@');
/* if interrupted while completing, behave like it failed */
--- 1437,1446 ----
/* if 'wildmode' first contains "longest", get longest
* common part */
if (wim_flags[0] & WIM_LONGEST)
! res = nextwild(&xpc, WILD_LONGEST, options,
firstc != '@');
else
! res = nextwild(&xpc, WILD_EXPAND_KEEP, options,
firstc != '@');
/* if interrupted while completing, behave like it failed */
***************
*** 1488,1497 ****
redrawcmd();
did_wild_list = TRUE;
if (wim_flags[wim_index] & WIM_LONGEST)
! nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP,
firstc != '@');
else if (wim_flags[wim_index] & WIM_FULL)
! nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP,
firstc != '@');
}
else
--- 1491,1500 ----
redrawcmd();
did_wild_list = TRUE;
if (wim_flags[wim_index] & WIM_LONGEST)
! nextwild(&xpc, WILD_LONGEST, options,
firstc != '@');
else if (wim_flags[wim_index] & WIM_FULL)
! nextwild(&xpc, WILD_NEXT, options,
firstc != '@');
}
else
*** ../vim-8.1.2224/src/misc1.c 2019-10-17 22:58:59.066497012 +0200
--- src/misc1.c 2019-10-27 05:07:14.170365034 +0100
***************
*** 2576,2578 ****
--- 2576,2609 ----
;
return path_is_url(p);
}
+
+ /*
+ * Put timestamp "tt" in "buf[buflen]" in a nice format.
+ */
+ void
+ add_time(char_u *buf, size_t buflen, time_t tt)
+ {
+ #ifdef HAVE_STRFTIME
+ struct tm tmval;
+ struct tm *curtime;
+
+ if (vim_time() - tt >= 100)
+ {
+ curtime = vim_localtime(&tt, &tmval);
+ if (vim_time() - tt < (60L * 60L * 12L))
+ /* within 12 hours */
+ (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
+ else
+ /* longer ago */
+ (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
+ }
+ else
+ #endif
+ {
+ long seconds = (long)(vim_time() - tt);
+
+ vim_snprintf((char *)buf, buflen,
+ NGETTEXT("%ld second ago", "%ld seconds ago", seconds),
+ seconds);
+ }
+ }
*** ../vim-8.1.2224/src/option.c 2019-10-19 20:57:24.956093733 +0200
--- src/option.c 2019-10-27 04:43:57.253937893 +0100
***************
*** 6987,6992 ****
--- 6987,6994 ----
new_wim_flags[idx] |= WIM_FULL;
else if (i == 4 && STRNCMP(p, "list", 4) == 0)
new_wim_flags[idx] |= WIM_LIST;
+ else if (i == 8 && STRNCMP(p, "lastused", 8) == 0)
+ new_wim_flags[idx] |= WIM_BUFLASTUSED;
else
return FAIL;
p += i;
*** ../vim-8.1.2224/src/option.h 2019-10-17 22:58:59.070496999 +0200
--- src/option.h 2019-10-27 04:43:57.253937893 +0100
***************
*** 338,343 ****
--- 338,344 ----
#define WIM_FULL 0x01
#define WIM_LONGEST 0x02
#define WIM_LIST 0x04
+ #define WIM_BUFLASTUSED 0x08
// arguments for can_bs()
#define BS_INDENT 'i' // "Indent"
*** ../vim-8.1.2224/src/proto/misc1.pro 2019-10-09 22:52:49.000043746 +0200
--- src/proto/misc1.pro 2019-10-27 04:43:57.253937893 +0100
***************
*** 46,49 ****
--- 46,50 ----
char_u *get_isolated_shell_name(void);
int path_is_url(char_u *p);
int path_with_url(char_u *fname);
+ void add_time(char_u *buf, size_t buflen, time_t tt);
/* vim: set ft=c : */
*** ../vim-8.1.2224/src/proto/viminfo.pro 2019-07-23 22:15:21.307518880
+0200
--- src/proto/viminfo.pro 2019-10-27 04:43:57.253937893 +0100
***************
*** 3,7 ****
--- 3,8 ----
void check_marks_read(void);
int read_viminfo(char_u *file, int flags);
void write_viminfo(char_u *file, int forceit);
+ int buf_compare(const void *s1, const void *s2);
void ex_viminfo(exarg_T *eap);
/* vim: set ft=c : */
*** ../vim-8.1.2224/src/testdir/test_bufwintabinfo.vim 2019-09-06
22:45:47.574271573 +0200
--- src/testdir/test_bufwintabinfo.vim 2019-10-27 04:43:57.253937893 +0100
***************
*** 139,141 ****
--- 139,153 ----
set foldlevel=0
endif
endfunc
+
+ function Test_getbufinfo_lastused()
+ call test_settime(1234567)
+ edit Xtestfile1
+ enew
+ call test_settime(7654321)
+ edit Xtestfile2
+ enew
+ call assert_equal(getbufinfo('Xtestfile1')[0].lastused, 1234567)
+ call assert_equal(getbufinfo('Xtestfile2')[0].lastused, 7654321)
+ call test_settime(0)
+ endfunc
*** ../vim-8.1.2224/src/testdir/test_cmdline.vim 2019-10-12
20:17:24.605773312 +0200
--- src/testdir/test_cmdline.vim 2019-10-27 04:43:57.253937893 +0100
***************
*** 767,769 ****
--- 767,814 ----
endtry
bw!
endfunc
+
+ func Test_buffers_lastused()
+ " check that buffers are sorted by time when wildmode has lastused
+ call test_settime(1550020000) " middle
+ edit bufa
+ enew
+ call test_settime(1550030000) " newest
+ edit bufb
+ enew
+ call test_settime(1550010000) " oldest
+ edit bufc
+ enew
+ call test_settime(0)
+ enew
+
+ call assert_equal(['bufa', 'bufb', 'bufc'],
+ \ getcompletion('', 'buffer'))
+
+ let save_wildmode = &wildmode
+ set wildmode=full:lastused
+
+ let cap = "\<c-r>=execute('let X=getcmdline()')\<cr>"
+ call feedkeys(":b \<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufb', X)
+ call feedkeys(":b \<tab>\<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufa', X)
+ call feedkeys(":b \<tab>\<tab>\<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufc', X)
+ enew
+
+ edit other
+ call feedkeys(":b \<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufb', X)
+ call feedkeys(":b \<tab>\<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufa', X)
+ call feedkeys(":b \<tab>\<tab>\<tab>" .. cap .. "\<esc>", 'xt')
+ call assert_equal('b bufc', X)
+ enew
+
+ let &wildmode = save_wildmode
+
+ bwipeout bufa
+ bwipeout bufb
+ bwipeout bufc
+ endfunc
*** ../vim-8.1.2224/src/testdir/test_excmd.vim 2019-08-06 21:29:25.742634550
+0200
--- src/testdir/test_excmd.vim 2019-10-27 04:43:57.253937893 +0100
***************
*** 19,21 ****
--- 19,46 ----
normal vv
call assert_fails(":'<,'>echo 1", 'E481:')
endfunc
+
+ func Test_buffers_lastused()
+ call test_settime(localtime() - 2000) " middle
+ edit bufa
+ enew
+ call test_settime(localtime() - 10) " newest
+ edit bufb
+ enew
+ call test_settime(1550010000) " oldest
+ edit bufc
+ enew
+ call test_settime(0)
+ enew
+
+ let ls = split(execute('buffers t', 'silent!'), '\n')
+ let bufs = ls->map({i,v->split(v, '"\s*')[1:2]})
+ call assert_equal(['bufb', 'bufa', 'bufc'], bufs[1:]->map({i,v->v[0]}))
+ call assert_match('1[0-3] seconds ago', bufs[1][1])
+ call assert_match('\d\d:\d\d:\d\d', bufs[2][1])
+ call assert_match('2019/02/1\d \d\d:\d\d:00', bufs[3][1])
+
+ bwipeout bufa
+ bwipeout bufb
+ bwipeout bufc
+ endfunc
*** ../vim-8.1.2224/src/undo.c 2019-09-21 23:09:00.979830687 +0200
--- src/undo.c 2019-10-27 04:43:57.253937893 +0100
***************
*** 106,112 ****
static void u_doit(int count);
static void u_undoredo(int undo);
static void u_undo_end(int did_undo, int absolute);
- static void u_add_time(char_u *buf, size_t buflen, time_t tt);
static void u_freeheader(buf_T *buf, u_header_T *uhp, u_header_T **uhpp);
static void u_freebranch(buf_T *buf, u_header_T *uhp, u_header_T **uhpp);
static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp);
--- 106,111 ----
***************
*** 2973,2979 ****
if (uhp == NULL)
*msgbuf = NUL;
else
! u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
#ifdef FEAT_CONCEAL
{
--- 2972,2978 ----
if (uhp == NULL)
*msgbuf = NUL;
else
! add_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
#ifdef FEAT_CONCEAL
{
***************
*** 3050,3056 ****
break;
vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ",
uhp->uh_seq, changes);
! u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
uhp->uh_time);
if (uhp->uh_save_nr > 0)
{
--- 3049,3055 ----
break;
vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ",
uhp->uh_seq, changes);
! add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
uhp->uh_time);
if (uhp->uh_save_nr > 0)
{
***************
*** 3124,3160 ****
}
}
- /*
- * Put the timestamp of an undo header in "buf[buflen]" in a nice format.
- */
- static void
- u_add_time(char_u *buf, size_t buflen, time_t tt)
- {
- #ifdef HAVE_STRFTIME
- struct tm tmval;
- struct tm *curtime;
-
- if (vim_time() - tt >= 100)
- {
- curtime = vim_localtime(&tt, &tmval);
- if (vim_time() - tt < (60L * 60L * 12L))
- /* within 12 hours */
- (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
- else
- /* longer ago */
- (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
- }
- else
- #endif
- {
- long seconds = (long)(vim_time() - tt);
-
- vim_snprintf((char *)buf, buflen,
- NGETTEXT("%ld second ago", "%ld seconds ago", seconds),
- seconds);
- }
- }
-
/*
* ":undojoin": continue adding to the last entry list
*/
--- 3123,3128 ----
*** ../vim-8.1.2224/src/vim.h 2019-10-26 16:21:34.511468348 +0200
--- src/vim.h 2019-10-27 04:45:59.721441102 +0100
***************
*** 811,816 ****
--- 811,817 ----
#define WILD_ALLLINKS 0x200
#define WILD_IGNORE_COMPLETESLASH 0x400
#define WILD_NOERROR 0x800 // sets EW_NOERROR
+ #define WILD_BUFLASTUSED 0x1000
// Flags for expand_wildcards()
#define EW_DIR 0x01 // include directory names
*** ../vim-8.1.2224/src/viminfo.c 2019-10-09 22:01:20.599438001 +0200
--- src/viminfo.c 2019-10-27 04:43:57.257937875 +0100
***************
*** 2152,2158 ****
/*
* Compare functions for qsort() below, that compares b_last_used.
*/
! static int
buf_compare(const void *s1, const void *s2)
{
buf_T *buf1 = *(buf_T **)s1;
--- 2152,2158 ----
/*
* Compare functions for qsort() below, that compares b_last_used.
*/
! int
buf_compare(const void *s1, const void *s2)
{
buf_T *buf1 = *(buf_T **)s1;
*** ../vim-8.1.2224/src/version.c 2019-10-26 21:33:11.334329088 +0200
--- src/version.c 2019-10-27 04:53:51.290982776 +0100
***************
*** 743,744 ****
--- 743,746 ----
{ /* Add new patch number below this line */
+ /**/
+ 2225,
/**/
--
Bad fashion can discourage normal people from interacting with the engineer
and talking about the cute things their children do.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar -- [email protected] -- 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 ///
--
--
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].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/201910270413.x9R4DmXp018194%40masaka.moolenaar.net.