To: vim_dev@googlegroups.com Subject: Patch 8.1.0271 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0271 Problem: 'incsearch' doesn't work for :s, :g or :v. Solution: Also use 'incsearch' for other commands that use a pattern. Files: src/ex_getln.c, src/globals.h, src/screen.c, src/testdir/test_search.vim *** ../vim-8.1.0270/src/ex_getln.c 2018-08-10 22:07:28.821903829 +0200 --- src/ex_getln.c 2018-08-11 16:16:52.578317070 +0200 *************** *** 264,274 **** /* * Return TRUE when 'incsearch' highlighting is to be done. */ static int ! do_incsearch_highlighting(int firstc) { ! return p_is && !cmd_silent && (firstc == '/' || firstc == '?'); } /* --- 264,341 ---- /* * Return TRUE when 'incsearch' highlighting is to be done. + * Sets search_first_line and search_last_line to the address range. */ static int ! do_incsearch_highlighting(int firstc, incsearch_state_T *is_state, ! int *skiplen, int *patlen) { ! *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 ! vim_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 = is_state->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; } /* *************** *** 280,293 **** long count, incsearch_state_T *is_state) { int i; pos_T end_pos; struct cmdline_info save_ccline; #ifdef FEAT_RELTIME proftime_T tm; #endif ! if (!do_incsearch_highlighting(firstc)) return; // If there is a character waiting, search and redraw later. --- 347,362 ---- long count, incsearch_state_T *is_state) { + int skiplen, patlen; int i; pos_T end_pos; struct cmdline_info save_ccline; #ifdef FEAT_RELTIME proftime_T tm; #endif + int c; ! if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) return; // If there is a character waiting, search and redraw later. *************** *** 298,309 **** } is_state->incsearch_postponed = FALSE; ! // start at old position ! curwin->w_cursor = is_state->search_start; save_last_search_pattern(); // If there is no command line, don't do anything. ! if (ccline.cmdlen == 0) { i = 0; set_no_hlsearch(TRUE); // turn off previous highlight --- 367,385 ---- } is_state->incsearch_postponed = FALSE; ! if (search_first_line == 0) ! // start at the original cursor position ! curwin->w_cursor = is_state->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(); // If there is no command line, don't do anything. ! if (patlen == 0) { i = 0; set_no_hlsearch(TRUE); // turn off previous highlight *************** *** 322,336 **** #endif if (!p_hls) search_flags += SEARCH_KEEP; ! i = do_search(NULL, firstc, ccline.cmdbuff, count, search_flags, #ifdef FEAT_RELTIME &tm, NULL #else NULL, NULL #endif ); --emsg_off; // if interrupted while searching, behave like it failed if (got_int) { --- 398,421 ---- #endif if (!p_hls) search_flags += SEARCH_KEEP; ! c = ccline.cmdbuff[skiplen + patlen]; ! ccline.cmdbuff[skiplen + patlen] = NUL; ! i = do_search(NULL, firstc == ':' ? '/' : firstc, ! ccline.cmdbuff + skiplen, count, search_flags, #ifdef FEAT_RELTIME &tm, NULL #else NULL, NULL #endif ); + 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) { *************** *** 369,376 **** --- 454,464 ---- // 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. *************** *** 398,422 **** */ static int may_adjust_incsearch_highlighting( ! int firstc, ! long count, incsearch_state_T *is_state, ! int c) { pos_T t; char_u *pat; int search_flags = SEARCH_NOOF; int i; ! if (!do_incsearch_highlighting(firstc)) return OK; ! if (ccline.cmdlen == 0) return FAIL; ! if (firstc == ccline.cmdbuff[0]) pat = last_search_pattern(); else ! pat = ccline.cmdbuff; save_last_search_pattern(); cursor_off(); --- 486,512 ---- */ static int may_adjust_incsearch_highlighting( ! int firstc, ! long count, incsearch_state_T *is_state, ! int c) { + int skiplen, patlen; pos_T t; char_u *pat; int search_flags = SEARCH_NOOF; int i; + int save; ! if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) return OK; ! if (patlen == 0 && ccline.cmdbuff[skiplen] == NUL) return FAIL; ! if (firstc == ccline.cmdbuff[skiplen]) pat = last_search_pattern(); else ! pat = ccline.cmdbuff + skiplen; save_last_search_pattern(); cursor_off(); *************** *** 435,451 **** if (!p_hls) search_flags += SEARCH_KEEP; ++emsg_off; i = searchit(curwin, curbuf, &t, c == Ctrl_G ? FORWARD : BACKWARD, pat, count, search_flags, RE_SEARCH, 0, NULL, NULL); --emsg_off; if (i) { is_state->search_start = is_state->match_start; is_state->match_end = t; is_state->match_start = t; ! if (c == Ctrl_T && firstc == '/') { // Move just before the current match, so that when nv_search // finishes the cursor will be put back on the match. --- 525,544 ---- if (!p_hls) search_flags += SEARCH_KEEP; ++emsg_off; + save = pat[patlen]; + pat[patlen] = NUL; i = searchit(curwin, curbuf, &t, c == Ctrl_G ? FORWARD : BACKWARD, pat, count, search_flags, RE_SEARCH, 0, NULL, NULL); --emsg_off; + pat[patlen] = save; if (i) { is_state->search_start = is_state->match_start; is_state->match_end = t; is_state->match_start = t; ! if (c == Ctrl_T && firstc != '?') { // Move just before the current match, so that when nv_search // finishes the cursor will be put back on the match. *************** *** 493,499 **** static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) { ! if (!do_incsearch_highlighting(firstc)) return FAIL; // Add a character from under the cursor for 'incsearch'. --- 586,594 ---- static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) { ! int skiplen, patlen; ! ! if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) return FAIL; // Add a character from under the cursor for 'incsearch'. *************** *** 507,513 **** // If 'ignorecase' and 'smartcase' are set and the // command line has no uppercase characters, convert // the character to lowercase. ! if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) *c = MB_TOLOWER(*c); if (*c != NUL) { --- 602,608 ---- // If 'ignorecase' and 'smartcase' are set and the // command line has no uppercase characters, convert // the character to lowercase. ! if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen)) *c = MB_TOLOWER(*c); if (*c != NUL) { *** ../vim-8.1.0270/src/globals.h 2018-07-29 16:09:14.644945560 +0200 --- src/globals.h 2018-08-11 15:13:44.359706095 +0200 *************** *** 345,353 **** * 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 int no_smartcase INIT(= FALSE); /* don't use 'smartcase' once */ --- 345,357 ---- * 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 ! #ifdef FEAT_SEARCH_EXTRA ! 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 ! #endif EXTERN int no_smartcase INIT(= FALSE); /* don't use 'smartcase' once */ *** ../vim-8.1.0270/src/screen.c 2018-07-29 17:35:19.493750319 +0200 --- src/screen.c 2018-08-11 15:26:39.760558152 +0200 *************** *** 7892,7897 **** --- 7892,7904 ---- long nmatched; 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: *** ../vim-8.1.0270/src/testdir/test_search.vim 2018-07-14 17:24:57.681329029 +0200 --- src/testdir/test_search.vim 2018-08-11 16:27:47.757683001 +0200 *************** *** 362,367 **** --- 362,419 ---- bw! endfunc + func Cmdline3_prep() + " 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() + set noincsearch + call test_override("char_avail", 0) + bw! + endfunc + + func Test_search_cmdline3s() + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":%s/the\/xxx\", 'tx') + call assert_equal(' 2 xxxe', getline('.')) + + call Cmdline3_cleanup() + endfunc + + func Test_search_cmdline3g() + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":g/the\/d\", 'tx') + call assert_equal(' 3 the theother', getline(2)) + + call Cmdline3_cleanup() + endfunc + + func Test_search_cmdline3v() + if !exists('+incsearch') + return + endif + call Cmdline3_prep() + 1 + call feedkeys(":v/the\/d\", 'tx') + call assert_equal(1, line('$')) + call assert_equal(' 2 the~e', getline(1)) + + call Cmdline3_cleanup() + endfunc + func Test_search_cmdline4() if !exists('+incsearch') return *** ../vim-8.1.0270/src/version.c 2018-08-11 14:41:48.326928864 +0200 --- src/version.c 2018-08-11 16:29:55.060807807 +0200 *************** *** 796,797 **** --- 796,799 ---- { /* Add new patch number below this line */ + /**/ + 271, /**/ -- Every exit is an entrance into something else. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///