diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 97f66c7b11..0465254c1a 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2409,6 +2409,7 @@ submatch({nr} [, {list}]) String or List specific match in ":s" or substitute() substitute({expr}, {pat}, {sub}, {flags}) String all {pat} in {expr} replaced with {sub} +swapinfo({fname}) Dict information about swap file {fname} synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col} synIDattr({synID}, {what} [, {mode}]) String attribute {what} of syntax ID {synID} @@ -2497,6 +2498,7 @@ win_screenpos({nr}) List get screen position of window {nr} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} +winlayout([{tabnr}]) List layout of windows in tab {tabnr} winline() Number window line of the cursor winnr([{expr}]) Number number of current window winrestcmd() String returns command to restore window sizes @@ -8000,6 +8002,24 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()* |submatch()| returns. Example: > :echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g') +swapinfo({fname}) swapinfo() + The result is a dictionary, which holds information about the + swapfile {fname}. The available fields are: + version VIM version + user user name + host host name + fname original file name + pid PID of the VIM process that created the swap + file + mtime last modification time in seconds + inode Optional: INODE number of the file + dirty 1 if file was modified, 0 if not + In case of failure an "error" item is added with the reason: + Cannot open file: file not found or in accessible + Cannot read file: cannot read first block + Not a swap file: does not contain correct block ID + Magic number mismatch: Info in first block is invalid + synID({lnum}, {col}, {trans}) *synID()* The result is a Number, which is the syntax ID at the position {lnum} and {col} in the current window. @@ -9087,6 +9107,35 @@ winheight({nr}) *winheight()* This excludes any window toolbar line. Examples: > :echo "The current window has " . winheight(0) . " lines." +< +winlayout([{tabnr}]) *winlayout()* + The result is a nested List containing the layout of windows + in a tabpage. + + Without {tabnr} use the current tabpage, otherwise the tabpage + with number {tabnr}. If the tabpage {tabnr} is not found, + returns an empty list. + + For a leaf window, it returns: + ['leaf', {winid}] + For horizontally split windows, which form a column, it + returns: + ['col', [{nested list of windows}]] + For vertically split windows, which form a row, it returns: + ['row', [{nested list of windows}]] + + Example: > + " Only one window in the tab page + :echo winlayout() + ['leaf', 1000] + " Two horizontally split windows + :echo winlayout() + ['col', [['leaf', 1000], ['leaf', 1001]]] + " Three horizontally split windows, with two + " vertically split windows in the middle window + :echo winlayout(2) + ['col', [['leaf', 1002], ['row', ['leaf', 1003], + ['leaf', 1001]]], ['leaf', 1000]] < *winline()* winline() The result is a Number, which is the screen line of the cursor diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 1399d8bed4..211fe96117 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1551,6 +1551,22 @@ The backslashes before the pipe character are required to avoid it to be recognized as a command separator. The backslash before each space is required for the set command. + *cfilter-plugin* +If you have too many matching messages, you can use the cfilter plugin to +reduce the number of entries. Load the plugin with: > + packadd cfilter + +Then you can use these command: > + :Cfilter[!] {pat} + :Lfilter[!] {pat} + +:Cfilter creates a new quickfix list from entries matching {pat} in the +current quickfix list. Both the file name and the text of the entries are +matched against {pat}. If ! is supplied, then entries not matching {pat} are +used. + +:Lfilter does the same as :Cfilter but operates on the current location list. + ============================================================================= 8. The directory stack *quickfix-directory-stack* diff --git a/runtime/pack/dist/opt/cfilter/plugin/cfilter.vim b/runtime/pack/dist/opt/cfilter/plugin/cfilter.vim new file mode 100644 index 0000000000..7a6464fc98 --- /dev/null +++ b/runtime/pack/dist/opt/cfilter/plugin/cfilter.vim @@ -0,0 +1,43 @@ +" cfilter.vim: Plugin to filter entries from a quickfix/location list +" Last Change: May 12, 2018 +" Maintainer: Yegappan Lakshmanan (yegappan AT yahoo DOT com) +" Version: 1.0 +" +" Commands to filter the quickfix list: +" :Cfilter[!] {pat} +" Create a new quickfix list from entries matching {pat} in the current +" quickfix list. Both the file name and the text of the entries are +" matched against {pat}. If ! is supplied, then entries not matching +" {pat} are used. +" :Lfilter[!] {pat} +" Same as :Cfilter but operates on the current location list. +" +if exists("loaded_cfilter") + finish +endif +let loaded_cfilter = 1 + +func s:Qf_filter(qf, pat, bang) + if a:qf + let Xgetlist = function('getqflist') + let Xsetlist = function('setqflist') + let cmd = ':Cfilter' . a:bang + else + let Xgetlist = function('getloclist', [0]) + let Xsetlist = function('setloclist', [0]) + let cmd = ':Lfilter' . a:bang + endif + + if a:bang == '!' + let cond = 'v:val.text !~# a:pat && bufname(v:val.bufnr) !~# a:pat' + else + let cond = 'v:val.text =~# a:pat || bufname(v:val.bufnr) =~# a:pat' + endif + + let items = filter(Xgetlist(), cond) + let title = cmd . ' ' . a:pat + call Xsetlist([], ' ', {'title' : title, 'items' : items}) +endfunc + +com! -nargs=+ -bang Cfilter call s:Qf_filter(1, , ) +com! -nargs=+ -bang Lfilter call s:Qf_filter(0, , ) diff --git a/src/buffer.c b/src/buffer.c index 8396846ea7..1d0170ed28 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1039,7 +1039,14 @@ handle_swap_exists(bufref_T *old_curbuf) buf = old_curbuf->br_buf; if (buf != NULL) { + int old_msg_silent = msg_silent; + + if (shortmess(SHM_FILEINFO)) + msg_silent = 1; // prevent fileinfo message enter_buffer(buf); + // restore msg_silent, so that the command line will be shown + msg_silent = old_msg_silent; + # ifdef FEAT_SYN_HL if (old_tw != curbuf->b_p_tw) check_colorcolumn(curwin); @@ -1178,26 +1185,14 @@ do_bufdel( else if (deleted >= p_report) { if (command == DOBUF_UNLOAD) - { - if (deleted == 1) - MSG(_("1 buffer unloaded")); - else - smsg((char_u *)_("%d buffers unloaded"), deleted); - } + smsg((char_u *)NGETTEXT("%d buffer unloaded", + "%d buffers unloaded", deleted), deleted); else if (command == DOBUF_DEL) - { - if (deleted == 1) - MSG(_("1 buffer deleted")); - else - smsg((char_u *)_("%d buffers deleted"), deleted); - } + smsg((char_u *)NGETTEXT("%d buffer deleted", + "%d buffers deleted", deleted), deleted); else - { - if (deleted == 1) - MSG(_("1 buffer wiped out")); - else - smsg((char_u *)_("%d buffers wiped out"), deleted); - } + smsg((char_u *)NGETTEXT("%d buffer wiped out", + "%d buffers wiped out", deleted), deleted); } } @@ -3489,19 +3484,14 @@ fileinfo( n = (int)(((long)curwin->w_cursor.lnum * 100L) / (long)curbuf->b_ml.ml_line_count); if (curbuf->b_ml.ml_flags & ML_EMPTY) - { vim_snprintf_add((char *)buffer, IOSIZE, "%s", _(no_lines_msg)); - } #ifdef FEAT_CMDL_INFO else if (p_ru) - { /* Current line and column are already on the screen -- webb */ - if (curbuf->b_ml.ml_line_count == 1) - vim_snprintf_add((char *)buffer, IOSIZE, _("1 line --%d%%--"), n); - else - vim_snprintf_add((char *)buffer, IOSIZE, _("%ld lines --%d%%--"), - (long)curbuf->b_ml.ml_line_count, n); - } + vim_snprintf_add((char *)buffer, IOSIZE, + NGETTEXT("%ld line --%d%%--", "%ld lines --%d%%--", + curbuf->b_ml.ml_line_count), + (long)curbuf->b_ml.ml_line_count, n); #endif else { diff --git a/src/dosinst.c b/src/dosinst.c index 64edbbdae4..182546e885 100644 --- a/src/dosinst.c +++ b/src/dosinst.c @@ -1575,18 +1575,13 @@ install_registry(void) } printf("Creating an uninstall entry\n"); + sprintf(display_name, "Vim " VIM_VERSION_SHORT); /* For the NSIS installer use the generated uninstaller. */ if (interactive) - { - sprintf(display_name, "Vim " VIM_VERSION_SHORT); sprintf(uninstall_string, "%s\\uninstal.exe", installdir); - } else - { - sprintf(display_name, "Vim " VIM_VERSION_SHORT " (self-installing)"); sprintf(uninstall_string, "%s\\uninstall-gui.exe", installdir); - } lRet = register_uninstall( HKEY_LOCAL_MACHINE, diff --git a/src/evalfunc.c b/src/evalfunc.c index 71176fc1c4..b8a72f5db5 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -398,6 +398,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv); static void f_strwidth(typval_T *argvars, typval_T *rettv); static void f_submatch(typval_T *argvars, typval_T *rettv); static void f_substitute(typval_T *argvars, typval_T *rettv); +static void f_swapinfo(typval_T *argvars, typval_T *rettv); static void f_synID(typval_T *argvars, typval_T *rettv); static void f_synIDattr(typval_T *argvars, typval_T *rettv); static void f_synIDtrans(typval_T *argvars, typval_T *rettv); @@ -463,6 +464,7 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv); static void f_winbufnr(typval_T *argvars, typval_T *rettv); static void f_wincol(typval_T *argvars, typval_T *rettv); static void f_winheight(typval_T *argvars, typval_T *rettv); +static void f_winlayout(typval_T *argvars, typval_T *rettv); static void f_winline(typval_T *argvars, typval_T *rettv); static void f_winnr(typval_T *argvars, typval_T *rettv); static void f_winrestcmd(typval_T *argvars, typval_T *rettv); @@ -858,6 +860,7 @@ static struct fst {"strwidth", 1, 1, f_strwidth}, {"submatch", 1, 2, f_submatch}, {"substitute", 4, 4, f_substitute}, + {"swapinfo", 1, 1, f_swapinfo}, {"synID", 3, 3, f_synID}, {"synIDattr", 2, 3, f_synIDattr}, {"synIDtrans", 1, 1, f_synIDtrans}, @@ -952,6 +955,7 @@ static struct fst {"winbufnr", 1, 1, f_winbufnr}, {"wincol", 0, 0, f_wincol}, {"winheight", 1, 1, f_winheight}, + {"winlayout", 0, 1, f_winlayout}, {"winline", 0, 0, f_winline}, {"winnr", 0, 1, f_winnr}, {"winrestcmd", 0, 0, f_winrestcmd}, @@ -12342,6 +12346,16 @@ f_substitute(typval_T *argvars, typval_T *rettv) rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg); } +/* + * "swapinfo(swap_filename)" function + */ + static void +f_swapinfo(typval_T *argvars, typval_T *rettv) +{ + if (rettv_dict_alloc(rettv) == OK) + get_b0_dict(get_tv_string(argvars), rettv->vval.v_dict); +} + /* * "synID(lnum, col, trans)" function */ @@ -13773,6 +13787,29 @@ f_winheight(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = wp->w_height; } +/* + * "winlayout()" function + */ + static void +f_winlayout(typval_T *argvars, typval_T *rettv) +{ + tabpage_T *tp; + + if (rettv_list_alloc(rettv) != OK) + return; + + if (argvars[0].v_type == VAR_UNKNOWN) + tp = curtab; + else + { + tp = find_tabpage((int)get_tv_number(&argvars[0])); + if (tp == NULL) + return; + } + + get_framelayout(tp->tp_topframe, rettv->vval.v_list, TRUE); +} + /* * "winline()" function */ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index bee50c5955..6e713c49a3 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -985,12 +985,8 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest) ml_delete(line1 + extra, TRUE); if (!global_busy && num_lines > p_report) - { - if (num_lines == 1) - MSG(_("1 line moved")); - else - smsg((char_u *)_("%ld lines moved"), num_lines); - } + smsg((char_u *)NGETTEXT("%ld line moved", "%ld lines moved", num_lines), + (long)num_lines); /* * Leave the cursor on the last of the moved lines. @@ -5940,23 +5936,29 @@ do_sub_msg( || count_only) && messaging()) { + char *msg_single; + char *msg_plural; + if (got_int) STRCPY(msg_buf, _("(Interrupted) ")); else *msg_buf = NUL; - if (sub_nsubs == 1) - vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), - "%s", count_only ? _("1 match") : _("1 substitution")); - else - vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), - count_only ? _("%ld matches") : _("%ld substitutions"), - sub_nsubs); - if (sub_nlines == 1) - vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), - "%s", _(" on 1 line")); - else - vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), - _(" on %ld lines"), (long)sub_nlines); + + msg_single = count_only + ? NGETTEXT("%ld match on %ld line", + "%ld matches on %ld line", sub_nsubs) + : NGETTEXT("%ld substitution on %ld line", + "%ld substitutions on %ld line", sub_nsubs); + msg_plural = count_only + ? NGETTEXT("%ld match on %ld lines", + "%ld matches on %ld lines", sub_nsubs) + : NGETTEXT("%ld substitution on %ld lines", + "%ld substitutions on %ld lines", sub_nsubs); + + vim_snprintf_add((char *)msg_buf, sizeof(msg_buf), + NGETTEXT(msg_single, msg_plural, sub_nlines), + sub_nsubs, (long)sub_nlines); + if (msg(msg_buf)) /* save message to display it after redraw */ set_keep_msg(msg_buf, 0); diff --git a/src/ex_cmds.h b/src/ex_cmds.h index ff9083a871..0434197268 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -1797,6 +1797,12 @@ struct exarg void *cookie; /* argument for getline() */ #ifdef FEAT_EVAL struct condstack *cstack; /* condition stack for ":if" etc. */ +#endif + long verbose_save; // saved value of p_verbose + int save_msg_silent; // saved value of msg_silent + int did_esilent; // how many times emsg_silent was incremented +#ifdef HAVE_SANDBOX + int did_sandbox; // when TRUE did ++sandbox #endif }; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 2e05e4b508..4960f0bf8a 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -68,6 +68,7 @@ static char_u *do_one_cmd(char_u **, int, struct condstack *, char_u *(*fgetline static char_u *do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie); static int if_level = 0; /* depth in :if */ #endif +static void free_cmdmod(void); static void append_command(char_u *cmd); static char_u *find_command(exarg_T *eap, int *full); @@ -1716,13 +1717,7 @@ do_one_cmd( char_u *errormsg = NULL; /* error message */ char_u *after_modifier = NULL; exarg_T ea; /* Ex command arguments */ - long verbose_save = -1; int save_msg_scroll = msg_scroll; - int save_msg_silent = -1; - int did_esilent = 0; -#ifdef HAVE_SANDBOX - int did_sandbox = FALSE; -#endif cmdmod_T save_cmdmod; int ni; /* set when Not Implemented */ char_u *cmd; @@ -1749,236 +1744,26 @@ do_one_cmd( * recursive calls. */ save_cmdmod = cmdmod; - vim_memset(&cmdmod, 0, sizeof(cmdmod)); /* "#!anything" is handled like a comment. */ if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!') goto doend; - /* - * Repeat until no more command modifiers are found. - */ - ea.cmd = *cmdlinep; - for (;;) - { /* * 1. Skip comment lines and leading white space and colons. - */ - while (*ea.cmd == ' ' || *ea.cmd == '\t' || *ea.cmd == ':') - ++ea.cmd; - - /* in ex mode, an empty line works like :+ */ - if (*ea.cmd == NUL && exmode_active - && (getline_equal(fgetline, cookie, getexmodeline) - || getline_equal(fgetline, cookie, getexline)) - && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) - { - ea.cmd = (char_u *)"+"; - ex_pressedreturn = TRUE; - } - - /* ignore comment and empty lines */ - if (*ea.cmd == '"') - goto doend; - if (*ea.cmd == NUL) - { - ex_pressedreturn = TRUE; - goto doend; - } - -/* * 2. Handle command modifiers. */ - p = skip_range(ea.cmd, NULL); - switch (*p) - { - /* When adding an entry, also modify cmd_exists(). */ - case 'a': if (!checkforcmd(&ea.cmd, "aboveleft", 3)) - break; - cmdmod.split |= WSP_ABOVE; - continue; - - case 'b': if (checkforcmd(&ea.cmd, "belowright", 3)) - { - cmdmod.split |= WSP_BELOW; - continue; - } - if (checkforcmd(&ea.cmd, "browse", 3)) - { -#ifdef FEAT_BROWSE_CMD - cmdmod.browse = TRUE; + // The "ea" structure holds the arguments that can be used. + ea.cmd = *cmdlinep; + ea.cmdlinep = cmdlinep; + ea.getline = fgetline; + ea.cookie = cookie; +#ifdef FEAT_EVAL + ea.cstack = cstack; #endif - continue; - } - if (!checkforcmd(&ea.cmd, "botright", 2)) - break; - cmdmod.split |= WSP_BOT; - continue; + if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL) + goto doend; - case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4)) - break; -#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) - cmdmod.confirm = TRUE; -#endif - continue; - - case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3)) - { - cmdmod.keepmarks = TRUE; - continue; - } - if (checkforcmd(&ea.cmd, "keepalt", 5)) - { - cmdmod.keepalt = TRUE; - continue; - } - if (checkforcmd(&ea.cmd, "keeppatterns", 5)) - { - cmdmod.keeppatterns = TRUE; - continue; - } - if (!checkforcmd(&ea.cmd, "keepjumps", 5)) - break; - cmdmod.keepjumps = TRUE; - continue; - - case 'f': /* only accept ":filter {pat} cmd" */ - { - char_u *reg_pat; - - if (!checkforcmd(&p, "filter", 4) - || *p == NUL || ends_excmd(*p)) - break; - if (*p == '!') - { - cmdmod.filter_force = TRUE; - p = skipwhite(p + 1); - if (*p == NUL || ends_excmd(*p)) - break; - } - p = skip_vimgrep_pat(p, ®_pat, NULL); - if (p == NULL || *p == NUL) - break; - cmdmod.filter_regmatch.regprog = - vim_regcomp(reg_pat, RE_MAGIC); - if (cmdmod.filter_regmatch.regprog == NULL) - break; - ea.cmd = p; - continue; - } - - /* ":hide" and ":hide | cmd" are not modifiers */ - case 'h': if (p != ea.cmd || !checkforcmd(&p, "hide", 3) - || *p == NUL || ends_excmd(*p)) - break; - ea.cmd = p; - cmdmod.hide = TRUE; - continue; - - case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3)) - { - cmdmod.lockmarks = TRUE; - continue; - } - - if (!checkforcmd(&ea.cmd, "leftabove", 5)) - break; - cmdmod.split |= WSP_ABOVE; - continue; - - case 'n': if (checkforcmd(&ea.cmd, "noautocmd", 3)) - { - if (cmdmod.save_ei == NULL) - { - /* Set 'eventignore' to "all". Restore the - * existing option value later. */ - cmdmod.save_ei = vim_strsave(p_ei); - set_string_option_direct((char_u *)"ei", -1, - (char_u *)"all", OPT_FREE, SID_NONE); - } - continue; - } - if (!checkforcmd(&ea.cmd, "noswapfile", 3)) - break; - cmdmod.noswapfile = TRUE; - continue; - - case 'r': if (!checkforcmd(&ea.cmd, "rightbelow", 6)) - break; - cmdmod.split |= WSP_BELOW; - continue; - - case 's': if (checkforcmd(&ea.cmd, "sandbox", 3)) - { -#ifdef HAVE_SANDBOX - if (!did_sandbox) - ++sandbox; - did_sandbox = TRUE; -#endif - continue; - } - if (!checkforcmd(&ea.cmd, "silent", 3)) - break; - if (save_msg_silent == -1) - save_msg_silent = msg_silent; - ++msg_silent; - if (*ea.cmd == '!' && !VIM_ISWHITE(ea.cmd[-1])) - { - /* ":silent!", but not "silent !cmd" */ - ea.cmd = skipwhite(ea.cmd + 1); - ++emsg_silent; - ++did_esilent; - } - continue; - - case 't': if (checkforcmd(&p, "tab", 3)) - { - long tabnr = get_address(&ea, &ea.cmd, ADDR_TABS, - ea.skip, FALSE, 1); - if (tabnr == MAXLNUM) - cmdmod.tab = tabpage_index(curtab) + 1; - else - { - if (tabnr < 0 || tabnr > LAST_TAB_NR) - { - errormsg = (char_u *)_(e_invrange); - goto doend; - } - cmdmod.tab = tabnr + 1; - } - ea.cmd = p; - continue; - } - if (!checkforcmd(&ea.cmd, "topleft", 2)) - break; - cmdmod.split |= WSP_TOP; - continue; - - case 'u': if (!checkforcmd(&ea.cmd, "unsilent", 3)) - break; - if (save_msg_silent == -1) - save_msg_silent = msg_silent; - msg_silent = 0; - continue; - - case 'v': if (checkforcmd(&ea.cmd, "vertical", 4)) - { - cmdmod.split |= WSP_VERT; - continue; - } - if (!checkforcmd(&p, "verbose", 4)) - break; - if (verbose_save < 0) - verbose_save = p_verbose; - if (vim_isdigit(*ea.cmd)) - p_verbose = atoi((char *)ea.cmd); - else - p_verbose = 1; - ea.cmd = p; - continue; - } - break; - } after_modifier = ea.cmd; #ifdef FEAT_EVAL @@ -1988,28 +1773,6 @@ do_one_cmd( ea.skip = (if_level > 0); #endif -#ifdef FEAT_EVAL -# ifdef FEAT_PROFILE - /* Count this line for profiling if ea.skip is FALSE. */ - if (do_profiling == PROF_YES && !ea.skip) - { - if (getline_equal(fgetline, cookie, get_func_line)) - func_line_exec(getline_cookie(fgetline, cookie)); - else if (getline_equal(fgetline, cookie, getsourceline)) - script_line_exec(); - } -#endif - - /* May go to debug mode. If this happens and the ">quit" debug command is - * used, throw an interrupt exception and skip the next command. */ - dbg_check_breakpoint(&ea); - if (!ea.skip && got_int) - { - ea.skip = TRUE; - (void)do_intthrow(cstack); - } -#endif - /* * 3. Skip over the range to find the command. Let "p" point to after it. * @@ -2021,6 +1784,51 @@ do_one_cmd( ea.cmd = skipwhite(ea.cmd + 1); p = find_command(&ea, NULL); +#ifdef FEAT_EVAL +# ifdef FEAT_PROFILE + // Count this line for profiling if skip is TRUE. + if (do_profiling == PROF_YES + && (!ea.skip || cstack->cs_idx == 0 || (cstack->cs_idx > 0 + && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) + { + int skip = did_emsg || got_int || did_throw; + + if (ea.cmdidx == CMD_catch) + skip = !skip && !(cstack->cs_idx >= 0 + && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN) + && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT)); + else if (ea.cmdidx == CMD_else || ea.cmdidx == CMD_elseif) + skip = skip || !(cstack->cs_idx >= 0 + && !(cstack->cs_flags[cstack->cs_idx] + & (CSF_ACTIVE | CSF_TRUE))); + else if (ea.cmdidx == CMD_finally) + skip = FALSE; + else if (ea.cmdidx != CMD_endif + && ea.cmdidx != CMD_endfor + && ea.cmdidx != CMD_endtry + && ea.cmdidx != CMD_endwhile) + skip = ea.skip; + + if (!skip) + { + if (getline_equal(fgetline, cookie, get_func_line)) + func_line_exec(getline_cookie(fgetline, cookie)); + else if (getline_equal(fgetline, cookie, getsourceline)) + script_line_exec(); + } + } +# endif + + /* May go to debug mode. If this happens and the ">quit" debug command is + * used, throw an interrupt exception and skip the next command. */ + dbg_check_breakpoint(&ea); + if (!ea.skip && got_int) + { + ea.skip = TRUE; + (void)do_intthrow(cstack); + } +#endif + /* * 4. parse a range specifier of the form: addr [,addr] [;addr] .. * @@ -2695,25 +2503,17 @@ do_one_cmd( /* The :try command saves the emsg_silent flag, reset it here when * ":silent! try" was used, it should only apply to :try itself. */ - if (ea.cmdidx == CMD_try && did_esilent > 0) + if (ea.cmdidx == CMD_try && ea.did_esilent > 0) { - emsg_silent -= did_esilent; + emsg_silent -= ea.did_esilent; if (emsg_silent < 0) emsg_silent = 0; - did_esilent = 0; + ea.did_esilent = 0; } /* * 7. Execute the command. - * - * The "ea" structure holds the arguments that can be used. */ - ea.cmdlinep = cmdlinep; - ea.getline = fgetline; - ea.cookie = cookie; -#ifdef FEAT_EVAL - ea.cstack = cstack; -#endif #ifdef FEAT_USR_CMDS if (IS_USER_CMDIDX(ea.cmdidx)) @@ -2782,29 +2582,19 @@ doend: ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL); #endif - if (verbose_save >= 0) - p_verbose = verbose_save; - - if (cmdmod.save_ei != NULL) - { - /* Restore 'eventignore' to the value before ":noautocmd". */ - set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei, - OPT_FREE, SID_NONE); - free_string_option(cmdmod.save_ei); - } - - if (cmdmod.filter_regmatch.regprog != NULL) - vim_regfree(cmdmod.filter_regmatch.regprog); + if (ea.verbose_save >= 0) + p_verbose = ea.verbose_save; + free_cmdmod(); cmdmod = save_cmdmod; - if (save_msg_silent != -1) + if (ea.save_msg_silent != -1) { /* messages could be enabled for a serious error, need to check if the * counters don't become negative */ - if (!did_emsg || msg_silent > save_msg_silent) - msg_silent = save_msg_silent; - emsg_silent -= did_esilent; + if (!did_emsg || msg_silent > ea.save_msg_silent) + msg_silent = ea.save_msg_silent; + emsg_silent -= ea.did_esilent; if (emsg_silent < 0) emsg_silent = 0; /* Restore msg_scroll, it's set by file I/O commands, even when no @@ -2818,7 +2608,7 @@ doend: } #ifdef HAVE_SANDBOX - if (did_sandbox) + if (ea.did_sandbox) --sandbox; #endif @@ -2835,6 +2625,290 @@ doend: #pragma optimize( "", on ) #endif +/* + * Parse and skip over command modifiers: + * - update eap->cmd + * - store flags in "cmdmod". + * - Set ex_pressedreturn for an empty command line. + * - set msg_silent for ":silent" + * - set 'eventignore' to "all" for ":noautocmd" + * - set p_verbose for ":verbose" + * - Increment "sandbox" for ":sandbox" + * When "skip_only" is TRUE the global variables are not changed, except for + * "cmdmod". + * Return FAIL when the command is not to be executed. + * May set "errormsg" to an error message. + */ + int +parse_command_modifiers(exarg_T *eap, char_u **errormsg, int skip_only) +{ + char_u *p; + + vim_memset(&cmdmod, 0, sizeof(cmdmod)); + eap->verbose_save = -1; + eap->save_msg_silent = -1; + + // Repeat until no more command modifiers are found. + for (;;) + { + while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':') + ++eap->cmd; + + /* in ex mode, an empty line works like :+ */ + if (*eap->cmd == NUL && exmode_active + && (getline_equal(eap->getline, eap->cookie, getexmodeline) + || getline_equal(eap->getline, eap->cookie, getexline)) + && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) + { + eap->cmd = (char_u *)"+"; + if (!skip_only) + ex_pressedreturn = TRUE; + } + + /* ignore comment and empty lines */ + if (*eap->cmd == '"') + return FAIL; + if (*eap->cmd == NUL) + { + if (!skip_only) + ex_pressedreturn = TRUE; + return FAIL; + } + + p = skip_range(eap->cmd, NULL); + switch (*p) + { + /* When adding an entry, also modify cmd_exists(). */ + case 'a': if (!checkforcmd(&eap->cmd, "aboveleft", 3)) + break; + cmdmod.split |= WSP_ABOVE; + continue; + + case 'b': if (checkforcmd(&eap->cmd, "belowright", 3)) + { + cmdmod.split |= WSP_BELOW; + continue; + } + if (checkforcmd(&eap->cmd, "browse", 3)) + { +#ifdef FEAT_BROWSE_CMD + cmdmod.browse = TRUE; +#endif + continue; + } + if (!checkforcmd(&eap->cmd, "botright", 2)) + break; + cmdmod.split |= WSP_BOT; + continue; + + case 'c': if (!checkforcmd(&eap->cmd, "confirm", 4)) + break; +#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) + cmdmod.confirm = TRUE; +#endif + continue; + + case 'k': if (checkforcmd(&eap->cmd, "keepmarks", 3)) + { + cmdmod.keepmarks = TRUE; + continue; + } + if (checkforcmd(&eap->cmd, "keepalt", 5)) + { + cmdmod.keepalt = TRUE; + continue; + } + if (checkforcmd(&eap->cmd, "keeppatterns", 5)) + { + cmdmod.keeppatterns = TRUE; + continue; + } + if (!checkforcmd(&eap->cmd, "keepjumps", 5)) + break; + cmdmod.keepjumps = TRUE; + continue; + + case 'f': /* only accept ":filter {pat} cmd" */ + { + char_u *reg_pat; + + if (!checkforcmd(&p, "filter", 4) + || *p == NUL || ends_excmd(*p)) + break; + if (*p == '!') + { + cmdmod.filter_force = TRUE; + p = skipwhite(p + 1); + if (*p == NUL || ends_excmd(*p)) + break; + } + if (skip_only) + p = skip_vimgrep_pat(p, NULL, NULL); + else + // NOTE: This puts a NUL after the pattern. + p = skip_vimgrep_pat(p, ®_pat, NULL); + if (p == NULL || *p == NUL) + break; + if (!skip_only) + { + cmdmod.filter_regmatch.regprog = + vim_regcomp(reg_pat, RE_MAGIC); + if (cmdmod.filter_regmatch.regprog == NULL) + break; + } + eap->cmd = p; + continue; + } + + /* ":hide" and ":hide | cmd" are not modifiers */ + case 'h': if (p != eap->cmd || !checkforcmd(&p, "hide", 3) + || *p == NUL || ends_excmd(*p)) + break; + eap->cmd = p; + cmdmod.hide = TRUE; + continue; + + case 'l': if (checkforcmd(&eap->cmd, "lockmarks", 3)) + { + cmdmod.lockmarks = TRUE; + continue; + } + + if (!checkforcmd(&eap->cmd, "leftabove", 5)) + break; + cmdmod.split |= WSP_ABOVE; + continue; + + case 'n': if (checkforcmd(&eap->cmd, "noautocmd", 3)) + { + if (cmdmod.save_ei == NULL && !skip_only) + { + /* Set 'eventignore' to "all". Restore the + * existing option value later. */ + cmdmod.save_ei = vim_strsave(p_ei); + set_string_option_direct((char_u *)"ei", -1, + (char_u *)"all", OPT_FREE, SID_NONE); + } + continue; + } + if (!checkforcmd(&eap->cmd, "noswapfile", 3)) + break; + cmdmod.noswapfile = TRUE; + continue; + + case 'r': if (!checkforcmd(&eap->cmd, "rightbelow", 6)) + break; + cmdmod.split |= WSP_BELOW; + continue; + + case 's': if (checkforcmd(&eap->cmd, "sandbox", 3)) + { +#ifdef HAVE_SANDBOX + if (!skip_only) + { + if (!eap->did_sandbox) + ++sandbox; + eap->did_sandbox = TRUE; + } +#endif + continue; + } + if (!checkforcmd(&eap->cmd, "silent", 3)) + break; + if (!skip_only) + { + if (eap->save_msg_silent == -1) + eap->save_msg_silent = msg_silent; + ++msg_silent; + } + if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1])) + { + /* ":silent!", but not "silent !cmd" */ + eap->cmd = skipwhite(eap->cmd + 1); + if (!skip_only) + { + ++emsg_silent; + ++eap->did_esilent; + } + } + continue; + + case 't': if (checkforcmd(&p, "tab", 3)) + { + long tabnr = get_address(eap, &eap->cmd, ADDR_TABS, + eap->skip, FALSE, 1); + if (tabnr == MAXLNUM) + cmdmod.tab = tabpage_index(curtab) + 1; + else + { + if (tabnr < 0 || tabnr > LAST_TAB_NR) + { + *errormsg = (char_u *)_(e_invrange); + return FAIL; + } + cmdmod.tab = tabnr + 1; + } + eap->cmd = p; + continue; + } + if (!checkforcmd(&eap->cmd, "topleft", 2)) + break; + cmdmod.split |= WSP_TOP; + continue; + + case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3)) + break; + if (!skip_only) + { + if (eap->save_msg_silent == -1) + eap->save_msg_silent = msg_silent; + msg_silent = 0; + } + continue; + + case 'v': if (checkforcmd(&eap->cmd, "vertical", 4)) + { + cmdmod.split |= WSP_VERT; + continue; + } + if (!checkforcmd(&p, "verbose", 4)) + break; + if (!skip_only) + { + if (eap->verbose_save < 0) + eap->verbose_save = p_verbose; + if (vim_isdigit(*eap->cmd)) + p_verbose = atoi((char *)eap->cmd); + else + p_verbose = 1; + } + eap->cmd = p; + continue; + } + break; + } + + return OK; +} + +/* + * Free contents of "cmdmod". + */ + static void +free_cmdmod(void) +{ + if (cmdmod.save_ei != NULL) + { + /* Restore 'eventignore' to the value before ":noautocmd". */ + set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei, + OPT_FREE, SID_NONE); + free_string_option(cmdmod.save_ei); + } + + if (cmdmod.filter_regmatch.regprog != NULL) + vim_regfree(cmdmod.filter_regmatch.regprog); +} + /* * Parse the address range, if any, in "eap". * Return FAIL and set "errormsg" or return OK. @@ -5714,22 +5788,16 @@ check_more( { char_u buff[DIALOG_MSG_SIZE]; - if (n == 1) - vim_strncpy(buff, - (char_u *)_("1 more file to edit. Quit anyway?"), - DIALOG_MSG_SIZE - 1); - else - vim_snprintf((char *)buff, DIALOG_MSG_SIZE, - _("%d more files to edit. Quit anyway?"), n); + vim_snprintf((char *)buff, DIALOG_MSG_SIZE, + NGETTEXT("%d more file to edit. Quit anyway?", + "%d more files to edit. Quit anyway?", n), n); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) return OK; return FAIL; } #endif - if (n == 1) - EMSG(_("E173: 1 more file to edit")); - else - EMSGN(_("E173: %ld more files to edit"), n); + EMSGN(NGETTEXT("E173: %ld more file to edit", + "E173: %ld more files to edit", n), n); quitmore = 2; /* next try to quit is allowed */ } return FAIL; @@ -12512,6 +12580,20 @@ ex_folddo(exarg_T *eap) } #endif +#ifdef FEAT_QUICKFIX +/* + * Returns TRUE if the supplied Ex cmdidx is for a location list command + * instead of a quickfix command. + */ + int +is_loclist_cmd(int cmdidx) +{ + if (cmdidx < 0 || cmdidx > CMD_SIZE) + return FALSE; + return cmdnames[cmdidx].cmd_name[0] == 'l'; +} +#endif + # if defined(FEAT_TIMERS) || defined(PROTO) int get_pressedreturn(void) diff --git a/src/ex_getln.c b/src/ex_getln.c index c3804a6ac9..5f1fbe7587 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -13,6 +13,10 @@ #include "vim.h" +#ifndef MAX +# define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + /* * Variables shared between getcmdline(), redrawcmdline() and others. * These need to be saved when using CTRL-R |, that's why they are in a @@ -231,6 +235,7 @@ typedef struct { pos_T match_end; int did_incsearch; int incsearch_postponed; + int magic_save; } incsearch_state_T; static void @@ -239,6 +244,7 @@ init_incsearch_state(incsearch_state_T *is_state) is_state->match_start = curwin->w_cursor; is_state->did_incsearch = FALSE; is_state->incsearch_postponed = FALSE; + is_state->magic_save = p_magic; CLEAR_POS(&is_state->match_end); is_state->save_cursor = curwin->w_cursor; // may be restored later is_state->search_start = curwin->w_cursor; @@ -270,92 +276,125 @@ set_search_match(pos_T *t) do_incsearch_highlighting(int firstc, incsearch_state_T *is_state, int *skiplen, int *patlen) { + char_u *cmd; + cmdmod_T save_cmdmod = cmdmod; + char_u *p; + int delim_optional = FALSE; + int delim; + char_u *end; + char_u *dummy; + exarg_T ea; + pos_T save_cursor; + *skiplen = 0; *patlen = ccline.cmdlen; - if (p_is && !cmd_silent) + if (!p_is || cmd_silent) + return FALSE; + + // by default search all lines + search_first_line = 0; + search_last_line = MAXLNUM; + + if (firstc == '/' || firstc == '?') + return TRUE; + if (firstc != ':') + return FALSE; + + vim_memset(&ea, 0, sizeof(ea)); + ea.line1 = 1; + ea.line2 = 1; + ea.cmd = ccline.cmdbuff; + ea.addr_type = ADDR_LINES; + + parse_command_modifiers(&ea, &dummy, TRUE); + cmdmod = save_cmdmod; + + cmd = skip_range(ea.cmd, NULL); + if (vim_strchr((char_u *)"sgvl", *cmd) == NULL) + return FALSE; + + // Skip over "substitute" to find the pattern separator. + for (p = cmd; ASCII_ISALPHA(*p); ++p) + ; + if (*skipwhite(p) == NUL) + return FALSE; + + if (STRNCMP(cmd, "substitute", p - cmd) == 0 + || STRNCMP(cmd, "smagic", p - cmd) == 0 + || STRNCMP(cmd, "snomagic", MAX(p - cmd, 3)) == 0 + || STRNCMP(cmd, "vglobal", p - cmd) == 0) { - // by default search all lines - search_first_line = 0; - search_last_line = MAXLNUM; - - if (firstc == '/' || firstc == '?') - return TRUE; - if (firstc == ':') + if (*cmd == 's' && cmd[1] == 'm') + p_magic = TRUE; + else if (*cmd == 's' && cmd[1] == 'n') + p_magic = FALSE; + } + else if (STRNCMP(cmd, "sort", MAX(p - cmd, 3)) == 0) + { + // skip over flags + while (ASCII_ISALPHA(*(p = skipwhite(p)))) + ++p; + if (*p == NUL) + return FALSE; + } + else if (STRNCMP(cmd, "vimgrep", MAX(p - cmd, 3)) == 0 + || STRNCMP(cmd, "vimgrepadd", MAX(p - cmd, 8)) == 0 + || STRNCMP(cmd, "lvimgrep", MAX(p - cmd, 2)) == 0 + || STRNCMP(cmd, "lvimgrepadd", MAX(p - cmd, 9)) == 0 + || STRNCMP(cmd, "global", p - cmd) == 0) + { + // skip over "!" + if (*p == '!') { - char_u *cmd = skip_range(ccline.cmdbuff, NULL); - char_u *p; - int delim; - char_u *end; + p++; + if (*skipwhite(p) == NUL) + return FALSE; + } + if (*cmd != 'g') + delim_optional = TRUE; + } + else + return FALSE; - if (*cmd == 's' || *cmd == 'g' || *cmd == 'v') - { - // Skip over "substitute" to find the pattern separator. - for (p = cmd; ASCII_ISALPHA(*p); ++p) - ; - if (*skipwhite(p) != NUL - && (STRNCMP(cmd, "substitute", p - cmd) == 0 - || STRNCMP(cmd, "global", p - cmd) == 0 - || STRNCMP(cmd, "vglobal", p - cmd) == 0)) - { - // Check for "global!/". - if (*cmd == 'g' && *p == '!') - { - p++; - if (*skipwhite(p) == NUL) - return FALSE; - } - p = skipwhite(p); - delim = *p++; - end = skip_regexp(p, delim, p_magic, NULL); - if (end > p || *end == delim) - { - char_u *dummy; - exarg_T ea; - pos_T save_cursor = curwin->w_cursor; + p = skipwhite(p); + delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++; + end = skip_regexp(p, delim, p_magic, NULL); - // found a non-empty pattern - *skiplen = (int)(p - ccline.cmdbuff); - *patlen = (int)(end - p); + if (end == p && *end != delim) + return FALSE; + // found a non-empty pattern or // - // parse the address range - vim_memset(&ea, 0, sizeof(ea)); - ea.line1 = 1; - ea.line2 = 1; - ea.cmd = ccline.cmdbuff; - ea.addr_type = ADDR_LINES; - curwin->w_cursor = is_state->search_start; - parse_cmd_address(&ea, &dummy); - if (ea.addr_count > 0) - { - // Allow for reverse match. - if (ea.line2 < ea.line1) - { - search_first_line = ea.line2; - search_last_line = ea.line1; - } - else - { - search_first_line = ea.line1; - search_last_line = ea.line2; - } - } - else if (*cmd == 's') - { - // :s defaults to the current line - search_first_line = curwin->w_cursor.lnum; - search_last_line = curwin->w_cursor.lnum; - } + *skiplen = (int)(p - ccline.cmdbuff); + *patlen = (int)(end - p); - curwin->w_cursor = save_cursor; - return TRUE; - } - } - } + // parse the address range + save_cursor = curwin->w_cursor; + curwin->w_cursor = is_state->search_start; + parse_cmd_address(&ea, &dummy); + if (ea.addr_count > 0) + { + // Allow for reverse match. + if (ea.line2 < ea.line1) + { + search_first_line = ea.line2; + search_last_line = ea.line1; + } + else + { + search_first_line = ea.line1; + search_last_line = ea.line2; } } + else if (cmd[0] == 's' && cmd[1] != 'o') + { + // :s defaults to the current line + search_first_line = curwin->w_cursor.lnum; + search_last_line = curwin->w_cursor.lnum; + } - return FALSE; + curwin->w_cursor = save_cursor; + return TRUE; } static void @@ -386,6 +425,7 @@ finish_incsearch_highlighting( update_screen(SOME_VALID); else redraw_all_later(SOME_VALID); + p_magic = is_state->magic_save; } } @@ -474,8 +514,11 @@ may_do_incsearch_highlighting( if (curwin->w_cursor.lnum < search_first_line || curwin->w_cursor.lnum > search_last_line) + { // match outside of address range i = 0; + curwin->w_cursor = is_state->search_start; + } // if interrupted while searching, behave like it failed if (got_int) @@ -571,7 +614,7 @@ may_adjust_incsearch_highlighting( { pat = last_search_pattern(); skiplen = 0; - patlen = STRLEN(pat); + patlen = (int)STRLEN(pat); } else pat = ccline.cmdbuff + skiplen; diff --git a/src/feature.h b/src/feature.h index affdeda71d..c839c86c50 100644 --- a/src/feature.h +++ b/src/feature.h @@ -355,6 +355,10 @@ # endif #endif +#ifdef FEAT_EVAL +# define HAVE_SANDBOX +#endif + /* * +profile Profiling for functions and scripts. */ diff --git a/src/fileio.c b/src/fileio.c index 82b5e469df..3401865f52 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5353,16 +5353,11 @@ msg_add_lines( "%ldL, %lldC", lnum, (long long)nchars); else { - if (lnum == 1) - STRCPY(p, _("1 line, ")); - else - sprintf((char *)p, _("%ld lines, "), lnum); + sprintf((char *)p, NGETTEXT("%ld line, ", "%ld lines, ", lnum), lnum); p += STRLEN(p); - if (nchars == 1) - STRCPY(p, _("1 character")); - else - vim_snprintf((char *)p, IOSIZE - (p - IObuff), - _("%lld characters"), (long long)nchars); + vim_snprintf((char *)p, IOSIZE - (p - IObuff), + NGETTEXT("%lld character", "%lld characters", nchars), + (long long)nchars); } } diff --git a/src/globals.h b/src/globals.h index 2f53f0d61e..268b0a8ef6 100644 --- a/src/globals.h +++ b/src/globals.h @@ -518,7 +518,7 @@ EXTERN char *foreground_argument INIT(= NULL); * * volatile because it is used in signal handler sig_sysmouse(). */ -EXTERN volatile int hold_gui_events INIT(= 0); +EXTERN volatile sig_atomic_t hold_gui_events INIT(= 0); /* * When resizing the shell is postponed, remember the new size, and call @@ -655,7 +655,7 @@ EXTERN int entered_free_all_mem INIT(= FALSE); /* TRUE when in or after free_all_mem() */ #endif /* volatile because it is used in signal handler deathtrap(). */ -EXTERN volatile int full_screen INIT(= FALSE); +EXTERN volatile sig_atomic_t full_screen INIT(= FALSE); /* TRUE when doing full-screen output * otherwise only writing some messages */ @@ -678,8 +678,7 @@ EXTERN int allbuf_lock INIT(= 0); * changed, no buffer can be deleted and * current directory can't be changed. * Used for SwapExists et al. */ -#ifdef FEAT_EVAL -# define HAVE_SANDBOX +#ifdef HAVE_SANDBOX EXTERN int sandbox INIT(= 0); /* Non-zero when evaluating an expression in a * "sandbox". Several things are not allowed @@ -801,11 +800,11 @@ EXTERN JMP_BUF x_jump_env; EXTERN JMP_BUF lc_jump_env; /* argument to SETJMP() */ # ifdef SIGHASARG /* volatile because it is used in signal handlers. */ -EXTERN volatile int lc_signal; /* caught signal number, 0 when no was signal +EXTERN volatile sig_atomic_t lc_signal; /* caught signal number, 0 when no was signal caught; used for mch_libcall() */ # endif /* volatile because it is used in signal handler deathtrap(). */ -EXTERN volatile int lc_active INIT(= FALSE); /* TRUE when lc_jump_env is valid. */ +EXTERN volatile sig_atomic_t lc_active INIT(= FALSE); /* TRUE when lc_jump_env is valid. */ #endif #if defined(FEAT_MBYTE) || defined(FEAT_POSTSCRIPT) @@ -1040,7 +1039,7 @@ EXTERN FILE *scriptout INIT(= NULL); /* stream to write script to */ EXTERN int read_cmd_fd INIT(= 0); /* fd to read commands from */ /* volatile because it is used in signal handler catch_sigint(). */ -EXTERN volatile int got_int INIT(= FALSE); /* set to TRUE when interrupt +EXTERN volatile sig_atomic_t got_int INIT(= FALSE); /* set to TRUE when interrupt signal occurred */ #ifdef USE_TERM_CONSOLE EXTERN int term_console INIT(= FALSE); /* set to TRUE when console used */ diff --git a/src/gui_beval.c b/src/gui_beval.c index 2cdff65e2d..0513eab9d8 100644 --- a/src/gui_beval.c +++ b/src/gui_beval.c @@ -944,6 +944,8 @@ drawBalloon(BalloonEval *beval) GtkRequisition requisition; int screen_w; int screen_h; + int screen_x; + int screen_y; int x; int y; int x_offset = EVAL_OFFSET_X; @@ -956,8 +958,8 @@ drawBalloon(BalloonEval *beval) screen = gtk_widget_get_screen(beval->target); gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen); # endif - gui_gtk_get_screen_size_of_win(beval->balloonShell, - &screen_w, &screen_h); + gui_gtk_get_screen_geom_of_win(beval->balloonShell, + &screen_x, &screen_y, &screen_w, &screen_h); # if !GTK_CHECK_VERSION(3,0,0) gtk_widget_ensure_style(beval->balloonShell); gtk_widget_ensure_style(beval->balloonLabel); @@ -998,14 +1000,16 @@ drawBalloon(BalloonEval *beval) y += beval->y; /* Get out of the way of the mouse pointer */ - if (x + x_offset + requisition.width > screen_w) + if (x + x_offset + requisition.width > screen_x + screen_w) y_offset += 15; - if (y + y_offset + requisition.height > screen_h) + if (y + y_offset + requisition.height > screen_y + screen_h) y_offset = -requisition.height - EVAL_OFFSET_Y; /* Sanitize values */ - x = CLAMP(x + x_offset, 0, MAX(0, screen_w - requisition.width)); - y = CLAMP(y + y_offset, 0, MAX(0, screen_h - requisition.height)); + x = CLAMP(x + x_offset, 0, + MAX(0, screen_x + screen_w - requisition.width)); + y = CLAMP(y + y_offset, 0, + MAX(0, screen_y + screen_h - requisition.height)); /* Show the balloon */ # if GTK_CHECK_VERSION(3,0,0) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 7541d79072..196c9dc7be 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -5008,27 +5008,35 @@ gui_mch_set_shellsize(int width, int height, } void -gui_gtk_get_screen_size_of_win(GtkWidget *wid, int *width, int *height) +gui_gtk_get_screen_geom_of_win( + GtkWidget *wid, + int *screen_x, + int *screen_y, + int *width, + int *height) { + GdkRectangle geometry; + GdkWindow *win = gtk_widget_get_window(wid); #if GTK_CHECK_VERSION(3,22,0) GdkDisplay *dpy = gtk_widget_get_display(wid); - GdkWindow *win = gtk_widget_get_window(wid); GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); - GdkRectangle geometry; gdk_monitor_get_geometry(monitor, &geometry); - *width = geometry.width; - *height = geometry.height; #else GdkScreen* screen; + int monitor; if (wid != NULL && gtk_widget_has_screen(wid)) screen = gtk_widget_get_screen(wid); else screen = gdk_screen_get_default(); - *width = gdk_screen_get_width(screen); - *height = gdk_screen_get_height(screen); + monitor = gdk_screen_get_monitor_at_window(screen, win); + gdk_screen_get_monitor_geometry(screen, monitor, &geometry); #endif + *screen_x = geometry.x; + *screen_y = geometry.y; + *width = geometry.width; + *height = geometry.height; } /* @@ -5039,7 +5047,9 @@ gui_gtk_get_screen_size_of_win(GtkWidget *wid, int *width, int *height) void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h) { - gui_gtk_get_screen_size_of_win(gui.mainwin, screen_w, screen_h); + int x, y; + + gui_gtk_get_screen_geom_of_win(gui.mainwin, &x, &y, screen_w, screen_h); /* Subtract 'guiheadroom' from the height to allow some room for the * window manager (task list and window title bar). */ diff --git a/src/if_lua.c b/src/if_lua.c index 7602c80de4..6e33734643 100644 --- a/src/if_lua.c +++ b/src/if_lua.c @@ -164,7 +164,11 @@ static luaV_Funcref *luaV_pushfuncref(lua_State *L, typval_T *tv); #define lua_rawget dll_lua_rawget #define lua_rawgeti dll_lua_rawgeti #define lua_createtable dll_lua_createtable -#define lua_newuserdata dll_lua_newuserdata +#if LUA_VERSION_NUM >= 504 + #define lua_newuserdatauv dll_lua_newuserdatauv +#else + #define lua_newuserdata dll_lua_newuserdata +#endif #define lua_getmetatable dll_lua_getmetatable #define lua_setfield dll_lua_setfield #define lua_rawset dll_lua_rawset @@ -261,7 +265,11 @@ int (*dll_lua_rawget) (lua_State *L, int idx); int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n); #endif void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); +#if LUA_VERSION_NUM >= 504 +void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); +#else void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); +#endif int (*dll_lua_getmetatable) (lua_State *L, int objindex); void (*dll_lua_setfield) (lua_State *L, int idx, const char *k); void (*dll_lua_rawset) (lua_State *L, int idx); @@ -362,7 +370,11 @@ static const luaV_Reg luaV_dll[] = { {"lua_rawget", (luaV_function) &dll_lua_rawget}, {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, {"lua_createtable", (luaV_function) &dll_lua_createtable}, +#if LUA_VERSION_NUM >= 504 + {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv}, +#else {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, +#endif {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, {"lua_setfield", (luaV_function) &dll_lua_setfield}, {"lua_rawset", (luaV_function) &dll_lua_rawset}, diff --git a/src/mbyte.c b/src/mbyte.c index 231f835e39..b97e746a61 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -4975,24 +4975,26 @@ im_add_to_input(char_u *str, int len) static void im_preedit_window_set_position(void) { - int x, y, w, h, sw, sh; + int x, y, width, height; + int screen_x, screen_y, screen_width, screen_height; if (preedit_window == NULL) return; - gui_gtk_get_screen_size_of_win(preedit_window, &sw, &sh); + gui_gtk_get_screen_geom_of_win(gui.drawarea, + &screen_x, &screen_y, &screen_width, &screen_height); #if GTK_CHECK_VERSION(3,0,0) gdk_window_get_origin(gtk_widget_get_window(gui.drawarea), &x, &y); #else gdk_window_get_origin(gui.drawarea->window, &x, &y); #endif - gtk_window_get_size(GTK_WINDOW(preedit_window), &w, &h); + gtk_window_get_size(GTK_WINDOW(preedit_window), &width, &height); x = x + FILL_X(gui.col); y = y + FILL_Y(gui.row); - if (x + w > sw) - x = sw - w; - if (y + h > sh) - y = sh - h; + if (x + width > screen_x + screen_width) + x = screen_x + screen_width - width; + if (y + height > screen_y + screen_height) + y = screen_y + screen_height - height; gtk_window_move(GTK_WINDOW(preedit_window), x, y); } diff --git a/src/memline.c b/src/memline.c index a2f0b4f626..3d82af0813 100644 --- a/src/memline.c +++ b/src/memline.c @@ -828,10 +828,13 @@ ml_open_file(buf_T *buf) */ void check_need_swap( - int newfile) /* reading file into new buffer */ + int newfile) // reading file into new buffer { + int old_msg_silent = msg_silent; // might be reset by an E325 message + if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile)) ml_open_file(curbuf); + msg_silent = old_msg_silent; } /* @@ -2038,6 +2041,53 @@ make_percent_swname(char_u *dir, char_u *name) static int process_still_running; #endif +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Return information found in swapfile "fname" in dictionary "d". + * This is used by the swapinfo() function. + */ + void +get_b0_dict(char_u *fname, dict_T *d) +{ + int fd; + struct block0 b0; + + if ((fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0) + { + if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) + { + if (ml_check_b0_id(&b0) == FAIL) + dict_add_string(d, "error", + vim_strsave((char_u *)"Not a swap file")); + else if (b0_magic_wrong(&b0)) + dict_add_string(d, "error", + vim_strsave((char_u *)"Magic number mismatch")); + else + { + /* we have swap information */ + dict_add_string(d, "version", vim_strsave(b0.b0_version)); + dict_add_string(d, "user", vim_strsave(b0.b0_uname)); + dict_add_string(d, "host", vim_strsave(b0.b0_hname)); + dict_add_string(d, "fname", vim_strsave(b0.b0_fname)); + + dict_add_number(d, "pid", char_to_long(b0.b0_pid)); + dict_add_number(d, "mtime", char_to_long(b0.b0_mtime)); + dict_add_number(d, "dirty", b0.b0_dirty ? 1 : 0); +# ifdef CHECK_INODE + dict_add_number(d, "inode", char_to_long(b0.b0_ino)); +# endif + } + } + else + dict_add_string(d, "error", + vim_strsave((char_u *)"Cannot read file")); + close(fd); + } + else + dict_add_string(d, "error", vim_strsave((char_u *)"Cannot open file")); +} +#endif + /* * Give information about an existing swap file. * Returns timestamp (0 when unknown). @@ -5267,7 +5317,7 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) /* Don't count the last line break if 'noeol' and ('bin' or * 'nofixeol'). */ if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol - && buf->b_ml.ml_line_count == lnum) + && lnum > buf->b_ml.ml_line_count) size -= ffdos + 1; } diff --git a/src/misc1.c b/src/misc1.c index f5dd978d29..a6dda789ff 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -3809,24 +3809,12 @@ msgmore(long n) if (pn > p_report) { - if (pn == 1) - { - if (n > 0) - vim_strncpy(msg_buf, (char_u *)_("1 more line"), - MSG_BUF_LEN - 1); - else - vim_strncpy(msg_buf, (char_u *)_("1 line less"), - MSG_BUF_LEN - 1); - } + if (n > 0) + vim_snprintf((char *)msg_buf, MSG_BUF_LEN, + NGETTEXT("%ld more line", "%ld more lines", pn), pn); else - { - if (n > 0) - vim_snprintf((char *)msg_buf, MSG_BUF_LEN, - _("%ld more lines"), pn); - else - vim_snprintf((char *)msg_buf, MSG_BUF_LEN, - _("%ld fewer lines"), pn); - } + vim_snprintf((char *)msg_buf, MSG_BUF_LEN, + NGETTEXT("%ld line less", "%ld fewer lines", pn), pn); if (got_int) vim_strcat(msg_buf, (char_u *)_(" (Interrupted)"), MSG_BUF_LEN); if (msg(msg_buf)) diff --git a/src/ops.c b/src/ops.c index 50ebf44495..3384556f90 100644 --- a/src/ops.c +++ b/src/ops.c @@ -244,7 +244,6 @@ op_shift(oparg_T *oap, int curs_top, int amount) { long i; int first_char; - char_u *s; int block_col = 0; if (u_save((linenr_T)(oap->start.lnum - 1), @@ -297,26 +296,21 @@ op_shift(oparg_T *oap, int curs_top, int amount) if (oap->line_count > p_report) { + char *op; + char *msg_line_single; + char *msg_line_plural; + if (oap->op_type == OP_RSHIFT) - s = (char_u *)">"; + op = ">"; else - s = (char_u *)"<"; - if (oap->line_count == 1) - { - if (amount == 1) - sprintf((char *)IObuff, _("1 line %sed 1 time"), s); - else - sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount); - } - else - { - if (amount == 1) - sprintf((char *)IObuff, _("%ld lines %sed 1 time"), - oap->line_count, s); - else - sprintf((char *)IObuff, _("%ld lines %sed %d times"), - oap->line_count, s, amount); - } + op = "<"; + msg_line_single = NGETTEXT("%ld line %sed %d time", + "%ld line %sed %d times", amount); + msg_line_plural = NGETTEXT("%ld lines %sed %d time", + "%ld lines %sed %d times", amount); + vim_snprintf((char *)IObuff, IOSIZE, + NGETTEXT(msg_line_single, msg_line_plural, oap->line_count), + oap->line_count, op, amount); msg(IObuff); } @@ -789,10 +783,8 @@ op_reindent(oparg_T *oap, int (*how)(void)) if (oap->line_count > p_report) { i = oap->line_count - (i + 1); - if (i == 1) - MSG(_("1 line indented ")); - else - smsg((char_u *)_("%ld lines indented "), i); + smsg((char_u *)NGETTEXT("%ld line indented ", + "%ld lines indented ", i), i); } /* set '[ and '] marks */ curbuf->b_op_start = oap->start; @@ -2529,12 +2521,8 @@ op_tilde(oparg_T *oap) curbuf->b_op_end = oap->end; if (oap->line_count > p_report) - { - if (oap->line_count == 1) - MSG(_("1 line changed")); - else - smsg((char_u *)_("%ld lines changed"), oap->line_count); - } + smsg((char_u *)NGETTEXT("%ld line changed", "%ld lines changed", + oap->line_count), oap->line_count); } /* @@ -3348,19 +3336,18 @@ op_yank(oparg_T *oap, int deleting, int mess) /* redisplay now, so message is not deleted */ update_topline_redraw(); - if (yanklines == 1) + if (oap->block_mode) { - if (oap->block_mode) - smsg((char_u *)_("block of 1 line yanked%s"), namebuf); - else - smsg((char_u *)_("1 line yanked%s"), namebuf); + smsg((char_u *)NGETTEXT("block of %ld line yanked%s", + "block of %ld lines yanked%s", yanklines), + yanklines, namebuf); } - else if (oap->block_mode) - smsg((char_u *)_("block of %ld lines yanked%s"), - yanklines, namebuf); else - smsg((char_u *)_("%ld lines yanked%s"), yanklines, - namebuf); + { + smsg((char_u *)NGETTEXT("%ld line yanked%s", + "%ld lines yanked%s", yanklines), + yanklines, namebuf); + } } } @@ -5653,12 +5640,8 @@ op_addsub( curbuf->b_op_start = startpos; if (change_cnt > p_report) - { - if (change_cnt == 1) - MSG(_("1 line changed")); - else - smsg((char_u *)_("%ld lines changed"), change_cnt); - } + smsg((char_u *)NGETTEXT("%ld line changed", "%ld lines changed", + change_cnt), change_cnt); } } diff --git a/src/os_unix.c b/src/os_unix.c index edacd93013..4f4c2926e4 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -161,6 +161,7 @@ static int get_x11_title(int); static int get_x11_icon(int); static char_u *oldtitle = NULL; +static volatile sig_atomic_t oldtitle_outdated = FALSE; static int did_set_title = FALSE; static char_u *oldicon = NULL; static int did_set_icon = FALSE; @@ -204,7 +205,7 @@ static RETSIGTYPE catch_sigpwr SIGPROTOARG; # define SET_SIG_ALARM static RETSIGTYPE sig_alarm SIGPROTOARG; /* volatile because it is used in signal handler sig_alarm(). */ -static volatile int sig_alarm_called; +static volatile sig_atomic_t sig_alarm_called; #endif static RETSIGTYPE deathtrap SIGPROTOARG; @@ -230,13 +231,13 @@ static int save_patterns(int num_pat, char_u **pat, int *num_file, char_u ***fil #endif /* volatile because it is used in signal handler sig_winch(). */ -static volatile int do_resize = FALSE; +static volatile sig_atomic_t do_resize = FALSE; static char_u *extra_shell_arg = NULL; static int show_shell_mess = TRUE; /* volatile because it is used in signal handler deathtrap(). */ -static volatile int deadly_signal = 0; /* The signal we caught */ +static volatile sig_atomic_t deadly_signal = 0; /* The signal we caught */ /* volatile because it is used in signal handler deathtrap(). */ -static volatile int in_mch_delay = FALSE; /* sleeping in mch_delay() */ +static volatile sig_atomic_t in_mch_delay = FALSE; /* sleeping in mch_delay() */ #if defined(FEAT_JOB_CHANNEL) && !defined(USE_SYSTEM) static int dont_check_job_ended = 0; @@ -1227,12 +1228,17 @@ deathtrap SIGDEFARG(sigarg) SIGRETURN; } +/* + * Invoked after receiving SIGCONT. We don't know what happened while + * sleeping, deal with part of that. + */ static void after_sigcont(void) { # ifdef FEAT_TITLE - // Set oldtitle to NULL, so the current title is obtained again. - VIM_CLEAR(oldtitle); + // Don't change "oldtitle" in a signal handler, set a flag to obtain it + // again later. + oldtitle_outdated = TRUE; # endif settmode(TMODE_RAW); need_check_timestamps = TRUE; @@ -1241,21 +1247,21 @@ after_sigcont(void) #if defined(SIGCONT) static RETSIGTYPE sigcont_handler SIGPROTOARG; -static int in_mch_suspend = FALSE; +static volatile sig_atomic_t in_mch_suspend = FALSE; -# if defined(_REENTRANT) && defined(SIGCONT) /* - * On Solaris with multi-threading, suspending might not work immediately. - * Catch the SIGCONT signal, which will be used as an indication whether the - * suspending has been done or not. + * With multi-threading, suspending might not work immediately. Catch the + * SIGCONT signal, which will be used as an indication whether the suspending + * has been done or not. * * On Linux, signal is not always handled immediately either. * See https://bugs.launchpad.net/bugs/291373 + * Probably because the signal is handled in another thread. * * volatile because it is used in signal handler sigcont_handler(). */ -static volatile int sigcont_received; -# endif +static volatile sig_atomic_t sigcont_received; +static RETSIGTYPE sigcont_handler SIGPROTOARG; /* * signal handler for SIGCONT @@ -1265,32 +1271,16 @@ sigcont_handler SIGDEFARG(sigarg) { if (in_mch_suspend) { -# if defined(_REENTRANT) && defined(SIGCONT) sigcont_received = TRUE; -# endif } else { // We didn't suspend ourselves, assume we were stopped by a SIGSTOP // signal (which can't be intercepted) and get a SIGCONT. Need to get - // back to a sane mode and redraw. + // back to a sane mode. We should redraw, but we can't really do that + // in a signal handler, do a redraw later. after_sigcont(); - - update_screen(CLEAR); - if (State & CMDLINE) - redrawcmdline(); - else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE - || State == EXTERNCMD || State == CONFIRM || exmode_active) - repeat_message(); - else if (redrawing()) - setcursor(); -#if defined(FEAT_INS_EXPAND) - if (pum_visible()) - { - redraw_later(NOT_VALID); - ins_compl_show_pum(); - } -#endif + redraw_later(CLEAR); cursor_on_force(); out_flush(); } @@ -1386,27 +1376,26 @@ mch_suspend(void) # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) loose_clipboard(); # endif - -# if defined(_REENTRANT) && defined(SIGCONT) +# if defined(SIGCONT) sigcont_received = FALSE; # endif + kill(0, SIGTSTP); /* send ourselves a STOP signal */ -# if defined(_REENTRANT) && defined(SIGCONT) + +# if defined(SIGCONT) /* * Wait for the SIGCONT signal to be handled. It generally happens - * immediately, but somehow not all the time. Do not call pause() - * because there would be race condition which would hang Vim if - * signal happened in between the test of sigcont_received and the - * call to pause(). If signal is not yet received, call sleep(0) - * to just yield CPU. Signal should then be received. If somehow - * it's still not received, sleep 1, 2, 3 ms. Don't bother waiting - * further if signal is not received after 1+2+3+4 ms (not expected - * to happen). + * immediately, but somehow not all the time, probably because it's handled + * in another thread. Do not call pause() because there would be race + * condition which would hang Vim if signal happened in between the test of + * sigcont_received and the call to pause(). If signal is not yet received, + * sleep 0, 1, 2, 3 ms. Don't bother waiting further if signal is not + * received after 1+2+3 ms (not expected to happen). */ { long wait_time; + for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++) - /* Loop is not entered most of the time */ mch_delay(wait_time, FALSE); } # endif @@ -1511,7 +1500,7 @@ catch_int_signal(void) reset_signals(void) { catch_signals(SIG_DFL, SIG_DFL); -#if defined(_REENTRANT) && defined(SIGCONT) +#if defined(SIGCONT) /* SIGCONT isn't in the list, because its default action is ignore */ signal(SIGCONT, SIG_DFL); #endif @@ -1574,7 +1563,7 @@ block_signals(sigset_t *set) for (i = 0; signal_info[i].sig != -1; i++) sigaddset(&newset, signal_info[i].sig); -# if defined(_REENTRANT) && defined(SIGCONT) +# if defined(SIGCONT) /* SIGCONT isn't in the list, because its default action is ignore */ sigaddset(&newset, SIGCONT); # endif @@ -2282,6 +2271,11 @@ mch_settitle(char_u *title, char_u *icon) */ if ((type || *T_TS != NUL) && title != NULL) { + if (oldtitle_outdated) + { + oldtitle_outdated = FALSE; + VIM_CLEAR(oldtitle); + } if (oldtitle == NULL #ifdef FEAT_GUI && !gui.in_use diff --git a/src/os_win32.c b/src/os_win32.c index 85c8a57d11..dc98d6acd2 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -3108,6 +3108,9 @@ mch_dirname( char_u *buf, int len) { + char_u abuf[_MAX_PATH + 1]; + DWORD lfnlen; + /* * Originally this was: * return (getcwd(buf, len) != NULL ? OK : FAIL); @@ -3121,7 +3124,21 @@ mch_dirname( if (GetCurrentDirectoryW(_MAX_PATH, wbuf) != 0) { - char_u *p = utf16_to_enc(wbuf, NULL); + WCHAR wcbuf[_MAX_PATH + 1]; + char_u *p = NULL; + + if (GetLongPathNameW(wbuf, wcbuf, _MAX_PATH) != 0) + { + p = utf16_to_enc(wcbuf, NULL); + if (STRLEN(p) >= (size_t)len) + { + // long path name is too long, fall back to short one + vim_free(p); + p = NULL; + } + } + if (p == NULL) + p = utf16_to_enc(wbuf, NULL); if (p != NULL) { @@ -3133,7 +3150,16 @@ mch_dirname( return FAIL; } #endif - return (GetCurrentDirectory(len, (LPSTR)buf) != 0 ? OK : FAIL); + if (GetCurrentDirectory(len, (LPSTR)buf) == 0) + return FAIL; + lfnlen = GetLongPathNameA((LPCSTR)buf, (LPSTR)abuf, _MAX_PATH); + if (lfnlen == 0 || lfnlen >= (DWORD)len) + // Failed to get long path name or it's too long: fall back to the + // short path name. + return OK; + + STRCPY(buf, abuf); + return OK; } /* diff --git a/src/os_win32.h b/src/os_win32.h index 5017f532ef..4b1fc39bbf 100644 --- a/src/os_win32.h +++ b/src/os_win32.h @@ -89,6 +89,7 @@ #define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */ +#include #include #include #include diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index 00800e1ef5..04bc0c3abd 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -4,6 +4,7 @@ int do_cmdline_cmd(char_u *cmd); int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags); int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int)); void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie); +int parse_command_modifiers(exarg_T *eap, char_u **errormsg, int skip_only); int parse_cmd_address(exarg_T *eap, char_u **errormsg); int checkforcmd(char_u **pp, char *cmd, int len); int modifier_len(char_u *cmd); @@ -69,6 +70,7 @@ char_u *get_behave_arg(expand_T *xp, int idx); char_u *get_messages_arg(expand_T *xp, int idx); char_u *get_mapclear_arg(expand_T *xp, int idx); void set_no_hlsearch(int flag); +int is_loclist_cmd(int cmdidx); int get_pressedreturn(void); void set_pressedreturn(int val); /* vim: set ft=c : */ diff --git a/src/proto/gui_gtk_x11.pro b/src/proto/gui_gtk_x11.pro index aea8d0b68e..111cac7c99 100644 --- a/src/proto/gui_gtk_x11.pro +++ b/src/proto/gui_gtk_x11.pro @@ -25,7 +25,7 @@ int gui_mch_maximized(void); void gui_mch_unmaximize(void); void gui_mch_newfont(void); void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction); -void gui_gtk_get_screen_size_of_win(GtkWidget *wid, int *width, int *height); +void gui_gtk_get_screen_geom_of_win(GtkWidget *wid, int *screen_x, int *screen_y, int *width, int *height); void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h); void gui_mch_settitle(char_u *title, char_u *icon); void gui_mch_enable_menu(int showit); diff --git a/src/proto/memline.pro b/src/proto/memline.pro index 727b24cc30..d18ede37b6 100644 --- a/src/proto/memline.pro +++ b/src/proto/memline.pro @@ -11,6 +11,8 @@ void ml_close_notmod(void); void ml_timestamp(buf_T *buf); void ml_recover(void); int recover_names(char_u *fname, int list, int nr, char_u **fname_out); +char_u *make_percent_swname(char_u *dir, char_u *name); +void get_b0_dict(char_u *fname, dict_T *d); void ml_sync_all(int check_file, int check_char); void ml_preserve(buf_T *buf, int message); char_u *ml_get(linenr_T lnum); @@ -34,5 +36,4 @@ char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned siz void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size); long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp); void goto_byte(long cnt); -char_u *make_percent_swname (char_u *dir, char_u *name); /* vim: set ft=c : */ diff --git a/src/proto/window.pro b/src/proto/window.pro index 7ed8042f7b..c31e59969b 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -94,4 +94,5 @@ void win_id2tabwin(typval_T *argvars, list_T *list); win_T *win_id2wp(typval_T *argvars); int win_id2win(typval_T *argvars); void win_findbuf(typval_T *argvars, list_T *list); +void get_framelayout(frame_T *fr, list_T *l, int topframe); /* vim: set ft=c : */ diff --git a/src/quickfix.c b/src/quickfix.c index ac40b24dd3..6248c21e64 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -159,6 +159,11 @@ static qf_info_T *ll_get_or_alloc_list(win_T *); #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) /* Location list window check helper macro */ #define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) + +// Quickfix and location list stack check helper macros +#define IS_QF_STACK(qi) (qi == &ql_info) +#define IS_LL_STACK(qi) (qi != &ql_info) + /* * Return location list for window 'wp' * For location list window, return the referenced location list @@ -1940,7 +1945,7 @@ qf_add_entry( qfp->qf_fnum = bufnum; if (buf != NULL) buf->b_has_qf_entry |= - (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; + IS_QF_STACK(qi) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; } else qfp->qf_fnum = qf_get_fnum(qi, qf_idx, dir, fname); @@ -2224,7 +2229,7 @@ qf_get_fnum(qf_info_T *qi, int qf_idx, char_u *directory, char_u *fname) return 0; buf->b_has_qf_entry = - (qi == &ql_info) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; + IS_QF_STACK(qi) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; return buf->b_fnum; } @@ -2631,7 +2636,7 @@ jump_to_help_window(qf_info_T *qi, int *opened_window) if (cmdmod.split == 0 && curwin->w_width != Columns && curwin->w_width < 80) flags |= WSP_TOP; - if (qi != &ql_info) + if (IS_LL_STACK(qi)) flags |= WSP_NEWLOC; /* don't copy the location list */ if (win_split(0, flags) == FAIL) @@ -2642,7 +2647,7 @@ jump_to_help_window(qf_info_T *qi, int *opened_window) if (curwin->w_height < p_hh) win_setheight((int)p_hh); - if (qi != &ql_info) /* not a quickfix list */ + if (IS_LL_STACK(qi)) // not a quickfix list { /* The new window should use the supplied location list */ curwin->w_llist = qi; @@ -2918,7 +2923,7 @@ qf_jump_edit_buffer( retval = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); - if (qi != &ql_info) + if (IS_LL_STACK(qi)) { /* * Location list. Check whether the associated window is still @@ -2939,7 +2944,7 @@ qf_jump_edit_buffer( else if (old_qf_curlist != qi->qf_curlist || !is_qf_entry_present(qi, qf_ptr)) { - if (qi == &ql_info) + if (IS_QF_STACK(qi)) EMSG(_("E925: Current quickfix was changed")); else EMSG(_(e_loc_list_changed)); @@ -3010,6 +3015,7 @@ qf_jump_goto_line( ++screen_col; } } + curwin->w_set_curswant = TRUE; check_cursor(); } else @@ -3330,7 +3336,7 @@ qf_list(exarg_T *eap) recognised errors */ qf_info_T *qi = &ql_info; - if (eap->cmdidx == CMD_llist) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -3478,7 +3484,7 @@ qf_age(exarg_T *eap) qf_info_T *qi = &ql_info; int count; - if (eap->cmdidx == CMD_lolder || eap->cmdidx == CMD_lnewer) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -3526,7 +3532,7 @@ qf_history(exarg_T *eap) qf_info_T *qi = &ql_info; int i; - if (eap->cmdidx == CMD_lhistory) + if (is_loclist_cmd(eap->cmdidx)) qi = GET_LOC_LIST(curwin); if (qi == NULL || (qi->qf_listcount == 0 && qf_list_empty(qi, qi->qf_curlist))) @@ -3745,7 +3751,7 @@ ex_cwindow(exarg_T *eap) qf_info_T *qi = &ql_info; win_T *win; - if (eap->cmdidx == CMD_lwindow) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -3781,7 +3787,7 @@ ex_cclose(exarg_T *eap) win_T *win = NULL; qf_info_T *qi = &ql_info; - if (eap->cmdidx == CMD_lclose || eap->cmdidx == CMD_lwindow) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -3808,7 +3814,7 @@ ex_copen(exarg_T *eap) buf_T *qf_buf; win_T *oldwin = curwin; - if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -3953,12 +3959,12 @@ qf_win_goto(win_T *win, linenr_T lnum) * :cbottom/:lbottom commands. */ void -ex_cbottom(exarg_T *eap UNUSED) +ex_cbottom(exarg_T *eap) { qf_info_T *qi = &ql_info; win_T *win; - if (eap->cmdidx == CMD_lbottom) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -4039,8 +4045,8 @@ is_qf_win(win_T *win, qf_info_T *qi) * pointing to the location list. */ if (bt_quickfix(win->w_buffer)) - if ((qi == &ql_info && win->w_llist_ref == NULL) - || (qi != &ql_info && win->w_llist_ref == qi)) + if ((IS_QF_STACK(qi) && win->w_llist_ref == NULL) + || (IS_LL_STACK(qi) && win->w_llist_ref == qi)) return TRUE; return FALSE; @@ -4430,8 +4436,7 @@ ex_make(exarg_T *eap) enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; #endif - if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep - || eap->cmdidx == CMD_lgrepadd) + if (is_loclist_cmd(eap->cmdidx)) wp = curwin; autowrite_all(); @@ -4570,7 +4575,7 @@ qf_get_size(exarg_T *eap) int i, sz = 0; int prev_fnum = 0; - if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) + if (is_loclist_cmd(eap->cmdidx)) { /* Location list */ qi = GET_LOC_LIST(curwin); @@ -4607,7 +4612,7 @@ qf_get_cur_idx(exarg_T *eap) { qf_info_T *qi = &ql_info; - if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) + if (is_loclist_cmd(eap->cmdidx)) { /* Location list */ qi = GET_LOC_LIST(curwin); @@ -4631,7 +4636,7 @@ qf_get_cur_valid_idx(exarg_T *eap) int i, eidx = 0; int prev_fnum = 0; - if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) + if (is_loclist_cmd(eap->cmdidx)) { /* Location list */ qi = GET_LOC_LIST(curwin); @@ -4724,12 +4729,7 @@ ex_cc(exarg_T *eap) qf_info_T *qi = &ql_info; int errornr; - if (eap->cmdidx == CMD_ll - || eap->cmdidx == CMD_lrewind - || eap->cmdidx == CMD_lfirst - || eap->cmdidx == CMD_llast - || eap->cmdidx == CMD_ldo - || eap->cmdidx == CMD_lfdo) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -4743,13 +4743,18 @@ ex_cc(exarg_T *eap) errornr = (int)eap->line2; else { - if (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll) - errornr = 0; - else if (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind - || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst) - errornr = 1; - else - errornr = 32767; + switch (eap->cmdidx) + { + case CMD_cc: case CMD_ll: + errornr = 0; + break; + case CMD_crewind: case CMD_lrewind: case CMD_cfirst: + case CMD_lfirst: + errornr = 1; + break; + default: + errornr = 32767; + } } /* For cdo and ldo commands, jump to the nth valid error. @@ -4774,15 +4779,9 @@ ex_cnext(exarg_T *eap) { qf_info_T *qi = &ql_info; int errornr; + int dir; - if (eap->cmdidx == CMD_lnext - || eap->cmdidx == CMD_lNext - || eap->cmdidx == CMD_lprevious - || eap->cmdidx == CMD_lnfile - || eap->cmdidx == CMD_lNfile - || eap->cmdidx == CMD_lpfile - || eap->cmdidx == CMD_ldo - || eap->cmdidx == CMD_lfdo) + if (is_loclist_cmd(eap->cmdidx)) { qi = GET_LOC_LIST(curwin); if (qi == NULL) @@ -4799,17 +4798,28 @@ ex_cnext(exarg_T *eap) else errornr = 1; - qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext - || eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) - ? FORWARD - : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile - || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) - ? FORWARD_FILE - : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_lpfile - || eap->cmdidx == CMD_cNfile || eap->cmdidx == CMD_lNfile) - ? BACKWARD_FILE - : BACKWARD, - errornr, eap->forceit); + // Depending on the command jump to either next or previous entry/file. + switch (eap->cmdidx) + { + case CMD_cnext: case CMD_lnext: case CMD_cdo: case CMD_ldo: + dir = FORWARD; + break; + case CMD_cprevious: case CMD_lprevious: case CMD_cNext: + case CMD_lNext: + dir = BACKWARD; + break; + case CMD_cnfile: case CMD_lnfile: case CMD_cfdo: case CMD_lfdo: + dir = FORWARD_FILE; + break; + case CMD_cpfile: case CMD_lpfile: case CMD_cNfile: case CMD_lNfile: + dir = BACKWARD_FILE; + break; + default: + dir = FORWARD; + break; + } + + qf_jump(qi, dir, errornr, eap->forceit); } /* @@ -4857,9 +4867,7 @@ ex_cfile(exarg_T *eap) if (*eap->arg != NUL) set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0); - if (eap->cmdidx == CMD_lfile - || eap->cmdidx == CMD_lgetfile - || eap->cmdidx == CMD_laddfile) + if (is_loclist_cmd(eap->cmdidx)) wp = curwin; /* @@ -5178,10 +5186,7 @@ ex_vimgrep(exarg_T *eap) #endif } - if (eap->cmdidx == CMD_lgrep - || eap->cmdidx == CMD_lvimgrep - || eap->cmdidx == CMD_lgrepadd - || eap->cmdidx == CMD_lvimgrepadd) + if (is_loclist_cmd(eap->cmdidx)) { qi = ll_get_or_alloc_list(curwin); if (qi == NULL) @@ -5380,7 +5385,7 @@ ex_vimgrep(exarg_T *eap) if (qf_restore_list(qi, save_qfid) == FAIL) goto theend; - /* Jump to first match. */ + // Jump to first match. if (!qf_list_empty(qi, qi->qf_curlist)) { if ((flags & VGR_NOJUMP) == 0) @@ -6525,9 +6530,7 @@ ex_cbuffer(exarg_T *eap) } /* Must come after autocommands. */ - if (eap->cmdidx == CMD_lbuffer - || eap->cmdidx == CMD_lgetbuffer - || eap->cmdidx == CMD_laddbuffer) + if (is_loclist_cmd(eap->cmdidx)) { qi = ll_get_or_alloc_list(curwin); if (qi == NULL) @@ -6631,9 +6634,7 @@ ex_cexpr(exarg_T *eap) #endif } - if (eap->cmdidx == CMD_lexpr - || eap->cmdidx == CMD_lgetexpr - || eap->cmdidx == CMD_laddexpr) + if (is_loclist_cmd(eap->cmdidx)) { qi = ll_get_or_alloc_list(curwin); if (qi == NULL) @@ -6843,16 +6844,13 @@ hgr_search_files_in_dir( /* * Search for a pattern in all the help files in the 'runtimepath' * and add the matches to a quickfix list. - * 'arg' is the language specifier. If supplied, then only matches in the + * 'lang' is the language specifier. If supplied, then only matches in the * specified language are found. */ static void -hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg) +hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *lang) { char_u *p; -#ifdef FEAT_MULTI_LANG - char_u *lang; -#endif #ifdef FEAT_MBYTE vimconv_T vc; @@ -6864,10 +6862,6 @@ hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg) convert_setup(&vc, (char_u *)"utf-8", p_enc); #endif -#ifdef FEAT_MULTI_LANG - /* Check for a specified language */ - lang = check_help_lang(arg); -#endif /* Go through all the directories in 'runtimepath' */ p = p_rtp; @@ -6902,6 +6896,7 @@ ex_helpgrep(exarg_T *eap) qf_info_T *qi = &ql_info; int new_qi = FALSE; char_u *au_name = NULL; + char_u *lang = NULL; switch (eap->cmdidx) { @@ -6918,25 +6913,29 @@ ex_helpgrep(exarg_T *eap) #endif } - /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ + // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; p_cpo = empty_option; - if (eap->cmdidx == CMD_lhelpgrep) + if (is_loclist_cmd(eap->cmdidx)) { qi = hgr_get_ll(&new_qi); if (qi == NULL) return; } +#ifdef FEAT_MULTI_LANG + // Check for a specified language + lang = check_help_lang(eap->arg); +#endif regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING); regmatch.rm_ic = FALSE; if (regmatch.regprog != NULL) { - /* create a new quickfix list */ + // create a new quickfix list qf_new_list(qi, qf_cmdtitle(*eap->cmdlinep)); - hgr_search_in_rtp(qi, ®match, eap->arg); + hgr_search_in_rtp(qi, ®match, lang); vim_regfree(regmatch.regprog); @@ -6949,7 +6948,7 @@ ex_helpgrep(exarg_T *eap) if (p_cpo == empty_option) p_cpo = save_cpo; else - /* Darn, some plugin changed the value. */ + // Darn, some plugin changed the value. free_string_option(save_cpo); qf_list_changed(qi, qi->qf_curlist); @@ -6959,7 +6958,7 @@ ex_helpgrep(exarg_T *eap) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, TRUE, curbuf); - if (!new_qi && qi != &ql_info && qf_find_buf(qi) == NULL) + if (!new_qi && IS_LL_STACK(qi) && qf_find_buf(qi) == NULL) /* autocommands made "qi" invalid */ return; } @@ -6972,8 +6971,8 @@ ex_helpgrep(exarg_T *eap) if (eap->cmdidx == CMD_lhelpgrep) { - /* If the help window is not opened or if it already points to the - * correct location list, then free the new location list. */ + // If the help window is not opened or if it already points to the + // correct location list, then free the new location list. if (!bt_help(curwin->w_buffer) || curwin->w_llist == qi) { if (new_qi) diff --git a/src/search.c b/src/search.c index 597b8816cf..143781d1dd 100644 --- a/src/search.c +++ b/src/search.c @@ -4115,9 +4115,10 @@ again: } curwin->w_cursor = end_pos; - /* If we now have the same text as before reset "do_include" and try - * again. */ - if (EQUAL_POS(start_pos, old_start) && EQUAL_POS(end_pos, old_end)) + // If we are in Visual mode and now have the same text as before set + // "do_include" and try again. + if (VIsual_active && EQUAL_POS(start_pos, old_start) + && EQUAL_POS(end_pos, old_end)) { do_include = TRUE; curwin->w_cursor = old_start; diff --git a/src/term.c b/src/term.c index f37a1f98f4..bd40c44c4a 100644 --- a/src/term.c +++ b/src/term.c @@ -3850,7 +3850,7 @@ cursor_on_force(void) } /* - * Enable the cursor. + * Enable the cursor if it's currently off. */ void cursor_on(void) diff --git a/src/testdir/dumps/Test_incsearch_sort_01.dump b/src/testdir/dumps/Test_incsearch_sort_01.dump new file mode 100644 index 0000000000..6c003af419 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_sort_01.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t|h|e|r| |o+1&&|n|e+0&&| |2| @56 +|t|h|a|t| |o+0&#ffff4012|n|e+0&#ffffff0| |3| @59 +|t|h|e| |o+0&#ffff4012|n|e+0&#ffffff0| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|s|o|r|t| |n|i| |u| |/|o|n> @55 diff --git a/src/testdir/dumps/Test_incsearch_substitute_06.dump b/src/testdir/dumps/Test_incsearch_substitute_06.dump new file mode 100644 index 0000000000..8a666208a0 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_substitute_06.dump @@ -0,0 +1,9 @@ +|f+0&#ffffff0|o@1| |3| @64 +|f+1&&|o@1| +0&&|4| @64 +|f+0&#ffff4012|o@1| +0&#ffffff0|5| @64 +|f|o@1| |6| @64 +|f|o@1| |7| @64 +|f|o@1| |8| @64 +|:|a|b|o|v|e| |b|e|l|o|w| |b|r|o|w|s|e| |b|o|t|r| |c|o|n|f|i|r|m| |k|e@1|p|m|a|r| |k|e@1|p|a|l|t| |k|e@1|p@1|a|t| |k|e@1|p|j|u|m| |f|i|l|t|e +|r| |x@2| |h|i|d|e| |l|o|c|k|m| |l|e|f|t|a|b|o|v|e| |n|o|a|u| |n|o|s|w|a|p| |r|i|g|h|t|b|e|l| |s|a|n|d|b|o|x| |s|i|l|e|n|t| |s|i|l|e|n|t|! +| |$|t|a|b| |t|o|p| |u|n|s|i|l| |v|e|r|t| |v|e|r|b|o|s|e| |4|,|5|s|/|f|o|.> @32 diff --git a/src/testdir/dumps/Test_incsearch_substitute_07.dump b/src/testdir/dumps/Test_incsearch_substitute_07.dump new file mode 100644 index 0000000000..7b4dc6e14a --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_substitute_07.dump @@ -0,0 +1,9 @@ +|f+0&#ffffff0|o@1| |4| @64 +|f|o@1| |5| @64 +|f|o@1| |6| @64 +|f|o@1| |7| @64 +|f|o@1| |8| @64 +|f|o@1| |9| @64 +|f|o@1| |1|0| @63 +|b+9&&|a|r| +8&&|1@1| @63 +|:+0&&|9|,|1@1|s|/|b|a|r> @59 diff --git a/src/testdir/dumps/Test_incsearch_substitute_08.dump b/src/testdir/dumps/Test_incsearch_substitute_08.dump new file mode 100644 index 0000000000..d87e507b2e --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_substitute_08.dump @@ -0,0 +1,9 @@ +|f+0&#ffffff0|o@1| |4| @64 +|f|o@1| |5| @64 +|f|o@1| |6| @64 +|f|o@1| |7| @64 +|f|o@1| |8| @64 +|f+8&&|o@1| |9| @64 +|f+0&&|o@1| |1|0| @63 +|b|a|r| |1@1| @63 +|:|9|,|1|0|s|/|b|a|r> @59 diff --git a/src/testdir/dumps/Test_incsearch_vimgrep_01.dump b/src/testdir/dumps/Test_incsearch_vimgrep_01.dump new file mode 100644 index 0000000000..955d030583 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_vimgrep_01.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t|h|e|r| |o+1&&|n|e+0&&| |2| @56 +|t|h|a|t| |o+0&#ffff4012|n|e+0&#ffffff0| |3| @59 +|t|h|e| |o+0&#ffff4012|n|e+0&#ffffff0| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|v|i|m|g|r|e|p| |o|n> @58 diff --git a/src/testdir/dumps/Test_incsearch_vimgrep_02.dump b/src/testdir/dumps/Test_incsearch_vimgrep_02.dump new file mode 100644 index 0000000000..a5d94eac55 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_vimgrep_02.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t|h|e|r| |o+1&&|n|e+0&&| |2| @56 +|t|h|a|t| |o+0&#ffff4012|n|e+0&#ffffff0| |3| @59 +|t|h|e| |o+0&#ffff4012|n|e+0&#ffffff0| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|v|i|m|g| |/|o|n|/| |*|.|t|x|t> @53 diff --git a/src/testdir/dumps/Test_incsearch_vimgrep_03.dump b/src/testdir/dumps/Test_incsearch_vimgrep_03.dump new file mode 100644 index 0000000000..038ceb9d95 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_vimgrep_03.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t|h|e|r| |o+1&&|n|e+0&&| |2| @56 +|t|h|a|t| |o+0&#ffff4012|n|e+0&#ffffff0| |3| @59 +|t|h|e| |o+0&#ffff4012|n|e+0&#ffffff0| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|v|i|m|g|r|e|p|a|d@1| |"|\|<|o|n> @52 diff --git a/src/testdir/dumps/Test_incsearch_vimgrep_04.dump b/src/testdir/dumps/Test_incsearch_vimgrep_04.dump new file mode 100644 index 0000000000..92dd78dd87 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_vimgrep_04.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t|h|e|r| |o|n|e| |2| @56 +|t+1&&|h|a|t+0&&| |o|n|e| |3| @59 +|t|h|e| |o|n|e| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|l|v| |"|t|h|a> @61 diff --git a/src/testdir/dumps/Test_incsearch_vimgrep_05.dump b/src/testdir/dumps/Test_incsearch_vimgrep_05.dump new file mode 100644 index 0000000000..e11ff574c1 --- /dev/null +++ b/src/testdir/dumps/Test_incsearch_vimgrep_05.dump @@ -0,0 +1,9 @@ +|a+0&#ffffff0|n|o|t+1&&|h|e|r+0&&| |o|n|e| |2| @56 +|t|h|a|t| |o|n|e| |3| @59 +|t+0&#ffff4012|h|e| +0&#ffffff0|o|n|e| |1| @60 +|~+0#4040ff13&| @68 +|~| @68 +|~| @68 +|~| @68 +|~| @68 +|:+0#0000000&|l|v|i|m|g|r|e|p|a| |"|t|h|e|"| |*@1|/|*|.|t|x|t> @44 diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 4f508a4875..c3414914f8 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -272,6 +272,7 @@ let s:flaky = [ \ 'Test_paused()', \ 'Test_pipe_through_sort_all()', \ 'Test_pipe_through_sort_some()', + \ 'Test_popup_and_window_resize()', \ 'Test_quoteplus()', \ 'Test_quotestar()', \ 'Test_reltime()', diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 13db0041e7..848e7986c3 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -682,6 +682,7 @@ endfunc func Test_byte2line_line2byte() new + set endofline call setline(1, ['a', 'bc', 'd']) set fileformat=unix @@ -702,7 +703,16 @@ func Test_byte2line_line2byte() call assert_equal([-1, -1, 1, 4, 8, 11, -1], \ map(range(-1, 5), 'line2byte(v:val)')) - set fileformat& + bw! + set noendofline nofixendofline + normal a- + for ff in ["unix", "mac", "dos"] + let &fileformat = ff + call assert_equal(1, line2byte(1)) + call assert_equal(2, line2byte(2)) " line2byte(line("$") + 1) is the buffer size plus one (as per :help line2byte). + endfor + + set endofline& fixendofline& fileformat& bw! endfunc diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index d8f033e03f..2d4a97aa18 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -414,3 +414,24 @@ func Test_shortmess_F() set shortmess& bwipe endfunc + +func Test_shortmess_F2() + e file1 + e file2 + call assert_match('file1', execute('bn', '')) + call assert_match('file2', execute('bn', '')) + set shortmess+=F + call assert_true(empty(execute('bn', ''))) + call assert_true(empty(execute('bn', ''))) + set hidden + call assert_true(empty(execute('bn', ''))) + call assert_true(empty(execute('bn', ''))) + set nohidden + call assert_true(empty(execute('bn', ''))) + call assert_true(empty(execute('bn', ''))) + set shortmess& + call assert_match('file1', execute('bn', '')) + call assert_match('file2', execute('bn', '')) + bwipe + bwipe +endfunc diff --git a/src/testdir/test_profile.vim b/src/testdir/test_profile.vim index 6c24d31100..cf9f3465cf 100644 --- a/src/testdir/test_profile.vim +++ b/src/testdir/test_profile.vim @@ -67,7 +67,7 @@ func Test_profile_func() call assert_match('^\s*1\s\+.*\slet l:count = 100$', lines[13]) call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[14]) call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[15]) - call assert_match('^\s*100\s\+.*\sendwhile$', lines[16]) + call assert_match('^\s*101\s\+.*\sendwhile$', lines[16]) call assert_equal('', lines[17]) call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[18]) call assert_equal('count total (s) self (s) function', lines[19]) @@ -84,6 +84,227 @@ func Test_profile_func() call delete('Xprofile_func.log') endfunc +func Test_profile_func_with_ifelse() + let lines = [ + \ "func! Foo1()", + \ " if 1", + \ " let x = 0", + \ " elseif 1", + \ " let x = 1", + \ " else", + \ " let x = 2", + \ " endif", + \ "endfunc", + \ "func! Foo2()", + \ " if 0", + \ " let x = 0", + \ " elseif 1", + \ " let x = 1", + \ " else", + \ " let x = 2", + \ " endif", + \ "endfunc", + \ "func! Foo3()", + \ " if 0", + \ " let x = 0", + \ " elseif 0", + \ " let x = 1", + \ " else", + \ " let x = 2", + \ " endif", + \ "endfunc", + \ "call Foo1()", + \ "call Foo2()", + \ "call Foo3()", + \ ] + + call writefile(lines, 'Xprofile_func.vim') + call system(v:progpath + \ . ' -es -u NONE -U NONE -i NONE --noplugin' + \ . ' -c "profile start Xprofile_func.log"' + \ . ' -c "profile func Foo*"' + \ . ' -c "so Xprofile_func.vim"' + \ . ' -c "qall!"') + call assert_equal(0, v:shell_error) + + let lines = readfile('Xprofile_func.log') + + " - Foo1() should pass 'if' block. + " - Foo2() should pass 'elseif' block. + " - Foo3() should pass 'else' block. + call assert_equal(54, len(lines)) + + call assert_equal('FUNCTION Foo1()', lines[0]) + call assert_equal('Called 1 time', lines[1]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3]) + call assert_equal('', lines[4]) + call assert_equal('count total (s) self (s)', lines[5]) + call assert_match('^\s*1\s\+.*\sif 1$', lines[6]) + call assert_match('^\s*1\s\+.*\s let x = 0$', lines[7]) + call assert_match( '^\s\+elseif 1$', lines[8]) + call assert_match( '^\s\+let x = 1$', lines[9]) + call assert_match( '^\s\+else$', lines[10]) + call assert_match( '^\s\+let x = 2$', lines[11]) + call assert_match('^\s*1\s\+.*\sendif$', lines[12]) + call assert_equal('', lines[13]) + call assert_equal('FUNCTION Foo2()', lines[14]) + call assert_equal('Called 1 time', lines[15]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[16]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[17]) + call assert_equal('', lines[18]) + call assert_equal('count total (s) self (s)', lines[19]) + call assert_match('^\s*1\s\+.*\sif 0$', lines[20]) + call assert_match( '^\s\+let x = 0$', lines[21]) + call assert_match('^\s*1\s\+.*\selseif 1$', lines[22]) + call assert_match('^\s*1\s\+.*\s let x = 1$', lines[23]) + call assert_match( '^\s\+else$', lines[24]) + call assert_match( '^\s\+let x = 2$', lines[25]) + call assert_match('^\s*1\s\+.*\sendif$', lines[26]) + call assert_equal('', lines[27]) + call assert_equal('FUNCTION Foo3()', lines[28]) + call assert_equal('Called 1 time', lines[29]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[30]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[31]) + call assert_equal('', lines[32]) + call assert_equal('count total (s) self (s)', lines[33]) + call assert_match('^\s*1\s\+.*\sif 0$', lines[34]) + call assert_match( '^\s\+let x = 0$', lines[35]) + call assert_match('^\s*1\s\+.*\selseif 0$', lines[36]) + call assert_match( '^\s\+let x = 1$', lines[37]) + call assert_match('^\s*1\s\+.*\selse$', lines[38]) + call assert_match('^\s*1\s\+.*\s let x = 2$', lines[39]) + call assert_match('^\s*1\s\+.*\sendif$', lines[40]) + call assert_equal('', lines[41]) + call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[42]) + call assert_equal('count total (s) self (s) function', lines[43]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[44]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[45]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[46]) + call assert_equal('', lines[47]) + call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[48]) + call assert_equal('count total (s) self (s) function', lines[49]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[50]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[51]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[52]) + call assert_equal('', lines[53]) + + call delete('Xprofile_func.vim') + call delete('Xprofile_func.log') +endfunc + +func Test_profile_func_with_trycatch() + let lines = [ + \ "func! Foo1()", + \ " try", + \ " let x = 0", + \ " catch", + \ " let x = 1", + \ " finally", + \ " let x = 2", + \ " endtry", + \ "endfunc", + \ "func! Foo2()", + \ " try", + \ " throw 0", + \ " catch", + \ " let x = 1", + \ " finally", + \ " let x = 2", + \ " endtry", + \ "endfunc", + \ "func! Foo3()", + \ " try", + \ " throw 0", + \ " catch", + \ " throw 1", + \ " finally", + \ " let x = 2", + \ " endtry", + \ "endfunc", + \ "call Foo1()", + \ "call Foo2()", + \ "try", + \ " call Foo3()", + \ "catch", + \ "endtry", + \ ] + + call writefile(lines, 'Xprofile_func.vim') + call system(v:progpath + \ . ' -es -u NONE -U NONE -i NONE --noplugin' + \ . ' -c "profile start Xprofile_func.log"' + \ . ' -c "profile func Foo*"' + \ . ' -c "so Xprofile_func.vim"' + \ . ' -c "qall!"') + call assert_equal(0, v:shell_error) + + let lines = readfile('Xprofile_func.log') + + " - Foo1() should pass 'try' 'finally' blocks. + " - Foo2() should pass 'catch' 'finally' blocks. + " - Foo3() should not pass 'endtry'. + call assert_equal(54, len(lines)) + + call assert_equal('FUNCTION Foo1()', lines[0]) + call assert_equal('Called 1 time', lines[1]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3]) + call assert_equal('', lines[4]) + call assert_equal('count total (s) self (s)', lines[5]) + call assert_match('^\s*1\s\+.*\stry$', lines[6]) + call assert_match('^\s*1\s\+.*\s let x = 0$', lines[7]) + call assert_match( '^\s\+catch$', lines[8]) + call assert_match( '^\s\+let x = 1$', lines[9]) + call assert_match('^\s*1\s\+.*\sfinally$', lines[10]) + call assert_match('^\s*1\s\+.*\s let x = 2$', lines[11]) + call assert_match('^\s*1\s\+.*\sendtry$', lines[12]) + call assert_equal('', lines[13]) + call assert_equal('FUNCTION Foo2()', lines[14]) + call assert_equal('Called 1 time', lines[15]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[16]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[17]) + call assert_equal('', lines[18]) + call assert_equal('count total (s) self (s)', lines[19]) + call assert_match('^\s*1\s\+.*\stry$', lines[20]) + call assert_match('^\s*1\s\+.*\s throw 0$', lines[21]) + call assert_match('^\s*1\s\+.*\scatch$', lines[22]) + call assert_match('^\s*1\s\+.*\s let x = 1$', lines[23]) + call assert_match('^\s*1\s\+.*\sfinally$', lines[24]) + call assert_match('^\s*1\s\+.*\s let x = 2$', lines[25]) + call assert_match('^\s*1\s\+.*\sendtry$', lines[26]) + call assert_equal('', lines[27]) + call assert_equal('FUNCTION Foo3()', lines[28]) + call assert_equal('Called 1 time', lines[29]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[30]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[31]) + call assert_equal('', lines[32]) + call assert_equal('count total (s) self (s)', lines[33]) + call assert_match('^\s*1\s\+.*\stry$', lines[34]) + call assert_match('^\s*1\s\+.*\s throw 0$', lines[35]) + call assert_match('^\s*1\s\+.*\scatch$', lines[36]) + call assert_match('^\s*1\s\+.*\s throw 1$', lines[37]) + call assert_match('^\s*1\s\+.*\sfinally$', lines[38]) + call assert_match('^\s*1\s\+.*\s let x = 2$', lines[39]) + call assert_match( '^\s\+endtry$', lines[40]) + call assert_equal('', lines[41]) + call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[42]) + call assert_equal('count total (s) self (s) function', lines[43]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[44]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[45]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[46]) + call assert_equal('', lines[47]) + call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[48]) + call assert_equal('count total (s) self (s) function', lines[49]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[50]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[51]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo.()$', lines[52]) + call assert_equal('', lines[53]) + + call delete('Xprofile_func.vim') + call delete('Xprofile_func.log') +endfunc + func Test_profile_file() let lines = [ \ 'func! Foo()', @@ -123,7 +344,7 @@ func Test_profile_file() call assert_equal(' " a comment', lines[9]) " if self and total are equal we only get one number call assert_match('^\s*20\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[10]) - call assert_match('^\s*20\s\+\d\+\.\d\+\s\+endfor$', lines[11]) + call assert_match('^\s*22\s\+\d\+\.\d\+\s\+endfor$', lines[11]) " if self and total are equal we only get one number call assert_match('^\s*2\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[12]) call assert_equal('', lines[13]) diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index ce19e74d3f..6063fd63cd 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -3091,6 +3091,20 @@ func Test_qf_tick() call Xqftick_tests('l') endfunc +" Test helpgrep with lang specifier +func Xtest_helpgrep_with_lang_specifier(cchar) + call s:setup_commands(a:cchar) + Xhelpgrep Vim@en + call assert_equal('help', &filetype) + call assert_notequal(0, g:Xgetlist({'nr' : '$'}).nr) + new | only +endfunc + +func Test_helpgrep_with_lang_specifier() + call Xtest_helpgrep_with_lang_specifier('c') + call Xtest_helpgrep_with_lang_specifier('l') +endfunc + " The following test used to crash Vim. " Open the location list window and close the regular window associated with " the location list. When the garbage collection runs now, it incorrectly @@ -3546,3 +3560,12 @@ func Test_view_result_split() call Xview_result_split_tests('c') call Xview_result_split_tests('l') endfunc + +" Test that :cc sets curswant +func Test_curswant() + helpgrep quickfix + normal! llll + 1cc + call assert_equal(getcurpos()[4], virtcol('.')) + cclose | helpclose +endfunc diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index 8d4b7cc604..9ede26dd3e 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -384,6 +384,14 @@ func Test_search_cmdline3s() undo call feedkeys(":%substitute/the\/xxx\", 'tx') call assert_equal(' 2 xxxe', getline('.')) + undo + call feedkeys(":%smagic/the.e/xxx\", 'tx') + call assert_equal(' 2 xxx', getline('.')) + undo + call assert_fails(":%snomagic/the.e/xxx\", 'E486') + " + call feedkeys(":%snomagic/the\\.e/xxx\", 'tx') + call assert_equal(' 2 xxx', getline('.')) call Incsearch_cleanup() endfunc @@ -839,6 +847,7 @@ func Test_incsearch_substitute_dump() \ 'for n in range(1, 10)', \ ' call setline(n, "foo " . n)', \ 'endfor', + \ 'call setline(11, "bar 11")', \ '3', \ ], 'Xis_subst_script') let buf = RunVimInTerminal('-S Xis_subst_script', {'rows': 9, 'cols': 70}) @@ -884,10 +893,104 @@ func Test_incsearch_substitute_dump() call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {}) call term_sendkeys(buf, "\") + " Command modifiers are skipped + call term_sendkeys(buf, ':above below browse botr confirm keepmar keepalt keeppat keepjum filter xxx hide lockm leftabove noau noswap rightbel sandbox silent silent! $tab top unsil vert verbose 4,5s/fo.') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_substitute_06', {}) + call term_sendkeys(buf, "\") + + " Cursorline highlighting at match + call term_sendkeys(buf, ":set cursorline\") + call term_sendkeys(buf, 'G9G') + call term_sendkeys(buf, ':9,11s/bar') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_substitute_07', {}) + call term_sendkeys(buf, "\") + + " Cursorline highlighting at cursor when no match + call term_sendkeys(buf, ':9,10s/bar') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_substitute_08', {}) + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) call delete('Xis_subst_script') endfunc +" Similar to Test_incsearch_substitute_dump() for :sort +func Test_incsearch_ssort_dump() + if !exists('+incsearch') + return + endif + if !CanRunVimInTerminal() + return + endif + call writefile([ + \ 'set incsearch hlsearch scrolloff=0', + \ 'call setline(1, ["another one 2", "that one 3", "the one 1"])', + \ ], 'Xis_sort_script') + let buf = RunVimInTerminal('-S Xis_sort_script', {'rows': 9, 'cols': 70}) + " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by + " the 'ambiwidth' check. + sleep 100m + + " Need to send one key at a time to force a redraw. + call term_sendkeys(buf, ':sort ni u /on') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_sort_01', {}) + call term_sendkeys(buf, "\") + + call StopVimInTerminal(buf) + call delete('Xis_sort_script') +endfunc + +" Similar to Test_incsearch_substitute_dump() for :vimgrep famiry +func Test_incsearch_vimgrep_dump() + if !exists('+incsearch') + return + endif + if !CanRunVimInTerminal() + return + endif + call writefile([ + \ 'set incsearch hlsearch scrolloff=0', + \ 'call setline(1, ["another one 2", "that one 3", "the one 1"])', + \ ], 'Xis_vimgrep_script') + let buf = RunVimInTerminal('-S Xis_vimgrep_script', {'rows': 9, 'cols': 70}) + " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by + " the 'ambiwidth' check. + sleep 100m + + " Need to send one key at a time to force a redraw. + call term_sendkeys(buf, ':vimgrep on') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_01', {}) + call term_sendkeys(buf, "\") + + call term_sendkeys(buf, ':vimg /on/ *.txt') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_02', {}) + call term_sendkeys(buf, "\") + + call term_sendkeys(buf, ':vimgrepadd "\") + + call term_sendkeys(buf, ':lv "tha') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_04', {}) + call term_sendkeys(buf, "\") + + call term_sendkeys(buf, ':lvimgrepa "the" **/*.txt') + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_05', {}) + call term_sendkeys(buf, "\") + + call StopVimInTerminal(buf) + call delete('Xis_vimgrep_script') +endfunc + func Test_search_undefined_behaviour() if !has("terminal") return diff --git a/src/testdir/test_swap.vim b/src/testdir/test_swap.vim index da5da2dbbd..c12693c81c 100644 --- a/src/testdir/test_swap.vim +++ b/src/testdir/test_swap.vim @@ -97,3 +97,38 @@ func Test_missing_dir() set directory& call delete('Xswapdir', 'rf') endfunc + +func Test_swapinfo() + new Xswapinfo + call setline(1, ['one', 'two', 'three']) + w + let fname = trim(execute('swapname')) + call assert_match('Xswapinfo', fname) + let info = swapinfo(fname) + call assert_match('8\.', info.version) + call assert_match('\w', info.user) + call assert_equal(hostname(), info.host) + call assert_match('Xswapinfo', info.fname) + call assert_match(0, info.dirty) + call assert_equal(getpid(), info.pid) + call assert_match('^\d*$', info.mtime) + if has_key(info, 'inode') + call assert_match('\d', info.inode) + endif + bwipe! + call delete(fname) + call delete('Xswapinfo') + + let info = swapinfo('doesnotexist') + call assert_equal('Cannot open file', info.error) + + call writefile(['burp'], 'Xnotaswapfile') + let info = swapinfo('Xnotaswapfile') + call assert_equal('Cannot read file', info.error) + call delete('Xnotaswapfile') + + call writefile([repeat('x', 10000)], 'Xnotaswapfile') + let info = swapinfo('Xnotaswapfile') + call assert_equal('Not a swap file', info.error) + call delete('Xnotaswapfile') +endfunc diff --git a/src/testdir/test_textobjects.vim b/src/testdir/test_textobjects.vim index f02619fc09..6a2f5044cc 100644 --- a/src/testdir/test_textobjects.vim +++ b/src/testdir/test_textobjects.vim @@ -121,6 +121,23 @@ func Test_string_html_objects() enew! endfunc +func Test_empty_html_tag() + new + call setline(1, '
') + normal 0citxxx + call assert_equal('
xxx
', getline(1)) + + call setline(1, '
') + normal 0fyyy', getline(1)) + + call setline(1, '
') + normal 0fw_id); } +/* + * Get the layout of the given tab page for winlayout(). + */ + void +get_framelayout(frame_T *fr, list_T *l, int outer) +{ + frame_T *child; + list_T *fr_list; + list_T *win_list; + + if (fr == NULL) + return; + + if (outer) + // outermost call from f_winlayout() + fr_list = l; + else + { + fr_list = list_alloc(); + if (fr_list == NULL) + return; + list_append_list(l, fr_list); + } + + if (fr->fr_layout == FR_LEAF) + { + if (fr->fr_win != NULL) + { + list_append_string(fr_list, (char_u *)"leaf", -1); + list_append_number(fr_list, fr->fr_win->w_id); + } + } + else + { + list_append_string(fr_list, + fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1); + + win_list = list_alloc(); + if (win_list == NULL) + return; + list_append_list(fr_list, win_list); + child = fr->fr_child; + while (child != NULL) + { + get_framelayout(child, win_list, FALSE); + child = child->fr_next; + } + } +} #endif