comparison src/ex_getln.c @ 14515:3648e74dd523 v8.1.0271

patch 8.1.0271: 'incsearch' doesn't work for :s, :g or :v commit https://github.com/vim/vim/commit/b0acacd767a2b0618a7f3c08087708f4329580d0 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Aug 11 16:40:43 2018 +0200 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.
author Christian Brabandt <cb@256bit.org>
date Sat, 11 Aug 2018 16:45:05 +0200
parents 4825955cb706
children 20866abc790b
comparison
equal deleted inserted replaced
14514:7ac24a4dc6ea 14515:3648e74dd523
262 } 262 }
263 } 263 }
264 264
265 /* 265 /*
266 * Return TRUE when 'incsearch' highlighting is to be done. 266 * Return TRUE when 'incsearch' highlighting is to be done.
267 * Sets search_first_line and search_last_line to the address range.
267 */ 268 */
268 static int 269 static int
269 do_incsearch_highlighting(int firstc) 270 do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
270 { 271 int *skiplen, int *patlen)
271 return p_is && !cmd_silent && (firstc == '/' || firstc == '?'); 272 {
273 *skiplen = 0;
274 *patlen = ccline.cmdlen;
275
276 if (p_is && !cmd_silent)
277 {
278 // by default search all lines
279 search_first_line = 0;
280 search_last_line = MAXLNUM;
281
282 if (firstc == '/' || firstc == '?')
283 return TRUE;
284 if (firstc == ':')
285 {
286 char_u *cmd = skip_range(ccline.cmdbuff, NULL);
287 char_u *p;
288 int delim;
289 char_u *end;
290
291 if (*cmd == 's' || *cmd == 'g' || *cmd == 'v')
292 {
293 // Skip over "substitute" to find the pattern separator.
294 for (p = cmd; ASCII_ISALPHA(*p); ++p)
295 ;
296 if (*p != NUL)
297 {
298 delim = *p++;
299 end = skip_regexp(p, delim, p_magic, NULL);
300 if (end > p)
301 {
302 char_u *dummy;
303 exarg_T ea;
304 pos_T save_cursor = curwin->w_cursor;
305
306 // found a non-empty pattern
307 *skiplen = (int)(p - ccline.cmdbuff);
308 *patlen = (int)(end - p);
309
310 // parse the address range
311 vim_memset(&ea, 0, sizeof(ea));
312 ea.line1 = 1;
313 ea.line2 = 1;
314 ea.cmd = ccline.cmdbuff;
315 ea.addr_type = ADDR_LINES;
316 parse_cmd_address(&ea, &dummy);
317 curwin->w_cursor = is_state->search_start;
318 if (ea.addr_count > 0)
319 {
320 search_first_line = ea.line1;
321 search_last_line = ea.line2;
322 }
323 else if (*cmd == 's')
324 {
325 // :s defaults to the current line
326 search_first_line = curwin->w_cursor.lnum;
327 search_last_line = curwin->w_cursor.lnum;
328 }
329
330 curwin->w_cursor = save_cursor;
331 return TRUE;
332 }
333 }
334 }
335 }
336 }
337
338 return FALSE;
272 } 339 }
273 340
274 /* 341 /*
275 * Do 'incsearch' highlighting if desired. 342 * Do 'incsearch' highlighting if desired.
276 */ 343 */
278 may_do_incsearch_highlighting( 345 may_do_incsearch_highlighting(
279 int firstc, 346 int firstc,
280 long count, 347 long count,
281 incsearch_state_T *is_state) 348 incsearch_state_T *is_state)
282 { 349 {
350 int skiplen, patlen;
283 int i; 351 int i;
284 pos_T end_pos; 352 pos_T end_pos;
285 struct cmdline_info save_ccline; 353 struct cmdline_info save_ccline;
286 #ifdef FEAT_RELTIME 354 #ifdef FEAT_RELTIME
287 proftime_T tm; 355 proftime_T tm;
288 #endif 356 #endif
289 357 int c;
290 if (!do_incsearch_highlighting(firstc)) 358
359 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen))
291 return; 360 return;
292 361
293 // If there is a character waiting, search and redraw later. 362 // If there is a character waiting, search and redraw later.
294 if (char_avail()) 363 if (char_avail())
295 { 364 {
296 is_state->incsearch_postponed = TRUE; 365 is_state->incsearch_postponed = TRUE;
297 return; 366 return;
298 } 367 }
299 is_state->incsearch_postponed = FALSE; 368 is_state->incsearch_postponed = FALSE;
300 369
301 // start at old position 370 if (search_first_line == 0)
302 curwin->w_cursor = is_state->search_start; 371 // start at the original cursor position
372 curwin->w_cursor = is_state->search_start;
373 else
374 {
375 // start at the first line in the range
376 curwin->w_cursor.lnum = search_first_line;
377 curwin->w_cursor.col = 0;
378 }
303 save_last_search_pattern(); 379 save_last_search_pattern();
304 380
305 // If there is no command line, don't do anything. 381 // If there is no command line, don't do anything.
306 if (ccline.cmdlen == 0) 382 if (patlen == 0)
307 { 383 {
308 i = 0; 384 i = 0;
309 set_no_hlsearch(TRUE); // turn off previous highlight 385 set_no_hlsearch(TRUE); // turn off previous highlight
310 redraw_all_later(SOME_VALID); 386 redraw_all_later(SOME_VALID);
311 } 387 }
320 // Set the time limit to half a second. 396 // Set the time limit to half a second.
321 profile_setlimit(500L, &tm); 397 profile_setlimit(500L, &tm);
322 #endif 398 #endif
323 if (!p_hls) 399 if (!p_hls)
324 search_flags += SEARCH_KEEP; 400 search_flags += SEARCH_KEEP;
325 i = do_search(NULL, firstc, ccline.cmdbuff, count, search_flags, 401 c = ccline.cmdbuff[skiplen + patlen];
402 ccline.cmdbuff[skiplen + patlen] = NUL;
403 i = do_search(NULL, firstc == ':' ? '/' : firstc,
404 ccline.cmdbuff + skiplen, count, search_flags,
326 #ifdef FEAT_RELTIME 405 #ifdef FEAT_RELTIME
327 &tm, NULL 406 &tm, NULL
328 #else 407 #else
329 NULL, NULL 408 NULL, NULL
330 #endif 409 #endif
331 ); 410 );
411 ccline.cmdbuff[skiplen + patlen] = c;
332 --emsg_off; 412 --emsg_off;
413
414 if (curwin->w_cursor.lnum < search_first_line
415 || curwin->w_cursor.lnum > search_last_line)
416 // match outside of address range
417 i = 0;
333 418
334 // if interrupted while searching, behave like it failed 419 // if interrupted while searching, behave like it failed
335 if (got_int) 420 if (got_int)
336 { 421 {
337 (void)vpeekc(); // remove <C-C> from input stream 422 (void)vpeekc(); // remove <C-C> from input stream
367 else 452 else
368 end_pos = curwin->w_cursor; // shutup gcc 4 453 end_pos = curwin->w_cursor; // shutup gcc 4
369 454
370 // Disable 'hlsearch' highlighting if the pattern matches everything. 455 // Disable 'hlsearch' highlighting if the pattern matches everything.
371 // Avoids a flash when typing "foo\|". 456 // Avoids a flash when typing "foo\|".
457 c = ccline.cmdbuff[skiplen + patlen];
458 ccline.cmdbuff[skiplen + patlen] = NUL;
372 if (empty_pattern(ccline.cmdbuff)) 459 if (empty_pattern(ccline.cmdbuff))
373 set_no_hlsearch(TRUE); 460 set_no_hlsearch(TRUE);
461 ccline.cmdbuff[skiplen + patlen] = c;
374 462
375 validate_cursor(); 463 validate_cursor();
376 // May redraw the status line to show the cursor position. 464 // May redraw the status line to show the cursor position.
377 if (p_ru && curwin->w_status_height > 0) 465 if (p_ru && curwin->w_status_height > 0)
378 curwin->w_redr_status = TRUE; 466 curwin->w_redr_status = TRUE;
396 * or previous match. 484 * or previous match.
397 * Returns FAIL when jumping to cmdline_not_changed; 485 * Returns FAIL when jumping to cmdline_not_changed;
398 */ 486 */
399 static int 487 static int
400 may_adjust_incsearch_highlighting( 488 may_adjust_incsearch_highlighting(
401 int firstc, 489 int firstc,
402 long count, 490 long count,
403 incsearch_state_T *is_state, 491 incsearch_state_T *is_state,
404 int c) 492 int c)
405 { 493 {
494 int skiplen, patlen;
406 pos_T t; 495 pos_T t;
407 char_u *pat; 496 char_u *pat;
408 int search_flags = SEARCH_NOOF; 497 int search_flags = SEARCH_NOOF;
409 int i; 498 int i;
410 499 int save;
411 if (!do_incsearch_highlighting(firstc)) 500
501 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen))
412 return OK; 502 return OK;
413 if (ccline.cmdlen == 0) 503 if (patlen == 0 && ccline.cmdbuff[skiplen] == NUL)
414 return FAIL; 504 return FAIL;
415 505
416 if (firstc == ccline.cmdbuff[0]) 506 if (firstc == ccline.cmdbuff[skiplen])
417 pat = last_search_pattern(); 507 pat = last_search_pattern();
418 else 508 else
419 pat = ccline.cmdbuff; 509 pat = ccline.cmdbuff + skiplen;
420 510
421 save_last_search_pattern(); 511 save_last_search_pattern();
422 cursor_off(); 512 cursor_off();
423 out_flush(); 513 out_flush();
424 if (c == Ctrl_G) 514 if (c == Ctrl_G)
433 else 523 else
434 t = is_state->match_start; 524 t = is_state->match_start;
435 if (!p_hls) 525 if (!p_hls)
436 search_flags += SEARCH_KEEP; 526 search_flags += SEARCH_KEEP;
437 ++emsg_off; 527 ++emsg_off;
528 save = pat[patlen];
529 pat[patlen] = NUL;
438 i = searchit(curwin, curbuf, &t, 530 i = searchit(curwin, curbuf, &t,
439 c == Ctrl_G ? FORWARD : BACKWARD, 531 c == Ctrl_G ? FORWARD : BACKWARD,
440 pat, count, search_flags, 532 pat, count, search_flags,
441 RE_SEARCH, 0, NULL, NULL); 533 RE_SEARCH, 0, NULL, NULL);
442 --emsg_off; 534 --emsg_off;
535 pat[patlen] = save;
443 if (i) 536 if (i)
444 { 537 {
445 is_state->search_start = is_state->match_start; 538 is_state->search_start = is_state->match_start;
446 is_state->match_end = t; 539 is_state->match_end = t;
447 is_state->match_start = t; 540 is_state->match_start = t;
448 if (c == Ctrl_T && firstc == '/') 541 if (c == Ctrl_T && firstc != '?')
449 { 542 {
450 // Move just before the current match, so that when nv_search 543 // Move just before the current match, so that when nv_search
451 // finishes the cursor will be put back on the match. 544 // finishes the cursor will be put back on the match.
452 is_state->search_start = t; 545 is_state->search_start = t;
453 (void)decl(&is_state->search_start); 546 (void)decl(&is_state->search_start);
491 * Return OK when jumping to cmdline_not_changed. 584 * Return OK when jumping to cmdline_not_changed.
492 */ 585 */
493 static int 586 static int
494 may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) 587 may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state)
495 { 588 {
496 if (!do_incsearch_highlighting(firstc)) 589 int skiplen, patlen;
590
591 if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen))
497 return FAIL; 592 return FAIL;
498 593
499 // Add a character from under the cursor for 'incsearch'. 594 // Add a character from under the cursor for 'incsearch'.
500 if (is_state->did_incsearch) 595 if (is_state->did_incsearch)
501 { 596 {
505 *c = gchar_cursor(); 600 *c = gchar_cursor();
506 601
507 // If 'ignorecase' and 'smartcase' are set and the 602 // If 'ignorecase' and 'smartcase' are set and the
508 // command line has no uppercase characters, convert 603 // command line has no uppercase characters, convert
509 // the character to lowercase. 604 // the character to lowercase.
510 if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff)) 605 if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen))
511 *c = MB_TOLOWER(*c); 606 *c = MB_TOLOWER(*c);
512 if (*c != NUL) 607 if (*c != NUL)
513 { 608 {
514 if (*c == firstc || vim_strchr((char_u *)( 609 if (*c == firstc || vim_strchr((char_u *)(
515 p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) 610 p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL)