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