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/eval.txt b/runtime/doc/eval.txt index f35516ff77..23bdb0129a 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. @@ -3046,6 +3050,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| @@ -4790,6 +4795,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/index.txt b/runtime/doc/index.txt index 1afc916880..5325c02421 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/options.txt b/runtime/doc/options.txt index a9cbb4c184..d71c6b344c 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4034,6 +4034,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, @@ -4065,6 +4066,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 @@ -5340,12 +5345,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 @@ -5356,7 +5360,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'|. @@ -8852,6 +8864,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/quickref.txt b/runtime/doc/quickref.txt index 065ef79865..894580f4cc 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/syntax.txt b/runtime/doc/syntax.txt index d9bbbc6661..eb639f5d2b 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/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/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/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 30c0fbb176..db342fd3d5 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2605,6 +2605,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". @@ -2623,6 +2630,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; @@ -2679,7 +2689,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; } } } @@ -2695,6 +2714,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); @@ -2705,6 +2728,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); } @@ -3020,7 +3065,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; @@ -3030,7 +3075,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); @@ -3104,13 +3174,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/drawline.c b/src/drawline.c index 5642f130c3..f4273996bd 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/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/evalvars.c b/src/evalvars.c index 7ae8e4d3b9..701a81651a 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -143,6 +143,8 @@ 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}, + // MacVim-specific value go here {VV_NAME("os_appearance", VAR_NUMBER), VV_RO}, }; @@ -2086,6 +2088,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/ex_getln.c b/src/ex_getln.c index 56946ba6f2..44a58fa279 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/filepath.c b/src/filepath.c index 8ff46a8518..eb2a5d0dd6 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/main.c b/src/main.c index 7b1e61f82c..cacc917063 100644 --- a/src/main.c +++ b/src/main.c @@ -1073,7 +1073,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/misc1.c b/src/misc1.c index 2c3f74b287..bcd0f86724 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -2583,3 +2583,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/move.c b/src/move.c index 4b61707c39..b2c74eccfa 100644 --- a/src/move.c +++ b/src/move.c @@ -1246,7 +1246,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/normal.c b/src/normal.c index cbc42181e3..46021a972f 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5991,6 +5991,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, (int)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/option.c b/src/option.c index 362a6bc934..442d1e4726 100644 --- a/src/option.c +++ b/src/option.c @@ -7103,6 +7103,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 90f083b5e7..40dab917fa 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/optiondefs.h b/src/optiondefs.h index f1e1f3fe54..f62278c088 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -292,7 +292,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/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/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/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/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_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..3f73d3da34 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -767,3 +767,78 @@ func Test_cmdwin_bug() endtry 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 + 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_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/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/testdir/test_normal.vim b/src/testdir/test_normal.vim index da9c004a84..c4b38b1c6c 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 @@ -1734,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 @@ -1767,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/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/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/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/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 afd484140d..50cc6afce8 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' @@ -2036,7 +2039,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/undo.c b/src/undo.c index 42c69b0f7e..f394caaae1 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 ddd4f6dd53..64c5d21311 100644 --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,26 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2234, +/**/ + 2233, +/**/ + 2232, +/**/ + 2231, +/**/ + 2230, +/**/ + 2229, +/**/ + 2228, +/**/ + 2227, +/**/ + 2226, +/**/ + 2225, /**/ 2224, /**/ diff --git a/src/vim.h b/src/vim.h index dfdd63dd50..13f1cbab12 100644 --- a/src/vim.h +++ b/src/vim.h @@ -813,6 +813,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 @@ -1384,6 +1385,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 @@ -1425,8 +1428,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'} @@ -1990,8 +1993,10 @@ typedef int sock_T; #define VV_EVENT 90 #define VV_VERSIONLONG 91 #define VV_ECHOSPACE 92 -#define VV_OS_APPEARANCE 93 -#define VV_LEN 94 // number of v: vars +#define VV_ARGV 93 +// MacVim-specific values go here +#define VV_OS_APPEARANCE 94 +#define VV_LEN 95 // number of v: vars // used for v_number in VAR_SPECIAL #define VVAL_FALSE 0L 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; diff --git a/src/window.c b/src/window.c index 14e673692e..c769cb90da 100644 --- a/src/window.c +++ b/src/window.c @@ -5182,17 +5182,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 @@ -5201,13 +5207,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++]); @@ -6387,7 +6394,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. */