Mercurial > vim
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) |