fFtT で現在行を飛び出て探しに行くハック

http://www.k3.dion.ne.jp/~jod/viusage.html

f (character-in-line-forward-search)
現在行の指定文字まで移動。Emacs の viper-modeでは現在段落内の指定文字まで移動らしい。確かに、現在行だけに制限する理由は特に考えられない。

現在行だけに制限する理由が特に考えられないので、指定した文字をバッファの末尾まで探しにいくようにしてみた。ちゃんと動くと思う。

--- ../src.orig/search.c	2006-05-05 21:12:13.001000000 +0900
+++ search.c	2006-08-14 17:47:08.593750000 +0900
@@ -1435,6 +1435,7 @@
     int			col;
     char_u		*p;
     int			len;
+    int                 moveline = 0;
 #ifdef FEAT_MBYTE
     static char_u	bytes[MB_MAXBYTES];
     static int		bytelen = 1;	/* >1 for multi-byte char */
@@ -1482,6 +1483,7 @@
 
     while (count--)
     {
+NEXT_LINE:
 #ifdef FEAT_MBYTE
 	if (has_mbyte)
 	{
@@ -1490,13 +1492,42 @@
 		if (dir > 0)
 		{
 		    col += (*mb_ptr2len)(p + col);
-		    if (col >= len)
-			return FAIL;
+		    if (col >= len) {
+                        moveline += dir;
+                        if (curwin->w_cursor.lnum + moveline > curbuf->b_ml.ml_line_count)	/* invalid line number */ {
+                            return FAIL;
+                        }
+                        else {
+                            p = ml_get_buf(curbuf, curwin->w_cursor.lnum + moveline, FALSE);
+                            col = -(*mb_ptr2len)(p + 0);
+                            len = (int)STRLEN(p);
+                            goto NEXT_LINE;
+                        }
+                    }
 		}
 		else
 		{
-		    if (col == 0)
-			return FAIL;
+		    if (col == 0) {
+                        moveline += -1;
+                        if (curwin->w_cursor.lnum + moveline <= 0) {
+                            return FAIL;
+                        }
+                        else {
+                            p = ml_get_buf(curbuf, curwin->w_cursor.lnum + moveline, FALSE);
+                            len = (int)STRLEN(p);
+                            {
+                                pos_T pos;
+
+                                pos = curwin->w_cursor;
+                                pos.lnum += moveline;
+                                pos.col = len > 1 ? len - 1 : 1;
+                                mb_adjustpos(&pos);
+
+                                col = pos.col; 
+                            }
+                            goto NEXT_LINE;
+                        }
+                    }
 		    col -= (*mb_head_off)(p, p + col - 1) + 1;
 		}
 		if (bytelen == 1)
@@ -1516,8 +1547,23 @@
 	{
 	    for (;;)
 	    {
-		if ((col += dir) < 0 || col >= len)
-		    return FAIL;
+		if ((col += dir) < 0 || col >= len) {
+                    moveline += dir;
+                    if (curwin->w_cursor.lnum + moveline > curbuf->b_ml.ml_line_count)	/* invalid line number */ {
+                        break;
+                    }
+                    else if (curwin->w_cursor.lnum + moveline <= 0) {
+                        break;
+                    }
+                    else {
+                        p = ml_get_buf(curbuf, curwin->w_cursor.lnum + moveline, FALSE);
+                        len = (int)STRLEN(p);
+                        curwin->w_cursor.lnum += moveline;
+                        col = getvpos(&curwin->w_cursor, (colnr_T)MAXCOL);
+                        curwin->w_cursor.lnum -= moveline;
+                        goto NEXT_LINE;
+                    }
+                }
 		if (p[col] == c)
 		    break;
 	    }
@@ -1540,6 +1586,8 @@
 	}
 #endif
     }
+    curwin->w_cursor.lnum += moveline;
+    // cursor_down(moveline, FALSE);
     curwin->w_cursor.col = col;
 
     return OK;

[追記:2006-08-24]
f のとき1桁目の文字に止まらないのを修正。


メモ:
pos_T の lnum は1以上、col は0以上らしい。

/*
 * position in file or buffer
 */
typedef struct
{
    linenr_T	lnum;	/* line number */
    colnr_T	col;	/* column number */
#ifdef FEAT_VIRTUALEDIT
    colnr_T	coladd;
#endif
} pos_T;

curwin->w_curswant が次のフレーム(というのか?)にあってほしいカーソル位置を保持するようだが、どこでそれを実際のカーソル位置に反映させているのかわからない。