diff options
author | Aufar Gilbran <aufargilbran@gmail.com> | 2020-08-10 03:02:54 +0800 |
---|---|---|
committer | Aufar Gilbran <aufargilbran@gmail.com> | 2020-09-11 10:31:41 +0800 |
commit | e8a8b9ed08405c830a049c4e43910c5ce9cdb669 (patch) | |
tree | ade437e15fd6e6b0fd67cea690717d0061385a39 /src | |
parent | 8ac47485777c2eaee9fe7aa93d1ed6c5748d2da9 (diff) | |
download | rneovim-e8a8b9ed08405c830a049c4e43910c5ce9cdb669.tar.gz rneovim-e8a8b9ed08405c830a049c4e43910c5ce9cdb669.tar.bz2 rneovim-e8a8b9ed08405c830a049c4e43910c5ce9cdb669.zip |
vim-patch:8.1.0271: 'incsearch' doesn't work for :s, :g or :v
Problem: 'incsearch' doesn't work for :s, :g or :v.
Solution: Also use 'incsearch' for other commands that use a pattern.
https://github.com/vim/vim/commit/b0acacd767a2b0618a7f3c08087708f4329580d0
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/ex_getln.c | 114 | ||||
-rw-r--r-- | src/nvim/globals.h | 8 | ||||
-rw-r--r-- | src/nvim/screen.c | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_search.vim | 57 |
4 files changed, 169 insertions, 16 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8ef1540737..47bfc89bdf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -271,9 +271,68 @@ static void init_incsearch_state(incsearch_state_T *s) } // Return true when 'incsearch' highlighting is to be done. -static bool do_incsearch_highlighting(int firstc) +// Sets search_first_line and search_last_line to the address range. +static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s, + int *skiplen, int *patlen) { - return p_is && !cmd_silent && (firstc == '/' || firstc == '?'); + *skiplen = 0; + *patlen = ccline.cmdlen; + + if (p_is && !cmd_silent) { + // by default search all lines + search_first_line = 0; + search_last_line = MAXLNUM; + + if (firstc == '/' || firstc == '?') { + return true; + } + if (firstc == ':') { + char_u *cmd = skip_range(ccline.cmdbuff, NULL); + char_u *p; + int delim; + char_u *end; + + if (*cmd == 's' || *cmd == 'g' || *cmd == 'v') { + // Skip over "substitute" to find the pattern separator. + for (p = cmd; ASCII_ISALPHA(*p); p++) {} + if (*p != NUL) { + delim = *p++; + end = skip_regexp(p, delim, p_magic, NULL); + if (end > p) { + char_u *dummy; + exarg_T ea; + pos_T save_cursor = curwin->w_cursor; + + // found a non-empty pattern + *skiplen = (int)(p - ccline.cmdbuff); + *patlen = (int)(end - p); + + // parse the address range + memset(&ea, 0, sizeof(ea)); + ea.line1 = 1; + ea.line2 = 1; + ea.cmd = ccline.cmdbuff; + ea.addr_type = ADDR_LINES; + parse_cmd_address(&ea, &dummy); + curwin->w_cursor = s->search_start; + if (ea.addr_count > 0) { + 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; + } + + curwin->w_cursor = save_cursor; + return true; + } + } + } + } + } + + return false; } // May do 'incsearch' highlighting if desired. @@ -283,8 +342,10 @@ static void may_do_incsearch_highlighting(int firstc, long count, pos_T end_pos; proftime_T tm; searchit_arg_T sia; + int skiplen, patlen; + char_u c; - if (!do_incsearch_highlighting(firstc)) { + if (!do_incsearch_highlighting(firstc, s, &skiplen, &patlen)) { return; } @@ -294,12 +355,20 @@ static void may_do_incsearch_highlighting(int firstc, long count, return; } s->incsearch_postponed = false; - curwin->w_cursor = s->search_start; // start at old position + + if (search_first_line == 0) { + // start at the original cursor position + curwin->w_cursor = s->search_start; + } else { + // start at the first line in the range + curwin->w_cursor.lnum = search_first_line; + curwin->w_cursor.col = 0; + } save_last_search_pattern(); int i; // If there is no command line, don't do anything - if (ccline.cmdlen == 0) { + if (patlen == 0) { i = 0; set_no_hlsearch(true); // turn off previous highlight redraw_all_later(SOME_VALID); @@ -313,11 +382,21 @@ static void may_do_incsearch_highlighting(int firstc, long count, if (!p_hls) { search_flags += SEARCH_KEEP; } + c = ccline.cmdbuff[skiplen + patlen]; + ccline.cmdbuff[skiplen + patlen] = NUL; memset(&sia, 0, sizeof(sia)); sia.sa_tm = &tm; - i = do_search(NULL, firstc, ccline.cmdbuff, count, + i = do_search(NULL, firstc == ':' ? '/' : firstc, + ccline.cmdbuff + skiplen, count, search_flags, &sia); + ccline.cmdbuff[skiplen + patlen] = c; emsg_off--; + if (curwin->w_cursor.lnum < search_first_line + || curwin->w_cursor.lnum > search_last_line) { + // match outside of address range + i = 0; + } + // if interrupted while searching, behave like it failed if (got_int) { (void)vpeekc(); // remove <C-C> from input stream @@ -357,9 +436,12 @@ static void may_do_incsearch_highlighting(int firstc, long count, // Disable 'hlsearch' highlighting if the pattern matches // everything. Avoids a flash when typing "foo\|". + c = ccline.cmdbuff[skiplen + patlen]; + ccline.cmdbuff[skiplen + patlen] = NUL; if (empty_pattern(ccline.cmdbuff)) { set_no_hlsearch(true); } + ccline.cmdbuff[skiplen + patlen] = c; validate_cursor(); // May redraw the status line to show the cursor position. @@ -385,8 +467,9 @@ static void may_do_incsearch_highlighting(int firstc, long count, // Return OK when calling command_line_not_changed. static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s) { + int skiplen, patlen; // Add a character from under the cursor for 'incsearch' - if (!do_incsearch_highlighting(firstc)) { + if (!do_incsearch_highlighting(firstc, s, &skiplen, &patlen)) { return FAIL; } @@ -398,7 +481,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s) // command line has no uppercase characters, convert // the character to lowercase if (p_ic && p_scs - && !pat_has_uppercase(ccline.cmdbuff)) { + && !pat_has_uppercase(ccline.cmdbuff + skiplen)) { *c = mb_tolower(*c); } if (*c != NUL) { @@ -1246,10 +1329,11 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_state_T *s, bool next_match) { - if (!do_incsearch_highlighting(firstc)) { + int skiplen, patlen; + if (!do_incsearch_highlighting(firstc, s, &skiplen, &patlen)) { return OK; } - if (ccline.cmdlen == 0) { + if (patlen == 0 && ccline.cmdbuff[skiplen] == NUL) { return FAIL; } @@ -1259,12 +1343,13 @@ static int may_do_command_line_next_incsearch(int firstc, long count, pos_T t; char_u *pat; int search_flags = SEARCH_NOOF; + char_u save; - if (firstc == ccline.cmdbuff[0]) { + if (firstc == ccline.cmdbuff[skiplen]) { pat = last_search_pattern(); } else { - pat = ccline.cmdbuff; + pat = ccline.cmdbuff + skiplen; } save_last_search_pattern(); @@ -1284,17 +1369,20 @@ static int may_do_command_line_next_incsearch(int firstc, long count, search_flags += SEARCH_KEEP; } emsg_off++; + save = pat[patlen]; + pat[patlen] = NUL; int found = searchit(curwin, curbuf, &t, NULL, next_match ? FORWARD : BACKWARD, pat, count, search_flags, RE_SEARCH, NULL); emsg_off--; + pat[patlen] = save; ui_busy_stop(); if (found) { s->search_start = s->match_start; s->match_end = t; s->match_start = t; - if (!next_match && firstc == '/') { + if (!next_match && firstc != '?') { // move just before the current match, so that // when nv_search finishes the cursor will be // put back on the match diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 91a0eab947..205be4b811 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -353,9 +353,11 @@ EXTERN int t_colors INIT(= 256); // int value of T_CCO // position. Search_match_lines is the number of lines after the match (0 for // a match within one line), search_match_endcol the column number of the // character just after the match in the last line. -EXTERN int highlight_match INIT(= false); // show search match pos -EXTERN linenr_T search_match_lines; // lines of of matched string -EXTERN colnr_T search_match_endcol; // col nr of match end +EXTERN bool highlight_match INIT(= false); // show search match pos +EXTERN linenr_T search_match_lines; // lines of of matched string +EXTERN colnr_T search_match_endcol; // col nr of match end +EXTERN linenr_T search_first_line INIT(= 0); // for :{FIRST},{last}s/pat +EXTERN linenr_T search_last_line INIT(= MAXLNUM); // for :{first},{LAST}s/pat EXTERN int no_smartcase INIT(= false); // don't use 'smartcase' once diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 69de1de6b2..4292ed2865 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -5918,6 +5918,12 @@ next_search_hl ( long nmatched = 0; int save_called_emsg = called_emsg; + // for :{range}s/pat only highlight inside the range + if (lnum < search_first_line || lnum > search_last_line) { + shl->lnum = 0; + return; + } + if (shl->lnum != 0) { // Check for three situations: // 1. If the "lnum" is below a previous match, start a new search. diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 8036dea29f..087a261cca 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -367,6 +367,63 @@ func Test_search_cmdline3() bw! endfunc +func Cmdline3_prep() + throw 'skipped: Nvim does not support test_override()' + " need to disable char_avail, + " so that expansion of commandline works + call test_override("char_avail", 1) + new + call setline(1, [' 1', ' 2 the~e', ' 3 the theother']) + set incsearch +endfunc + +func Cmdline3_cleanup() + throw 'skipped: Nvim does not support test_override()' + set noincsearch + call test_override("char_avail", 0) + bw! +endfunc + +func Test_search_cmdline3s() + throw 'skipped: Nvim does not support test_override()' + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":%s/the\<c-l>/xxx\<cr>", 'tx') + call assert_equal(' 2 xxxe', getline('.')) + + call Cmdline3_cleanup() +endfunc + +func Test_search_cmdline3g() + throw 'skipped: Nvim does not support test_override()' + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":g/the\<c-l>/d\<cr>", 'tx') + call assert_equal(' 3 the theother', getline(2)) + + call Cmdline3_cleanup() +endfunc + +func Test_search_cmdline3v() + throw 'skipped: Nvim does not support test_override()' + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":v/the\<c-l>/d\<cr>", 'tx') + call assert_equal(1, line('$')) + call assert_equal(' 2 the~e', getline(1)) + + call Cmdline3_cleanup() +endfunc + func Test_search_cmdline4() " See test/functional/legacy/search_spec.lua throw 'skipped: Nvim does not support test_override()' |