今日の関数 searchit その1 (https://github.com/vim/vim)
search.c
int searchit( win_T *win, /* window to search in; can be NULL for a buffer without a window! */ buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, /* which pattern to use when "pat" is empty */ linenr_T stop_lnum, /* stop after this line number when != 0 */ proftime_T *tm UNUSED) /* timeout limit or NULL */ {
0以外が返ればなら検索成功となります。
search.c
... if (search_regcomp(pat, RE_SEARCH, pat_use, (options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL) { if ((options & SEARCH_MSG) && !rc_did_emsg) EMSG2(_("E383: Invalid search string: %s"), mr_pattern); return FAIL; }
検索パターンのエラーチェックをします。
search.c
do /* loop for count */ { ...
無限ループに入ります。
search.c
if (pos->col == MAXCOL) start_char_len = 0; #ifdef FEAT_MBYTE /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */ //------------------------------ // pos ga max - 2 ika nara //------------------------------ else if (has_mbyte && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count && pos->col < MAXCOL - 2) { //------------------------------ // ptr = buf + col //------------------------------ ptr = ml_get_buf(buf, pos->lnum, FALSE) + pos->col; if (*ptr == NUL) start_char_len = 1; else start_char_len = (*mb_ptr2len)(ptr); } #endif else start_char_len = 1;
今のカーソル位置でstart_char_lenを設定していきます。
カーソル位置がMAXCOLにないかmultibyteの時カーソル位置の文字がNULでないならstart_char_lenは1となります。
このstart_char_lenはextra_colに入れられSEARCH_START(カーソルの位置を検索に含める)オプションのために使われます。
search.c
if (dir == FORWARD) { if (options & SEARCH_START) extra_col = 0; else extra_col = start_char_len; } else { if (options & SEARCH_START) extra_col = start_char_len; else extra_col = 0; }
SEARCH_START(カーソルの位置を検索に含める)オプションがついているなら
検索の方向によってextra_colが0か1に設定されます。
前方検索ならSEARCH_STARTがあるならextra_colに1が入りカーソル位置の文字を飛ばします。
SEARCH_STARTがないならextra_colは0で検索はカーソル位置の文字から始まります。
search.c
start_pos = *pos; /* remember start pos for detecting no match */ found = 0; /* default: not found */ at_first_line = TRUE; /* default: start in first line */ if (pos->lnum == 0) /* correct lnum for when starting in line 0 */ { pos->lnum = 1; pos->col = 0; at_first_line = FALSE; /* not in first line now */ }
検索ループに入る前の変数の初期化です。
search.c
//------------------------------ // imano gyou no search // moshi back de col ga 0 de nainara //------------------------------ if (dir == BACKWARD && start_pos.col == 0 && (options & SEARCH_START) == 0) { lnum = pos->lnum - 1; at_first_line = FALSE; } else lnum = pos->lnum;
lnum(行数)は今のカーソル位置のlnumをとります。
ただ後方検索の時で今のカーソル位置が0でしかもカーソル位置の文字を含めるオプションがついていない時は
lnumをカーソル位置の行の一つ前の行を入れます。そしてat_first_lineにFALSEを入れています。
search.c
for (loop = 0; loop <= 1; ++loop) /* loop twice if 'wrapscan' set */ { for ( ; lnum > 0 && lnum <= buf->b_ml.ml_line_count; lnum += dir, at_first_line = FALSE) // dir ha 1 ka -1 { ...
wrapscanは検索が最後まで行ったらまた最初からもう一度
検索するオプションです。そのために2回ループするようになっています。
その中にもう一つ行を舐めていくループがあります。
lnumが0以上でbufferの行数以下でループが回ります。
dirは前方で1後方検索で-1なのでどちらの方向でもこのループは機能します。
search.c
if (stop_lnum != 0 && (dir == FORWARD ? lnum > stop_lnum : lnum < stop_lnum)) break; #ifdef FEAT_RELTIME /* Stop after passing the "tm" time limit. */ if (tm != NULL && profile_passed_limit(tm)) break; #endif
stop_lnumとタイムリミットがセットされているならチェックします。
search.c
col = at_first_line && (options & SEARCH_COL) ? pos->col : (colnr_T)0;
colの設定をします。at_first_lineがTRUEでカーソル位置の文字を含めるオプションがあるなら
そのままカーソル位置のcolを入れます。
そうでなければ0です。一番最初の行にいる時だけカーソル位置を指定しています。