From 52410575be50d5c40bbe6380159df48cfc382ceb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 27 Oct 2019 05:12:45 +0100 Subject: [PATCH 1/9] patch 8.1.2225: the "last used" info of a buffer is under used 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) --- runtime/doc/eval.txt | 4 ++ runtime/doc/options.txt | 2 + runtime/doc/windows.txt | 1 + src/buffer.c | 88 ++++++++++++++++++++++++++++-- src/evalbuffer.c | 4 ++ src/ex_getln.c | 15 +++-- src/misc1.c | 31 +++++++++++ src/option.c | 2 + src/option.h | 1 + src/proto/misc1.pro | 1 + src/proto/viminfo.pro | 1 + src/testdir/test_bufwintabinfo.vim | 12 ++++ src/testdir/test_cmdline.vim | 45 +++++++++++++++ src/testdir/test_excmd.vim | 25 +++++++++ src/undo.c | 36 +----------- src/version.c | 2 + src/vim.h | 1 + src/viminfo.c | 2 +- 18 files changed, 228 insertions(+), 45 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index a167d5f563..f50c8c5b87 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4778,6 +4778,10 @@ getbufinfo([{dict}]) 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. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 029a0727f4..6e4ff1d6f5 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -8689,6 +8689,8 @@ A jump table for the options with a short description can be found at |Q_op|. 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: > diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 0c37cf5399..813de1b664 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -1090,6 +1090,7 @@ list of buffers. |unlisted-buffer| 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 diff --git a/src/buffer.c b/src/buffer.c index 86f6ffcedb..15fbc173e8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2601,6 +2601,13 @@ buflist_findpat( 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,6 +2626,9 @@ ExpandBufnames( 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,7 +2685,16 @@ ExpandBufnames( p = home_replace_save(buf, p); else p = vim_strsave(p); - (*file)[count++] = p; +#ifdef FEAT_VIMINFO + if (matches != NULL) + { + matches[count].buf = buf; + matches[count].match = p; + count++; + } + else +#endif + (*file)[count++] = p; } } } @@ -2691,6 +2710,10 @@ ExpandBufnames( vim_free(patc); return FAIL; } +#ifdef FEAT_VIMINFO + if (options & WILD_BUFLASTUSED) + matches = ALLOC_MULT(bufmatch_T, count); +#endif } } vim_regfree(regmatch.regprog); @@ -2701,6 +2724,28 @@ ExpandBufnames( 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,7 +3061,7 @@ buflist_findlnum(buf_T *buf) void buflist_list(exarg_T *eap) { - buf_T *buf; + buf_T *buf = firstbuf; int len; int i; int ro_char; @@ -3026,7 +3071,32 @@ buflist_list(exarg_T *eap) 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,13 +3170,23 @@ buflist_list(exarg_T *eap) 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 +#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 } /* diff --git a/src/evalbuffer.c b/src/evalbuffer.c index 35c9ed2459..a82b89727e 100644 --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -595,6 +595,10 @@ get_buffer_info(buf_T *buf) } #endif +#ifdef FEAT_VIMINFO + dict_add_number(dict, "lastused", buf->b_last_used); +#endif + return dict; } diff --git a/src/ex_getln.c b/src/ex_getln.c index 9c98f99bab..5cc1c34897 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -1407,6 +1407,9 @@ getcmdline_int( */ 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,10 +1422,10 @@ getcmdline_int( did_wild_list = TRUE; } if (wim_flags[wim_index] & WIM_LONGEST) - res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, + res = nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else if (wim_flags[wim_index] & WIM_FULL) - res = nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP, + res = nextwild(&xpc, WILD_NEXT, options, firstc != '@'); else res = OK; /* don't insert 'wildchar' now */ @@ -1434,10 +1437,10 @@ getcmdline_int( /* if 'wildmode' first contains "longest", get longest * common part */ if (wim_flags[0] & WIM_LONGEST) - res = nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, + res = nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else - res = nextwild(&xpc, WILD_EXPAND_KEEP, WILD_NO_BEEP, + res = nextwild(&xpc, WILD_EXPAND_KEEP, options, firstc != '@'); /* if interrupted while completing, behave like it failed */ @@ -1488,10 +1491,10 @@ getcmdline_int( redrawcmd(); did_wild_list = TRUE; if (wim_flags[wim_index] & WIM_LONGEST) - nextwild(&xpc, WILD_LONGEST, WILD_NO_BEEP, + nextwild(&xpc, WILD_LONGEST, options, firstc != '@'); else if (wim_flags[wim_index] & WIM_FULL) - nextwild(&xpc, WILD_NEXT, WILD_NO_BEEP, + nextwild(&xpc, WILD_NEXT, options, firstc != '@'); } else diff --git a/src/misc1.c b/src/misc1.c index 0e182555ac..74c8eaa66f 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -2576,3 +2576,34 @@ path_with_url(char_u *fname) ; 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); + } +} diff --git a/src/option.c b/src/option.c index 3314a3c4b7..1140a01ac2 100644 --- a/src/option.c +++ b/src/option.c @@ -6987,6 +6987,8 @@ check_opt_wim(void) 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; diff --git a/src/option.h b/src/option.h index 254ca6a282..3ee9979133 100644 --- a/src/option.h +++ b/src/option.h @@ -338,6 +338,7 @@ #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" diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index 1a06d7ed7f..2f7bd03885 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -46,4 +46,5 @@ int goto_im(void); 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 : */ diff --git a/src/proto/viminfo.pro b/src/proto/viminfo.pro index a1f03373d7..b1f97f6ede 100644 --- a/src/proto/viminfo.pro +++ b/src/proto/viminfo.pro @@ -3,5 +3,6 @@ int get_viminfo_parameter(int type); 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 : */ diff --git a/src/testdir/test_bufwintabinfo.vim b/src/testdir/test_bufwintabinfo.vim index ee22ebd455..b4b8a109bd 100644 --- a/src/testdir/test_bufwintabinfo.vim +++ b/src/testdir/test_bufwintabinfo.vim @@ -139,3 +139,15 @@ function Test_get_win_options() 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 diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 55f35e7dd6..57dff41673 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -767,3 +767,48 @@ func Test_cmdwin_bug() 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 = "\=execute('let X=getcmdline()')\" + call feedkeys(":b \" .. cap .. "\", 'xt') + call assert_equal('b bufb', X) + call feedkeys(":b \\" .. cap .. "\", 'xt') + call assert_equal('b bufa', X) + call feedkeys(":b \\\" .. cap .. "\", 'xt') + call assert_equal('b bufc', X) + enew + + edit other + call feedkeys(":b \" .. cap .. "\", 'xt') + call assert_equal('b bufb', X) + call feedkeys(":b \\" .. cap .. "\", 'xt') + call assert_equal('b bufa', X) + call feedkeys(":b \\\" .. cap .. "\", 'xt') + call assert_equal('b bufc', X) + enew + + let &wildmode = save_wildmode + + bwipeout bufa + bwipeout bufb + bwipeout bufc +endfunc diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim index 509d78dfba..992fc3de07 100644 --- a/src/testdir/test_excmd.vim +++ b/src/testdir/test_excmd.vim @@ -19,3 +19,28 @@ func Test_range_error() 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 diff --git a/src/undo.c b/src/undo.c index 2736f2a33d..64fb2050c3 100644 --- a/src/undo.c +++ b/src/undo.c @@ -106,7 +106,6 @@ static void u_getbot(void); 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); @@ -2973,7 +2972,7 @@ u_undo_end( if (uhp == NULL) *msgbuf = NUL; else - u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); + add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); #ifdef FEAT_CONCEAL { @@ -3050,7 +3049,7 @@ ex_undolist(exarg_T *eap UNUSED) break; vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes); - u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), + add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time); if (uhp->uh_save_nr > 0) { @@ -3124,37 +3123,6 @@ ex_undolist(exarg_T *eap UNUSED) } } -/* - * 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 */ diff --git a/src/version.c b/src/version.c index 62a48880d7..3f36958a69 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2225, /**/ 2224, /**/ diff --git a/src/vim.h b/src/vim.h index 917dbfa724..230f5b3f8d 100644 --- a/src/vim.h +++ b/src/vim.h @@ -811,6 +811,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #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 diff --git a/src/viminfo.c b/src/viminfo.c index b16282856b..a49bb01daf 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -2152,7 +2152,7 @@ write_viminfo_filemarks(FILE *fp) /* * Compare functions for qsort() below, that compares b_last_used. */ - static int + int buf_compare(const void *s1, const void *s2) { buf_T *buf1 = *(buf_T **)s1; From 5b418992cf254137fde2a14d7066fbea5afddb28 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 27 Oct 2019 18:50:25 +0100 Subject: [PATCH 2/9] patch 8.1.2226: cannot use system copy/paste in non-xterm terminals Problem: Cannot use system copy/paste in non-xterm terminals. Solution: Instead of setting 'mouse' to "a" set it to "nvi" in defaults.vim. --- runtime/defaults.vim | 8 +++++++- runtime/doc/options.txt | 19 +++++++++++++------ runtime/doc/term.txt | 11 ++++++++++- src/version.c | 2 ++ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/runtime/defaults.vim b/runtime/defaults.vim index 255b67b470..e7929eacd4 100644 --- a/runtime/defaults.vim +++ b/runtime/defaults.vim @@ -75,8 +75,14 @@ inoremap u " In many terminal emulators the mouse works just fine. By enabling it you " can position the cursor, Visually select and scroll with the mouse. +" Only xterm can grab the mouse events when using the shift key, for other +" terminals use ":", select text and press Esc. if has('mouse') - set mouse=a + if &term =~ 'xterm' + set mouse=a + else + set mouse=nvi + endif endif " Switch syntax highlighting on when the terminal has colors or when using the diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6e4ff1d6f5..82cac9df12 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5191,12 +5191,11 @@ A jump table for the options with a short description can be found at |Q_op|. *'mouse'* *E538* 'mouse' string (default "", "a" for GUI, MS-DOS and Win32, - set to "a" in |defaults.vim|) + set to "a" or "nvi" in |defaults.vim|) global - Enable the use of the mouse. Only works for certain terminals - (xterm, MS-DOS, Win32 |win32-mouse|, QNX pterm, *BSD console with - sysmouse and Linux console with gpm). For using the mouse in the - GUI, see |gui-mouse|. + Enable the use of the mouse. Works for most terminals (xterm, MS-DOS, + Win32 |win32-mouse|, QNX pterm, *BSD console with sysmouse and Linux + console with gpm). For using the mouse in the GUI, see |gui-mouse|. The mouse can be enabled for different modes: n Normal mode and Terminal modes v Visual mode @@ -5207,7 +5206,15 @@ A jump table for the options with a short description can be found at |Q_op|. r for |hit-enter| and |more-prompt| prompt Normally you would enable the mouse in all five modes with: > :set mouse=a -< When the mouse is not enabled, the GUI will still use the mouse for +< If your terminal can't overrule the mouse events going to the + application, use: > + :set mouse=nvi +< The you can press ":", select text for the system, and press Esc to go + back to Vim using the mouse events. + In |defaults.vim| "nvi" is used if the 'term' option is not matching + "xterm". + + When the mouse is not enabled, the GUI will still use the mouse for modeless selection. This doesn't move the text cursor. See |mouse-using|. Also see |'clipboard'|. diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 133d0e991b..0a0f647781 100644 --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -746,12 +746,21 @@ jump to tags). Whether the selection that is started with the mouse is in Visual mode or Select mode depends on whether "mouse" is included in the 'selectmode' option. - + *terminal-mouse* In an xterm, with the currently active mode included in the 'mouse' option, normal mouse clicks are used by Vim, mouse clicks with the shift or ctrl key pressed go to the xterm. With the currently active mode not included in 'mouse' all mouse clicks go to the xterm. +For terminals where it is not possible to have the mouse events be used by the +terminal itself by using a modifier, a workaround is to not use mouse events +for Vim in command-line mode: > + :set mouse=nvi +Then to select text with the terminal, use ":" to go to command-line mode, +select and copy the text to the system, then press Esc. + +Another way is to temporarily use ":sh" to run a shell, copy the text, then +exit the shell. 'mouse' can remain set to "a" then. *xterm-clipboard* In the Athena and Motif GUI versions, when running in a terminal and there is access to the X-server (DISPLAY is set), the copy and paste will behave like diff --git a/src/version.c b/src/version.c index 3f36958a69..f5bc809aca 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2226, /**/ 2225, /**/ From 1c329c04be2e95a3589a53f2978926e91b450cca Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 27 Oct 2019 20:37:35 +0100 Subject: [PATCH 3/9] patch 8.1.2227: layout wrong if 'lines' changes while cmdline window is open Problem: Layout wrong if 'lines' changes while cmdline window is open. Solution: Do not restore the window layout if 'lines' changed. (closes #5130) --- src/testdir/dumps/Test_cmdwin_restore_1.dump | 12 ++++++++ src/testdir/dumps/Test_cmdwin_restore_2.dump | 12 ++++++++ src/testdir/dumps/Test_cmdwin_restore_3.dump | 18 ++++++++++++ src/testdir/test_cmdline.vim | 30 ++++++++++++++++++++ src/version.c | 2 ++ src/window.c | 17 +++++++---- 6 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 src/testdir/dumps/Test_cmdwin_restore_1.dump create mode 100644 src/testdir/dumps/Test_cmdwin_restore_2.dump create mode 100644 src/testdir/dumps/Test_cmdwin_restore_3.dump diff --git a/src/testdir/dumps/Test_cmdwin_restore_1.dump b/src/testdir/dumps/Test_cmdwin_restore_1.dump new file mode 100644 index 0000000000..8ac0295a04 --- /dev/null +++ b/src/testdir/dumps/Test_cmdwin_restore_1.dump @@ -0,0 +1,12 @@ +|0+0&#ffffff0| @73 +|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p +|0+0&&| @73 +|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p +|:+0#4040ff13&> +0#0000000&@73 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|[+3#0000000&|C|o|m@1|a|n|d| |L|i|n|e|]| @42|1|,|0|-|1| @9|A|l@1 +|:+0&&| @73 diff --git a/src/testdir/dumps/Test_cmdwin_restore_2.dump b/src/testdir/dumps/Test_cmdwin_restore_2.dump new file mode 100644 index 0000000000..ce0b2b5ba8 --- /dev/null +++ b/src/testdir/dumps/Test_cmdwin_restore_2.dump @@ -0,0 +1,12 @@ +>0+0&#ffffff0| @73 +|1| @73 +|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p +|0+0&&| @73 +|1| @73 +|2| @73 +|3| @73 +|4| @73 +|5| @73 +|6| @73 +|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|T|o|p +| +0&&@74 diff --git a/src/testdir/dumps/Test_cmdwin_restore_3.dump b/src/testdir/dumps/Test_cmdwin_restore_3.dump new file mode 100644 index 0000000000..1cc0f3f401 --- /dev/null +++ b/src/testdir/dumps/Test_cmdwin_restore_3.dump @@ -0,0 +1,18 @@ +>0+0&#ffffff0| @73 +|1| @73 +|2| @73 +|3| @73 +|4| @73 +|5| @73 +|6| @73 +|7| @73 +|8| @73 +|9| @73 +|1|0| @72 +|1@1| @72 +|1|2| @72 +|1|3| @72 +|1|4| @72 +|1|5| @72 +|1|6| @72 +@57|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 57dff41673..3f73d3da34 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -768,6 +768,36 @@ func Test_cmdwin_bug() bw! endfunc +func Test_cmdwin_restore() + CheckScreendump + + let lines =<< trim [SCRIPT] + call setline(1, range(30)) + 2split + [SCRIPT] + call writefile(lines, 'XTest_restore') + + let buf = RunVimInTerminal('-S XTest_restore', {'rows': 12}) + call term_wait(buf, 100) + call term_sendkeys(buf, "q:") + call VerifyScreenDump(buf, 'Test_cmdwin_restore_1', {}) + + " normal restore + call term_sendkeys(buf, ":q\") + call VerifyScreenDump(buf, 'Test_cmdwin_restore_2', {}) + + " restore after setting 'lines' with one window + call term_sendkeys(buf, ":close\") + call term_sendkeys(buf, "q:") + call term_sendkeys(buf, ":set lines=18\") + call term_sendkeys(buf, ":q\") + call VerifyScreenDump(buf, 'Test_cmdwin_restore_3', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('XTest_restore') +endfunc + func Test_buffers_lastused() " check that buffers are sorted by time when wildmode has lastused call test_settime(1550020000) " middle diff --git a/src/version.c b/src/version.c index f5bc809aca..7b4ebe6b56 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2227, /**/ 2226, /**/ diff --git a/src/window.c b/src/window.c index 8bb3269a0f..abdbd50796 100644 --- a/src/window.c +++ b/src/window.c @@ -5177,17 +5177,23 @@ win_size_save(garray_T *gap) win_T *wp; ga_init2(gap, (int)sizeof(int), 1); - if (ga_grow(gap, win_count() * 2) == OK) + if (ga_grow(gap, win_count() * 2 + 1) == OK) + { + // first entry is value of 'lines' + ((int *)gap->ga_data)[gap->ga_len++] = Rows; + FOR_ALL_WINDOWS(wp) { ((int *)gap->ga_data)[gap->ga_len++] = wp->w_width + wp->w_vsep_width; ((int *)gap->ga_data)[gap->ga_len++] = wp->w_height; } + } } /* - * Restore window sizes, but only if the number of windows is still the same. + * Restore window sizes, but only if the number of windows is still the same + * and 'lines' didn't change. * Does not free the growarray. */ void @@ -5196,13 +5202,14 @@ win_size_restore(garray_T *gap) win_T *wp; int i, j; - if (win_count() * 2 == gap->ga_len) + if (win_count() * 2 + 1 == gap->ga_len + && ((int *)gap->ga_data)[0] == Rows) { /* The order matters, because frames contain other frames, but it's * difficult to get right. The easy way out is to do it twice. */ for (j = 0; j < 2; ++j) { - i = 0; + i = 1; FOR_ALL_WINDOWS(wp) { frame_setwidth(wp->w_frame, ((int *)gap->ga_data)[i++]); @@ -6374,7 +6381,7 @@ min_rows(void) } /* - * Return TRUE if there is only one window (in the current tab page), not + * Return TRUE if there is only one window and only one tab page, not * counting a help or preview window, unless it is the current window. * Does not count unlisted windows. */ From 38ba4dce4a8574e60f6ddb111922880b0c7affdc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 27 Oct 2019 21:39:09 +0100 Subject: [PATCH 4/9] patch 8.1.2228: screenpos() returns wrong values when 'number' is set Problem: screenpos() returns wrong values when 'number' is set. (Ben Jackson) Solution: Compare the column with the window width. (closes #5133) --- src/move.c | 2 +- src/testdir/test_cursor_func.vim | 15 +++++++++++++++ src/version.c | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/move.c b/src/move.c index 97f5ac1b7d..d6b1c2636f 100644 --- a/src/move.c +++ b/src/move.c @@ -1217,7 +1217,7 @@ textpos2screenpos( col -= rowoff * width; } col -= wp->w_leftcol; - if (col >= width) + if (col >= wp->w_width) col = -1; if (col >= 0) coloff = col - scol + wp->w_wincol + 1; diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim index dc65fdca2c..0afc45e588 100644 --- a/src/testdir/test_cursor_func.vim +++ b/src/testdir/test_cursor_func.vim @@ -100,3 +100,18 @@ func Test_screenpos() close bwipe! endfunc + +func Test_screenpos_number() + rightbelow new + rightbelow 73vsplit + call setline (1, repeat('x', 66)) + setlocal number + redraw + let winid = win_getid() + let [winrow, wincol] = win_screenpos(winid) + let pos = screenpos(winid, 1, 66) + call assert_equal(winrow, pos.row) + call assert_equal(wincol + 66 + 3, pos.col) + close + bwipe! +endfunc diff --git a/src/version.c b/src/version.c index 7b4ebe6b56..01c95b335f 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2228, /**/ 2227, /**/ From efae76ab1a43d5a628d8c2fa4218ace6ba597f5d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 27 Oct 2019 22:54:58 +0100 Subject: [PATCH 5/9] patch 8.1.2229: cannot color number column above/below cursor differently Problem: Cannot color number column above/below cursor differently. Solution: Add LineNrAbove and LineNrBelow. (Shaun Brady, closes #624) --- runtime/doc/options.txt | 5 ++++ runtime/doc/syntax.txt | 6 ++++ src/drawline.c | 10 +++++++ src/optiondefs.h | 2 +- src/testdir/dumps/Test_relnr_colors_1.dump | 10 +++++++ src/testdir/dumps/Test_relnr_colors_2.dump | 10 +++++++ src/testdir/dumps/Test_relnr_colors_3.dump | 10 +++++++ src/testdir/dumps/Test_relnr_colors_4.dump | 10 +++++++ src/testdir/test_number.vim | 34 ++++++++++++++++++++++ src/version.c | 2 ++ src/vim.h | 6 ++-- 11 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 src/testdir/dumps/Test_relnr_colors_1.dump create mode 100644 src/testdir/dumps/Test_relnr_colors_2.dump create mode 100644 src/testdir/dumps/Test_relnr_colors_3.dump create mode 100644 src/testdir/dumps/Test_relnr_colors_4.dump diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 82cac9df12..1ef944d62d 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3923,6 +3923,7 @@ A jump table for the options with a short description can be found at |Q_op|. "8:SpecialKey,~:EndOfBuffer,@:NonText, d:Directory,e:ErrorMsg,i:IncSearch, l:Search,m:MoreMsg,M:ModeMsg,n:LineNr, + a:LineNrAbove,b:LineNrBelow, N:CursorLineNr,r:Question,s:StatusLine, S:StatusLineNC,c:VertSplit,t:Title, v:Visual,V:VisualNOS,w:WarningMsg, @@ -3954,6 +3955,10 @@ A jump table for the options with a short description can be found at |Q_op|. |hl-ModeMsg| M Mode (e.g., "-- INSERT --") |hl-LineNr| n line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set. + |hl-LineNrAbove| a line number above the cursor for when the + 'relativenumber' option is set. + |hl-LineNrBelow| b line number below the cursor for when the + 'relativenumber' option is set. |hl-CursorLineNr| N like n for when 'cursorline' or 'relativenumber' is set. |hl-Question| r |hit-enter| prompt and yes/no questions diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index e45ff81951..1c4988ade8 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -5071,6 +5071,12 @@ IncSearch 'incsearch' highlighting; also used for the text replaced with *hl-LineNr* LineNr Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set. + *hl-LineNrAbove* +LineNrAbove Line number for when the 'relativenumber' + option is set, above the cursor line. + *hl-LineNrBelow* +LineNrBelow Line number for when the 'relativenumber' + option is set, below the cursor line. *hl-CursorLineNr* CursorLineNr Like LineNr when 'cursorline' is set and 'cursorlineopt' is set to "number" or "both", or 'relativenumber' is set, for diff --git a/src/drawline.c b/src/drawline.c index 869bdaa0ef..7caba051b6 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -1127,6 +1127,16 @@ win_line( || wp->w_p_culopt_flags & CULOPT_LINE)) char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN)); #endif + if (wp->w_p_rnu && lnum < wp->w_cursor.lnum + && HL_ATTR(HLF_LNA) != 0) + // Use LineNrAbove + char_attr = hl_combine_attr(wcr_attr, + HL_ATTR(HLF_LNA)); + if (wp->w_p_rnu && lnum > wp->w_cursor.lnum + && HL_ATTR(HLF_LNB) != 0) + // Use LineNrBelow + char_attr = hl_combine_attr(wcr_attr, + HL_ATTR(HLF_LNB)); } } } diff --git a/src/optiondefs.h b/src/optiondefs.h index b557771cfb..a1d37f8341 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -289,7 +289,7 @@ struct vimoption # define ISP_LATIN1 (char_u *)"@,161-255" #endif -# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC" +# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC" // Default python version for pyx* commands #if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) diff --git a/src/testdir/dumps/Test_relnr_colors_1.dump b/src/testdir/dumps/Test_relnr_colors_1.dump new file mode 100644 index 0000000000..ad0ddd9323 --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_1.dump @@ -0,0 +1,10 @@ +| +0#ff404010#ffffff0@1|4| |1+0#0000000&|0|6| @42 +| +0#ff404010&@1|3| |1+0#0000000&|0|7| @42 +| +0#ff404010&@1|2| |1+0#0000000&|0|8| @42 +| +0#ff404010&@1|1| |1+0#0000000&|0|9| @42 +|1+0#ff404010&@2| >1+0#0000000&@1|0| @42 +| +0#ff404010&@1|1| |1+0#0000000&@2| @42 +| +0#ff404010&@1|2| |1+0#0000000&@1|2| @42 +| +0#ff404010&@1|3| |1+0#0000000&@1|3| @42 +| +0#ff404010&@1|4| |1+0#0000000&@1|4| @42 +@32|1@2|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_2.dump b/src/testdir/dumps/Test_relnr_colors_2.dump new file mode 100644 index 0000000000..0e80fc61fd --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_2.dump @@ -0,0 +1,10 @@ +| +0#4040ff13#ffffff0@1|4| |1+0#0000000&|0|6| @42 +| +0#4040ff13&@1|3| |1+0#0000000&|0|7| @42 +| +0#4040ff13&@1|2| |1+0#0000000&|0|8| @42 +| +0#4040ff13&@1|1| |1+0#0000000&|0|9| @42 +|1+0#ff404010&@2| >1+0#0000000&@1|0| @42 +| +0#ff404010&@1|1| |1+0#0000000&@2| @42 +| +0#ff404010&@1|2| |1+0#0000000&@1|2| @42 +| +0#ff404010&@1|3| |1+0#0000000&@1|3| @42 +| +0#ff404010&@1|4| |1+0#0000000&@1|4| @42 +|:|h|i| |L|i|n|e|N|r|A|b|o|v|e| |c|t|e|r|m|f|g|=|b|l|u|e| @3|1@2|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_3.dump b/src/testdir/dumps/Test_relnr_colors_3.dump new file mode 100644 index 0000000000..f54a5befc8 --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_3.dump @@ -0,0 +1,10 @@ +| +0#4040ff13#ffffff0@1|4| |1+0#0000000&|0|6| @42 +| +0#4040ff13&@1|3| |1+0#0000000&|0|7| @42 +| +0#4040ff13&@1|2| |1+0#0000000&|0|8| @42 +| +0#4040ff13&@1|1| |1+0#0000000&|0|9| @42 +|1+0#ff404010&@2| >1+0#0000000&@1|0| @42 +| +0#40ff4011&@1|1| |1+0#0000000&@2| @42 +| +0#40ff4011&@1|2| |1+0#0000000&@1|2| @42 +| +0#40ff4011&@1|3| |1+0#0000000&@1|3| @42 +| +0#40ff4011&@1|4| |1+0#0000000&@1|4| @42 +|:|h|i| |L|i|n|e|N|r|B|e|l|o|w| |c|t|e|r|m|f|g|=|g|r|e@1|n| @2|1@2|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_4.dump b/src/testdir/dumps/Test_relnr_colors_4.dump new file mode 100644 index 0000000000..82028190ee --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_4.dump @@ -0,0 +1,10 @@ +| +0#ff404010#ffffff0@1|4| |1+0#0000000&|0|6| @42 +| +0#ff404010&@1|3| |1+0#0000000&|0|7| @42 +| +0#ff404010&@1|2| |1+0#0000000&|0|8| @42 +| +0#ff404010&@1|1| |1+0#0000000&|0|9| @42 +|1+0#ff404010&@2| >1+0#0000000&@1|0| @42 +| +0#40ff4011&@1|1| |1+0#0000000&@2| @42 +| +0#40ff4011&@1|2| |1+0#0000000&@1|2| @42 +| +0#40ff4011&@1|3| |1+0#0000000&@1|3| @42 +| +0#40ff4011&@1|4| |1+0#0000000&@1|4| @42 +|:|h|i| |c|l|e|a|r| |L|i|n|e|N|r|A|b|o|v|e| @10|1@2|,|1| @8|5@1|%| diff --git a/src/testdir/test_number.vim b/src/testdir/test_number.vim index 81326bce14..5417585136 100644 --- a/src/testdir/test_number.vim +++ b/src/testdir/test_number.vim @@ -1,7 +1,10 @@ " Test for 'number' and 'relativenumber' +source check.vim source view_util.vim +source screendump.vim + func s:screen_lines(start, end) abort return ScreenLines([a:start, a:end], 8) endfunc @@ -263,3 +266,34 @@ func Test_relativenumber_uninitialised() redraw bwipe! endfunc + +func Test_relativenumber_colors() + CheckScreendump + + let lines =<< trim [CODE] + call setline(1, range(200)) + 111 + set number relativenumber + hi LineNr ctermfg=red + [CODE] + call writefile(lines, 'XTest_relnr') + + " Check that the balloon shows up after a mouse move + let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50}) + call term_wait(buf, 100) + " Default colors + call VerifyScreenDump(buf, 'Test_relnr_colors_1', {}) + + call term_sendkeys(buf, ":hi LineNrAbove ctermfg=blue\") + call VerifyScreenDump(buf, 'Test_relnr_colors_2', {}) + + call term_sendkeys(buf, ":hi LineNrBelow ctermfg=green\") + call VerifyScreenDump(buf, 'Test_relnr_colors_3', {}) + + call term_sendkeys(buf, ":hi clear LineNrAbove\") + call VerifyScreenDump(buf, 'Test_relnr_colors_4', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('XTest_relnr') +endfunc diff --git a/src/version.c b/src/version.c index 01c95b335f..350f596027 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2229, /**/ 2228, /**/ diff --git a/src/vim.h b/src/vim.h index 230f5b3f8d..7b2aa5be5b 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1382,6 +1382,8 @@ typedef enum , HLF_M // "--More--" message , HLF_CM // Mode (e.g., "-- INSERT --") , HLF_N // line number for ":number" and ":#" commands + , HLF_LNA // LineNrAbove + , HLF_LNB // LineNrBelow , HLF_CLN // current line number , HLF_R // return to continue message and yes/no questions , HLF_S // status lines @@ -1423,8 +1425,8 @@ typedef enum // The HL_FLAGS must be in the same order as the HLF_ enums! // When changing this also adjust the default for 'highlight'. #define HL_FLAGS {'8', '~', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \ - 'n', 'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \ - 'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \ + 'n', 'a', 'b', 'N', 'r', 's', 'S', 'c', 't', 'v', 'V', \ + 'w', 'W', 'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \ 'B', 'P', 'R', 'L', \ '+', '=', 'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', \ 'z', 'Z'} From 077ff436a77f95c69da219af8cd8f553ff4f9ff8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Oct 2019 00:42:21 +0100 Subject: [PATCH 6/9] patch 8.1.2230: MS-Windows: testing external commands can be improved Problem: MS-Windows: testing external commands can be improved. Solution: Adjust tests, remove duplicate test. (closes #4928) --- src/testdir/test_normal.vim | 3 +-- src/testdir/test_system.vim | 46 ++++++++++------------------------- src/testdir/test_terminal.vim | 17 ++++++++++--- src/testdir/test_undo.vim | 2 +- src/version.c | 2 ++ 5 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index da9c004a84..b37f613ede 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -408,8 +408,7 @@ func Test_normal10_expand() if executable('echo') " Test expand(`...`) i.e. backticks command expansion. - " MS-Windows has a trailing space. - call assert_match('^abcde *$', expand('`echo abcde`')) + call assert_equal('abcde', expand('`echo abcde`')) endif " Test expand(`=...`) i.e. backticks expression expansion diff --git a/src/testdir/test_system.vim b/src/testdir/test_system.vim index eabccfb371..e69a045522 100644 --- a/src/testdir/test_system.vim +++ b/src/testdir/test_system.vim @@ -18,44 +18,24 @@ func Test_System() call assert_equal(["as\r", "df\r"], systemlist('more', ["as\df"])) endif - if !executable('cat') || !executable('wc') - return - endif - - let out = 'echo 123'->system() - " On Windows we may get a trailing space. - if out != "123 \n" - call assert_equal("123\n", out) - endif - - let out = 'echo 123'->systemlist() - if !has('win32') - call assert_equal(["123"], out) - else - call assert_equal(["123\r"], out) - endif - - if executable('cat') - call assert_equal('123', system('cat', '123')) - call assert_equal(['123'], systemlist('cat', '123')) - call assert_equal(["as\df"], systemlist('cat', ["as\df"])) - endif - new Xdummy call setline(1, ['asdf', "pw\er", 'xxxx']) - let out = system('wc -l', bufnr('%')) - " On OS/X we get leading spaces - let out = substitute(out, '^ *', '', '') - call assert_equal("3\n", out) - let out = systemlist('wc -l', bufnr('%')) - " On Windows we may get a trailing CR. - if out != ["3\r"] + if executable('wc') + let out = system('wc -l', bufnr('%')) " On OS/X we get leading spaces - if type(out) == v:t_list - let out[0] = substitute(out[0], '^ *', '', '') + let out = substitute(out, '^ *', '', '') + call assert_equal("3\n", out) + + let out = systemlist('wc -l', bufnr('%')) + " On Windows we may get a trailing CR. + if out != ["3\r"] + " On OS/X we get leading spaces + if type(out) == v:t_list + let out[0] = substitute(out[0], '^ *', '', '') + endif + call assert_equal(['3'], out) endif - call assert_equal(['3'], out) endif if !has('win32') diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 212a15f314..9aae680b4f 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -563,11 +563,14 @@ func Test_terminal_finish_open_close() endfunc func Test_terminal_cwd() - if !executable('pwd') - return + if has('win32') + let cmd = 'cmd /c cd' + else + CheckExecutable pwd + let cmd = 'pwd' endif call mkdir('Xdir') - let buf = term_start('pwd', {'cwd': 'Xdir'}) + let buf = term_start(cmd, {'cwd': 'Xdir'}) call WaitForAssert({-> assert_equal('Xdir', fnamemodify(getline(1), ":t"))}) exe buf . 'bwipe' @@ -2031,7 +2034,13 @@ func Test_terminal_does_not_truncate_last_newlines() endfunc func Test_terminal_no_job() - let term = term_start('false', {'term_finish': 'close'}) + if has('win32') + let cmd = 'cmd /c ""' + else + CheckExecutable false + let cmd = 'false' + endif + let term = term_start(cmd, {'term_finish': 'close'}) call WaitForAssert({-> assert_equal(v:null, term_getjob(term)) }) endfunc diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index 4a534ae631..12d835b48e 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -458,7 +458,7 @@ funct Test_undofile() " Test undofile() with 'undodir' set to a non-existing directory. call assert_equal('', 'Xundofoo'->undofile()) - if isdirectory('/tmp') + if !has('win32') && isdirectory('/tmp') set undodir=/tmp if has('osx') call assert_equal('/tmp/%private%tmp%file', undofile('///tmp/file')) diff --git a/src/version.c b/src/version.c index 350f596027..07a8cd9e51 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2230, /**/ 2229, /**/ From 8b530c1ff91f07cf6b0289a536992b7dfbc86598 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Oct 2019 02:13:05 +0100 Subject: [PATCH 7/9] patch 8.1.2231: not easy to move to the middle of a text line Problem: Not easy to move to the middle of a text line. Solution: Add the gM command. (Yasuhiro Matsumoto, closes #2070) --- runtime/doc/index.txt | 1 + runtime/doc/motion.txt | 8 +++++++- runtime/doc/quickref.txt | 1 + runtime/doc/usr_25.txt | 9 +++++---- src/normal.c | 18 ++++++++++++++++++ src/testdir/test_normal.vim | 24 +++++++++++++++++++++++- src/version.c | 2 ++ 7 files changed, 57 insertions(+), 6 deletions(-) diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 6b7c822052..d6957f5128 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -781,6 +781,7 @@ tag char note action in Normal mode ~ |gn| gn 1,2 find the next match with the last used search pattern and Visually select it |gm| gm 1 go to character at middle of the screenline +|gM| gM 1 go to character at middle of the text line |go| go 1 cursor to byte N in the buffer |gp| ["x]gp 2 put the text [from register x] after the cursor N times, leave the cursor after it diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index f0935da0eb..9ac460a738 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -1,4 +1,4 @@ -*motion.txt* For Vim version 8.1. Last change: 2019 Jun 02 +*motion.txt* For Vim version 8.1. Last change: 2019 Oct 28 VIM REFERENCE MANUAL by Bram Moolenaar @@ -227,6 +227,12 @@ g^ When lines wrap ('wrap' on): To the first non-blank gm Like "g0", but half a screenwidth to the right (or as much as possible). + *gm* *gM* +gM Like "g0", but to halfway the text of the line. + With a count: to this percentage of text in the line. + Thus "10gM" is near the start of the text and "90gM" + is near the end of the text. + *g$* *g* g$ or g When lines wrap ('wrap' on): To the last character of the screen line and [count - 1] screen lines downward diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index fa15bca8d8..76067f5934 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -47,6 +47,7 @@ N is used to indicate an optional count that can be given before the command. |g$| N g$ to last character in screen line (differs from "$" when lines wrap) |gm| gm to middle of the screen line +|gM| gM to middle of the line |bar| N | to column N (default: 1) |f| N f{char} to the Nth occurrence of {char} to the right |F| N F{char} to the Nth occurrence of {char} to the left diff --git a/runtime/doc/usr_25.txt b/runtime/doc/usr_25.txt index 7f65a852e0..1f71f3e356 100644 --- a/runtime/doc/usr_25.txt +++ b/runtime/doc/usr_25.txt @@ -346,12 +346,13 @@ scroll: g0 to first visible character in this line g^ to first non-blank visible character in this line - gm to middle of this line + gm to middle of screen line + gM to middle of the text in this line g$ to last visible character in this line - |<-- window -->| - some long text, part of which is visible ~ - g0 g^ gm g$ + |<-- window -->| + some long text, part of which is visible in one line ~ + g0 g^ gm gM g$ BREAKING AT WORDS *edit-no-break* diff --git a/src/normal.c b/src/normal.c index f66a97c34b..17db06a167 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5979,6 +5979,24 @@ nv_g_cmd(cmdarg_T *cap) curwin->w_set_curswant = TRUE; break; + case 'M': + { + char_u *ptr = ml_get_curline(); + + oap->motion_type = MCHAR; + oap->inclusive = FALSE; + if (has_mbyte) + i = mb_string2cells(ptr, STRLEN(ptr)); + else + i = (int)STRLEN(ptr); + if (cap->count0 > 0 && cap->count0 <= 100) + coladvance((colnr_T)(i * cap->count0 / 100)); + else + coladvance((colnr_T)(i / 2)); + curwin->w_set_curswant = TRUE; + } + break; + case '_': /* "g_": to the last non-blank character in the line or lines * downward. */ diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index b37f613ede..c4b38b1c6c 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -1733,6 +1733,7 @@ fun! Test_normal33_g_cmd2() set wrap listchars= sbr= let lineA='abcdefghijklmnopqrstuvwxyz' let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + let lineC='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' $put =lineA $put =lineB @@ -1766,9 +1767,30 @@ fun! Test_normal33_g_cmd2() call assert_equal(15, col('.')) call assert_equal('l', getreg(0)) + norm! 2ggdd + $put =lineC + + " Test for gM + norm! gMyl + call assert_equal(73, col('.')) + call assert_equal('0', getreg(0)) + " Test for 20gM + norm! 20gMyl + call assert_equal(29, col('.')) + call assert_equal('S', getreg(0)) + " Test for 60gM + norm! 60gMyl + call assert_equal(87, col('.')) + call assert_equal('E', getreg(0)) + + " Test for g Ctrl-G + set ff=unix + let a=execute(":norm! g\") + call assert_match('Col 87 of 144; Line 2 of 2; Word 1 of 1; Byte 88 of 146', a) + " Test for gI norm! gIfoo - call assert_equal(['', 'fooabcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$')) + call assert_equal(['', 'foo0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'], getline(1,'$')) " Test for gi wincmd c diff --git a/src/version.c b/src/version.c index 07a8cd9e51..99f15701b5 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2231, /**/ 2230, /**/ From 69bf634858a2a75f2984e42b1e4017bc529a040a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 29 Oct 2019 04:16:57 +0100 Subject: [PATCH 8/9] patch 8.1.2233: cannot get the Vim command line arguments Problem: Cannot get the Vim command line arguments. Solution: Add v:argv. (Dmitri Vereshchagin, closes #1322) --- runtime/doc/eval.txt | 7 ++++++- src/evalvars.c | 22 ++++++++++++++++++++++ src/main.c | 6 +++++- src/normal.c | 2 +- src/proto/evalvars.pro | 1 + src/testdir/test_startup.vim | 12 ++++++++++++ src/version.c | 4 ++++ src/vim.h | 3 ++- 8 files changed, 53 insertions(+), 4 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f50c8c5b87..30ec02d3c4 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.1. Last change: 2019 Oct 26 +*eval.txt* For Vim version 8.1. Last change: 2019 Oct 29 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1662,6 +1662,10 @@ PREDEFINED VIM VARIABLES *vim-variable* *v:var* *v:* *E963* Some variables can be set by the user, but the type cannot be changed. + *v:argv* *argv-variable* +v:argv The command line arguments Vim was invoked with. This is a + list of strings. The first item is the Vim command. + *v:beval_col* *beval_col-variable* v:beval_col The number of the column, over which the mouse pointer is. This is the byte index in the |v:beval_lnum| line. @@ -3034,6 +3038,7 @@ argv([{nr} [, {winid}]) the whole |arglist| is returned. The {winid} argument specifies the window ID, see |argc()|. + For the Vim command line arguments see |v:argv|. assert_ functions are documented here: |assert-functions-details| diff --git a/src/evalvars.c b/src/evalvars.c index eb198fdf9f..3aaae13b45 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -143,6 +143,7 @@ static struct vimvar {VV_NAME("event", VAR_DICT), VV_RO}, {VV_NAME("versionlong", VAR_NUMBER), VV_RO}, {VV_NAME("echospace", VAR_NUMBER), VV_RO}, + {VV_NAME("argv", VAR_LIST), VV_RO}, }; // shorthand @@ -2085,6 +2086,27 @@ set_vim_var_dict(int idx, dict_T *val) } } +/* + * Set the v:argv list. + */ + void +set_argv_var(char **argv, int argc) +{ + list_T *l = list_alloc(); + int i; + + if (l == NULL) + getout(1); + l->lv_lock = VAR_FIXED; + for (i = 0; i < argc; ++i) + { + if (list_append_string(l, (char_u *)argv[i], -1) == FAIL) + getout(1); + l->lv_last->li_tv.v_lock = VAR_FIXED; + } + set_vim_var_list(VV_ARGV, l); +} + /* * Set v:register if needed. */ diff --git a/src/main.c b/src/main.c index 8001c3fbb7..2ec5c26317 100644 --- a/src/main.c +++ b/src/main.c @@ -1009,7 +1009,11 @@ common_init(mparm_T *paramp) TIME_MSG("inits 1"); #ifdef FEAT_EVAL - set_lang_var(); /* set v:lang and v:ctype */ + // set v:lang and v:ctype + set_lang_var(); + + // set v:argv + set_argv_var(paramp->argv, paramp->argc); #endif #ifdef FEAT_SIGNS diff --git a/src/normal.c b/src/normal.c index 17db06a167..f2527e144b 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5986,7 +5986,7 @@ nv_g_cmd(cmdarg_T *cap) oap->motion_type = MCHAR; oap->inclusive = FALSE; if (has_mbyte) - i = mb_string2cells(ptr, STRLEN(ptr)); + i = mb_string2cells(ptr, (int)STRLEN(ptr)); else i = (int)STRLEN(ptr); if (cap->count0 > 0 && cap->count0 <= 100) diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 691eec3492..bb8b5a1c65 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -41,6 +41,7 @@ void restore_vimvars(vimvars_save_T *vvsave); void set_vim_var_string(int idx, char_u *val, int len); void set_vim_var_list(int idx, list_T *val); void set_vim_var_dict(int idx, dict_T *val); +void set_argv_var(char **argv, int argc); void set_reg_var(int c); char_u *v_exception(char_u *oldval); char_u *v_throwpoint(char_u *oldval); diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index f10eabb798..358ca81718 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -671,3 +671,15 @@ func Test_start_with_tabs() " clean up call StopVimInTerminal(buf) endfunc + +func Test_v_argv() + " Can't catch the output of gvim. + CheckNotGui + + let out = system(GetVimCommand() . ' -es -V1 -X arg1 --cmd "echo v:argv" --cmd q') + let list = out->split("', '") + call assert_match('vim', list[0]) + let idx = index(list, 'arg1') + call assert_true(idx > 2) + call assert_equal(['arg1', '--cmd', 'echo v:argv', '--cmd', 'q'']'], list[idx:]) +endfunc diff --git a/src/version.c b/src/version.c index 99f15701b5..0e92901b7d 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,10 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2233, +/**/ + 2232, /**/ 2231, /**/ diff --git a/src/vim.h b/src/vim.h index 7b2aa5be5b..de5873c1b1 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1990,7 +1990,8 @@ typedef int sock_T; #define VV_EVENT 90 #define VV_VERSIONLONG 91 #define VV_ECHOSPACE 92 -#define VV_LEN 93 // number of v: vars +#define VV_ARGV 93 +#define VV_LEN 94 // number of v: vars // used for v_number in VAR_SPECIAL #define VVAL_FALSE 0L From 3f39697b73f661d6900c7cf5430d967a129660d7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 30 Oct 2019 04:10:06 +0100 Subject: [PATCH 9/9] patch 8.1.2234: get_short_pathname() fails depending on encoding Problem: get_short_pathname() fails depending on encoding. Solution: Use the wide version of the library function. (closes #5129) --- src/filepath.c | 50 ++++++++++++++++++++++++------ src/testdir/test_shortpathname.vim | 20 ++++++++++++ src/version.c | 2 ++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/filepath.c b/src/filepath.c index cf401dc6d5..4ddeeaf45a 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -30,26 +30,56 @@ get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen) { int l, len; - char_u *newbuf; + WCHAR *newbuf; + WCHAR *wfname; - len = *fnamelen; - l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len); + len = MAXPATHL; + newbuf = malloc(len * sizeof(*newbuf)); + if (newbuf == NULL) + return FAIL; + + wfname = enc_to_utf16(*fnamep, NULL); + if (wfname == NULL) + { + vim_free(newbuf); + return FAIL; + } + + l = GetShortPathNameW(wfname, newbuf, len); if (l > len - 1) { // If that doesn't work (not enough space), then save the string // and try again with a new buffer big enough. - newbuf = vim_strnsave(*fnamep, l); + WCHAR *newbuf_t = newbuf; + newbuf = vim_realloc(newbuf, (l + 1) * sizeof(*newbuf)); if (newbuf == NULL) + { + vim_free(wfname); + vim_free(newbuf_t); return FAIL; - - vim_free(*bufp); - *fnamep = *bufp = newbuf; - + } // Really should always succeed, as the buffer is big enough. - l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1); + l = GetShortPathNameW(wfname, newbuf, l+1); } + if (l != 0) + { + char_u *p = utf16_to_enc(newbuf, NULL); + if (p != NULL) + { + vim_free(*bufp); + *fnamep = *bufp = p; + } + else + { + vim_free(wfname); + vim_free(newbuf); + return FAIL; + } + } + vim_free(wfname); + vim_free(newbuf); - *fnamelen = l; + *fnamelen = l == 0 ? l : STRLEN(*bufp); return OK; } diff --git a/src/testdir/test_shortpathname.vim b/src/testdir/test_shortpathname.vim index b88482016c..6b3f85f181 100644 --- a/src/testdir/test_shortpathname.vim +++ b/src/testdir/test_shortpathname.vim @@ -1,6 +1,9 @@ " Test for shortpathname ':8' extension. " Only for use on Win32 systems! +set encoding=utf-8 +scriptencoding utf-8 + source check.vim CheckMSWindows @@ -67,3 +70,20 @@ func Test_ColonEight() exe "cd " . save_dir endfunc + +func Test_ColonEight_MultiByte() + let dir = 'Xtest' + + let file = dir . '/日本語のファイル.txt' + + call mkdir(dir) + call writefile([], file) + + let sfile = fnamemodify(file, ':8') + + call assert_notequal(file, sfile) + call assert_match('\~', sfile) + + call delete(file) + call delete(dir, 'd') +endfunc diff --git a/src/version.c b/src/version.c index 0e92901b7d..324f40d707 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2234, /**/ 2233, /**/