# HG changeset patch # User Christian Brabandt # Date 1471989608 -7200 # Node ID e975914c17e97a1559b037296c584f3cd6c7988c # Parent b7b5f6a8607e9238a651a27d9c1ab535448abf08 commit https://github.com/vim/vim/commit/7b668e83d0635d082b7ec90d7d2aa30a9d7d8928 Author: Bram Moolenaar Date: Tue Aug 23 23:51:21 2016 +0200 patch 7.4.2244 Problem: Adding pattern to ":oldfiles" is not a generic solution. Solution: Add the ":filter /pat/ cmd" command modifier. Only works for some commands right now. diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 7.4. Last change: 2016 Aug 06 +*starting.txt* For Vim version 7.4. Last change: 2016 Aug 23 VIM REFERENCE MANUAL by Bram Moolenaar @@ -923,7 +923,8 @@ 12. Execute startup commands The $MYVIMRC or $MYGVIMRC file will be set to the first found vimrc and/or gvimrc file. -Some hints on using initializations: + +Some hints on using initializations ~ Standard setup: Create a vimrc file to set the default settings and mappings for all your edit @@ -946,27 +947,37 @@ want to set the defaults for all users. for default settings and mappings and put it in the place that is given with the ":version" command. -Saving the current state of Vim to a file: + +Saving the current state of Vim to a file ~ + Whenever you have changed values of options or when you have created a mapping, then you may want to save them in a vimrc file for later use. See |save-settings| about saving the current state of settings to a file. -Avoiding setup problems for Vi users: + +Avoiding setup problems for Vi users ~ + Vi uses the variable EXINIT and the file "~/.exrc". So if you do not want to interfere with Vi, then use the variable VIMINIT and the file "vimrc" instead. -Amiga environment variables: + +Amiga environment variables ~ + On the Amiga, two types of environment variables exist. The ones set with the DOS 1.3 (or later) setenv command are recognized. See the AmigaDos 1.3 manual. The environment variables set with the old Manx Set command (before version 5.0) are not recognized. -MS-DOS line separators: + +MS-DOS line separators ~ + On MS-DOS-like systems (MS-DOS itself, Win32, and OS/2), Vim assumes that all the vimrc files have pairs as line separators. This will give problems if you have a file with only s and have a line like ":map xx yy^M". The trailing ^M will be ignored. + +Vi compatible default value ~ *compatible-default* When Vim starts, the 'compatible' option is on. This will be used when Vim starts its initializations. But as soon as: @@ -999,6 +1010,8 @@ encountered. This makes a difference wh mappings depend on a certain value of 'compatible', set or reset it before giving the mapping. + +Defaults without a .vimrc file ~ *defaults.vim* If Vim is started normally and no user vimrc file is found, the $VIMRUTIME/defaults.vim script is loaded. This will set 'compatible' off, @@ -1018,7 +1031,8 @@ revert individual settings. See the def revert each item. -Avoiding trojan horses: *trojan-horse* +Avoiding trojan horses ~ + *trojan-horse* While reading the "vimrc" or the "exrc" file in the current directory, some commands can be disabled for security reasons by setting the 'secure' option. This is always done when executing the command from a tags file. Otherwise it @@ -1041,6 +1055,8 @@ Be careful! part of the line in the tags file) is always done in secure mode. This works just like executing a command from a vimrc/exrc in the current directory. + +If Vim startup is slow ~ *slow-start* If Vim takes a long time to start up, use the |--startuptime| argument to find out what happens. There are a few common causes: @@ -1055,6 +1071,8 @@ out what happens. There are a few commo moment (use the Vim argument "-i NONE", |-i|). Try reducing the number of lines stored in a register with ":set viminfo='20,<50,s10". |viminfo-file|. + +Intro message ~ *:intro* When Vim starts without a file name, an introductory message is displayed (for those who don't know what Vim is). It is removed as soon as the display is @@ -1613,18 +1631,12 @@ most of the information will be restored file. This list is read on startup and only changes afterwards with `:rviminfo!`. Also see |v:oldfiles|. The number can be used with |c_#<|. + The output can be filtered with |:filter|, e.g.: > + filter /\\.vim/ oldfiles +< The filtering happens on the file name. {not in Vi, only when compiled with the |+eval| feature} -:ol[dfiles] {pat} -:ol[dfiles] /{pat}/ - Like `:oldfiles` but only files matching {pat} will - be included. {pat} is a Vim search pattern. Instead - of enclosing it in / any non-ID character (see - |'isident'|) can be used, so long as it does not - appear in {pat}. Without the enclosing character the - pattern cannot include the bar character. - :bro[wse] ol[dfiles][!] List file names as with |:oldfiles|, and then prompt for a number. When the number is valid that file from diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -1,4 +1,4 @@ -*various.txt* For Vim version 7.4. Last change: 2016 Jul 29 +*various.txt* For Vim version 7.4. Last change: 2016 Aug 23 VIM REFERENCE MANUAL by Bram Moolenaar @@ -524,6 +524,25 @@ N *+X11* Unix only: can restore window :redi[r] END End redirecting messages. {not in Vi} + *:filt* *:filter* +:filt[er] {pat} {command} +:filt[er] /{pat}/ {command} + Restrict the output of {command} to matches with {pat}. + + {pat} is a Vim search pattern. Instead of enclosing + it in / any non-ID character (see |'isident'|) can be + used, so long as it does not appear in {pat}. Without + the enclosing character the pattern cannot include the + bar character. + + The pattern is matched against the relevant part of + the output, not necessarily the whole line. Only some + commands support filtering, try it out to check if it + works. + + Only normal messages are filtered, error messages are + not. + *:sil* *:silent* *:silent!* :sil[ent][!] {command} Execute {command} silently. Normal messages will not be given or added to the message history. diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -2072,6 +2072,7 @@ test_arglist \ test_farsi \ test_feedkeys \ test_file_perm \ + test_filter_cmd \ test_filter_map \ test_fnamemodify \ test_glob2regpat \ diff --git a/src/ex_cmds.h b/src/ex_cmds.h --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -544,6 +544,9 @@ EX(CMD_files, "files", buflist_list, EX(CMD_filetype, "filetype", ex_filetype, EXTRA|TRLBAR|CMDWIN, ADDR_LINES), +EX(CMD_filter, "filter", ex_wrongmodifier, + NEEDARG|EXTRA|NOTRLCOM, + ADDR_LINES), EX(CMD_find, "find", ex_find, RANGE|NOTADR|BANG|FILE1|EDITCMD|ARGOPT|TRLBAR, ADDR_LINES), @@ -992,7 +995,7 @@ EX(CMD_open, "open", ex_open, RANGE|BANG|EXTRA, ADDR_LINES), EX(CMD_oldfiles, "oldfiles", ex_oldfiles, - BANG|TRLBAR|NOTADR|EXTRA|SBOXOK|CMDWIN, + BANG|TRLBAR|SBOXOK|CMDWIN, ADDR_LINES), EX(CMD_omap, "omap", ex_map, EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN, diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1781,6 +1781,7 @@ do_one_cmd( linenr_T lnum; long n; 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; @@ -1917,6 +1918,24 @@ do_one_cmd( 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; + 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)) @@ -2041,6 +2060,7 @@ do_one_cmd( } break; } + after_modifier = ea.cmd; #ifdef FEAT_EVAL ea.skip = did_emsg || got_int || did_throw || (cstack->cs_idx >= 0 @@ -2374,7 +2394,14 @@ do_one_cmd( { STRCPY(IObuff, _("E492: Not an editor command")); if (!sourcing) - append_command(*cmdlinep); + { + /* If the modifier was parsed OK the error must be in the + * following command */ + if (after_modifier != NULL) + append_command(after_modifier); + else + append_command(*cmdlinep); + } errormsg = IObuff; did_emsg_syntax = TRUE; } @@ -2818,6 +2845,7 @@ do_one_cmd( case CMD_echomsg: case CMD_echon: case CMD_execute: + case CMD_filter: case CMD_help: case CMD_hide: case CMD_ijump: @@ -2989,6 +3017,8 @@ doend: free_string_option(cmdmod.save_ei); } #endif + if (cmdmod.filter_regmatch.regprog != NULL) + vim_regfree(cmdmod.filter_regmatch.regprog); cmdmod = save_cmdmod; @@ -3323,6 +3353,7 @@ static struct cmdmod {"botright", 2, FALSE}, {"browse", 3, FALSE}, {"confirm", 4, FALSE}, + {"filter", 4, FALSE}, {"hide", 3, FALSE}, {"keepalt", 5, FALSE}, {"keepjumps", 5, FALSE}, @@ -3833,6 +3864,7 @@ set_one_cmd_context( case CMD_cfdo: case CMD_confirm: case CMD_debug: + case CMD_filter: case CMD_folddoclosed: case CMD_folddoopen: case CMD_hide: diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -137,6 +137,11 @@ msg_attr_keep( int retval; char_u *buf = NULL; + /* Skip messages not matching ":filter pattern". + * Don't filter when there is an error. */ + if (!emsg_on_display && message_filtered(s)) + return TRUE; + #ifdef FEAT_EVAL if (attr == 0) set_vim_var_string(VV_STATUSMSG, s, -1); @@ -2150,6 +2155,17 @@ msg_puts_display( } /* + * Return TRUE when ":filter pattern" was used and "msg" does not match + * "pattern". + */ + int +message_filtered(char_u *msg) +{ + return cmdmod.filter_regmatch.regprog != NULL + && !vim_regexec(&cmdmod.filter_regmatch, msg, (colnr_T)0); +} + +/* * Scroll the screen up one line for displaying the next message line. */ static void diff --git a/src/proto/message.pro b/src/proto/message.pro --- a/src/proto/message.pro +++ b/src/proto/message.pro @@ -43,6 +43,7 @@ void msg_puts_title(char_u *s); void msg_puts_long_attr(char_u *longstr, int attr); void msg_puts_long_len_attr(char_u *longstr, int len, int attr); void msg_puts_attr(char_u *s, int attr); +int message_filtered(char_u *msg); void may_clear_sb_text(void); void clear_sb_text(void); void show_sb_text(void); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -571,6 +571,7 @@ typedef struct # ifdef FEAT_AUTOCMD char_u *save_ei; /* saved value of 'eventignore' */ # endif + regmatch_T filter_regmatch; /* set by :filter /pat/ */ } cmdmod_T; #define MF_SEED_LEN 8 diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -13,6 +13,7 @@ source test_expand_dllpath.vim source test_feedkeys.vim source test_fnamemodify.vim source test_file_perm.vim +source test_filter_cmd.vim source test_filter_map.vim source test_glob2regpat.vim source test_goto.vim diff --git a/src/testdir/test_filter_cmd.vim b/src/testdir/test_filter_cmd.vim new file mode 100644 --- /dev/null +++ b/src/testdir/test_filter_cmd.vim @@ -0,0 +1,15 @@ +" Test the :filter command modifier + +func Test_filter() + edit Xdoesnotmatch + edit Xwillmatch + call assert_equal('"Xwillmatch"', substitute(execute('filter willma ls'), '[^"]*\(".*"\)[^"]*', '\1', '')) +endfunc + +func Test_filter_fails() + call assert_fails('filter', 'E471:') + call assert_fails('filter pat', 'E476:') + call assert_fails('filter /pat', 'E476:') + call assert_fails('filter /pat/', 'E476:') + call assert_fails('filter /pat/ asdf', 'E492:') +endfunc diff --git a/src/testdir/test_viminfo.vim b/src/testdir/test_viminfo.vim --- a/src/testdir/test_viminfo.vim +++ b/src/testdir/test_viminfo.vim @@ -476,7 +476,7 @@ func Test_oldfiles() rviminfo! Xviminfo call delete('Xviminfo') - call assert_equal(['1: /tmp/file_one.txt', '2: /tmp/file_two.txt', '3: /tmp/another.txt'], filter(split(execute('oldfile'), "\n"), {i, v -> v =~ '/tmp/'})) - call assert_equal(['1: /tmp/file_one.txt', '2: /tmp/file_two.txt'], filter(split(execute('oldfile file_'), "\n"), {i, v -> v =~ '/tmp/'})) - call assert_equal(['3: /tmp/another.txt'], filter(split(execute('oldfile /another/'), "\n"), {i, v -> v =~ '/tmp/'})) + call assert_equal(['1: /tmp/file_one.txt', '2: /tmp/file_two.txt', '3: /tmp/another.txt'], filter(split(execute('oldfiles'), "\n"), {i, v -> v =~ '/tmp/'})) + call assert_equal(['1: /tmp/file_one.txt', '2: /tmp/file_two.txt'], filter(split(execute('filter file_ oldfiles'), "\n"), {i, v -> v =~ '/tmp/'})) + call assert_equal(['3: /tmp/another.txt'], filter(split(execute('filter /another/ oldfiles'), "\n"), {i, v -> v =~ '/tmp/'})) endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2244, +/**/ 2243, /**/ 2242,