Mercurial > vim
comparison src/evalfunc.c @ 20725:f4455c71a8aa v8.2.0915
patch 8.2.0915: search() cannot skip over matches like searchpair() can
Commit: https://github.com/vim/vim/commit/adc17a5f9d207fd1623fd923457a46efc9214777
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jun 6 18:37:51 2020 +0200
patch 8.2.0915: search() cannot skip over matches like searchpair() can
Problem: Search() cannot skip over matches like searchpair() can.
Solution: Add an optional "skip" argument. (Christian Brabandt, closes https://github.com/vim/vim/issues/861)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 06 Jun 2020 18:45:03 +0200 |
parents | 1af1d8ff2aa8 |
children | ab27db64f1fb |
comparison
equal
deleted
inserted
replaced
20724:b4f459787045 | 20725:f4455c71a8aa |
---|---|
799 {"screenchars", 2, 2, FEARG_1, ret_list_number, f_screenchars}, | 799 {"screenchars", 2, 2, FEARG_1, ret_list_number, f_screenchars}, |
800 {"screencol", 0, 0, 0, ret_number, f_screencol}, | 800 {"screencol", 0, 0, 0, ret_number, f_screencol}, |
801 {"screenpos", 3, 3, FEARG_1, ret_dict_number, f_screenpos}, | 801 {"screenpos", 3, 3, FEARG_1, ret_dict_number, f_screenpos}, |
802 {"screenrow", 0, 0, 0, ret_number, f_screenrow}, | 802 {"screenrow", 0, 0, 0, ret_number, f_screenrow}, |
803 {"screenstring", 2, 2, FEARG_1, ret_string, f_screenstring}, | 803 {"screenstring", 2, 2, FEARG_1, ret_string, f_screenstring}, |
804 {"search", 1, 4, FEARG_1, ret_number, f_search}, | 804 {"search", 1, 5, FEARG_1, ret_number, f_search}, |
805 {"searchcount", 0, 1, FEARG_1, ret_dict_any, f_searchcount}, | 805 {"searchcount", 0, 1, FEARG_1, ret_dict_any, f_searchcount}, |
806 {"searchdecl", 1, 3, FEARG_1, ret_number, f_searchdecl}, | 806 {"searchdecl", 1, 3, FEARG_1, ret_number, f_searchdecl}, |
807 {"searchpair", 3, 7, 0, ret_number, f_searchpair}, | 807 {"searchpair", 3, 7, 0, ret_number, f_searchpair}, |
808 {"searchpairpos", 3, 7, 0, ret_list_number, f_searchpairpos}, | 808 {"searchpairpos", 3, 7, 0, ret_list_number, f_searchpairpos}, |
809 {"searchpos", 1, 4, FEARG_1, ret_list_number, f_searchpos}, | 809 {"searchpos", 1, 5, FEARG_1, ret_list_number, f_searchpos}, |
810 {"server2client", 2, 2, FEARG_1, ret_number, f_server2client}, | 810 {"server2client", 2, 2, FEARG_1, ret_number, f_server2client}, |
811 {"serverlist", 0, 0, 0, ret_string, f_serverlist}, | 811 {"serverlist", 0, 0, 0, ret_string, f_serverlist}, |
812 {"setbufline", 3, 3, FEARG_3, ret_number, f_setbufline}, | 812 {"setbufline", 3, 3, FEARG_3, ret_number, f_setbufline}, |
813 {"setbufvar", 3, 3, FEARG_3, ret_void, f_setbufvar}, | 813 {"setbufvar", 3, 3, FEARG_3, ret_void, f_setbufvar}, |
814 {"setcharsearch", 1, 1, FEARG_1, ret_void, f_setcharsearch}, | 814 {"setcharsearch", 1, 1, FEARG_1, ret_void, f_setcharsearch}, |
6397 long time_limit = 0; | 6397 long time_limit = 0; |
6398 #endif | 6398 #endif |
6399 int options = SEARCH_KEEP; | 6399 int options = SEARCH_KEEP; |
6400 int subpatnum; | 6400 int subpatnum; |
6401 searchit_arg_T sia; | 6401 searchit_arg_T sia; |
6402 evalarg_T skip; | |
6403 pos_T firstpos; | |
6404 | |
6405 CLEAR_FIELD(skip); | |
6402 | 6406 |
6403 pat = tv_get_string(&argvars[0]); | 6407 pat = tv_get_string(&argvars[0]); |
6404 dir = get_search_arg(&argvars[1], flagsp); // may set p_ws | 6408 dir = get_search_arg(&argvars[1], flagsp); // may set p_ws |
6405 if (dir == 0) | 6409 if (dir == 0) |
6406 goto theend; | 6410 goto theend; |
6410 if (flags & SP_END) | 6414 if (flags & SP_END) |
6411 options |= SEARCH_END; | 6415 options |= SEARCH_END; |
6412 if (flags & SP_COLUMN) | 6416 if (flags & SP_COLUMN) |
6413 options |= SEARCH_COL; | 6417 options |= SEARCH_COL; |
6414 | 6418 |
6415 // Optional arguments: line number to stop searching and timeout. | 6419 // Optional arguments: line number to stop searching, timeout and skip. |
6416 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) | 6420 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) |
6417 { | 6421 { |
6418 lnum_stop = (long)tv_get_number_chk(&argvars[2], NULL); | 6422 lnum_stop = (long)tv_get_number_chk(&argvars[2], NULL); |
6419 if (lnum_stop < 0) | 6423 if (lnum_stop < 0) |
6420 goto theend; | 6424 goto theend; |
6425 if (argvars[3].v_type != VAR_UNKNOWN) | |
6426 { | |
6421 #ifdef FEAT_RELTIME | 6427 #ifdef FEAT_RELTIME |
6422 if (argvars[3].v_type != VAR_UNKNOWN) | |
6423 { | |
6424 time_limit = (long)tv_get_number_chk(&argvars[3], NULL); | 6428 time_limit = (long)tv_get_number_chk(&argvars[3], NULL); |
6425 if (time_limit < 0) | 6429 if (time_limit < 0) |
6426 goto theend; | 6430 goto theend; |
6427 } | 6431 #endif |
6428 #endif | 6432 if (argvars[4].v_type != VAR_UNKNOWN |
6433 && evalarg_get(&argvars[4], &skip) == FAIL) | |
6434 goto theend; | |
6435 } | |
6429 } | 6436 } |
6430 | 6437 |
6431 #ifdef FEAT_RELTIME | 6438 #ifdef FEAT_RELTIME |
6432 // Set the time limit, if there is one. | 6439 // Set the time limit, if there is one. |
6433 profile_setlimit(time_limit, &tm); | 6440 profile_setlimit(time_limit, &tm); |
6445 semsg(_(e_invarg2), tv_get_string(&argvars[1])); | 6452 semsg(_(e_invarg2), tv_get_string(&argvars[1])); |
6446 goto theend; | 6453 goto theend; |
6447 } | 6454 } |
6448 | 6455 |
6449 pos = save_cursor = curwin->w_cursor; | 6456 pos = save_cursor = curwin->w_cursor; |
6457 CLEAR_FIELD(firstpos); | |
6450 CLEAR_FIELD(sia); | 6458 CLEAR_FIELD(sia); |
6451 sia.sa_stop_lnum = (linenr_T)lnum_stop; | 6459 sia.sa_stop_lnum = (linenr_T)lnum_stop; |
6452 #ifdef FEAT_RELTIME | 6460 #ifdef FEAT_RELTIME |
6453 sia.sa_tm = &tm; | 6461 sia.sa_tm = &tm; |
6454 #endif | 6462 #endif |
6455 subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L, | 6463 |
6464 // Repeat until {skip} returns FALSE. | |
6465 for (;;) | |
6466 { | |
6467 subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L, | |
6456 options, RE_SEARCH, &sia); | 6468 options, RE_SEARCH, &sia); |
6469 // finding the first match again means there is no match where {skip} | |
6470 // evaluates to zero. | |
6471 if (firstpos.lnum != 0 && EQUAL_POS(pos, firstpos)) | |
6472 subpatnum = FAIL; | |
6473 | |
6474 if (subpatnum == FAIL || !evalarg_valid(&skip)) | |
6475 // didn't find it or no skip argument | |
6476 break; | |
6477 firstpos = pos; | |
6478 | |
6479 // If the skip pattern matches, ignore this match. | |
6480 { | |
6481 int do_skip; | |
6482 int err; | |
6483 pos_T save_pos = curwin->w_cursor; | |
6484 | |
6485 curwin->w_cursor = pos; | |
6486 do_skip = evalarg_call_bool(&skip, &err); | |
6487 curwin->w_cursor = save_pos; | |
6488 if (err) | |
6489 { | |
6490 // Evaluating {skip} caused an error, break here. | |
6491 subpatnum = FAIL; | |
6492 break; | |
6493 } | |
6494 if (!do_skip) | |
6495 break; | |
6496 } | |
6497 } | |
6498 | |
6457 if (subpatnum != FAIL) | 6499 if (subpatnum != FAIL) |
6458 { | 6500 { |
6459 if (flags & SP_SUBPAT) | 6501 if (flags & SP_SUBPAT) |
6460 retval = subpatnum; | 6502 retval = subpatnum; |
6461 else | 6503 else |
6479 curwin->w_cursor = save_cursor; | 6521 curwin->w_cursor = save_cursor; |
6480 else | 6522 else |
6481 curwin->w_set_curswant = TRUE; | 6523 curwin->w_set_curswant = TRUE; |
6482 theend: | 6524 theend: |
6483 p_ws = save_p_ws; | 6525 p_ws = save_p_ws; |
6526 evalarg_clean(&skip); | |
6484 | 6527 |
6485 return retval; | 6528 return retval; |
6486 } | 6529 } |
6487 | 6530 |
6488 #ifdef FEAT_FLOAT | 6531 #ifdef FEAT_FLOAT |