'paragraphexpr' ハック

'indentexpr' を真似てオプション 'paragraphexpr' でユーザが設定した式に
よってパラグラフの境界を判定できるようにしたハック。
まずはパラグラフの境界を判定している関数 startPS() に独自の関数
startPS_indentexpr() の呼び出しを加える。
startPS_indentexpr() は get_expr_indent() を真似て
内部変数 v:lnum に行番号を入れたのち、
カレントバッファの b_p_paragraphexpr を評価している。

--- ../src.orig/search.c	Fri May  5 21:12:13 2006
+++ search.c	Sat Jul 22 19:15:29 2006
@@ -2665,12 +2665,28 @@
     return (macro[0] != NUL);
 }
 
+    int
+startPS_indentexpr(lnum)
+    linenr_T	lnum;
+{
+    int r;
+
+    set_vim_var_nr(VV_LNUM, lnum);
+    r = eval_to_number(curbuf->b_p_paragraphexpr);
+    
+    if (r < 0) {
+	return 0;
+    }
+
+    return 1;
+}
+
 /*
  * startPS: return TRUE if line 'lnum' is the start of a section or paragraph.
  * If 'para' is '{' or '}' only check for sections.
  * If 'both' is TRUE also stop at '}'
  */
-    int
+int
 startPS(lnum, para, both)
     linenr_T	lnum;
     int		para;
@@ -2682,10 +2698,16 @@
     if (*s == para || *s == '\f' || (both && *s == '}'))
 	return TRUE;
     if (*s == '.' && (inmacro(p_sections, s + 1) ||
-					   (!para && inmacro(p_para, s + 1))))
+		      (!para && inmacro(p_para, s + 1))))
+	return TRUE;
+    //if (linewhite(lnum))
+    //return TRUE;
+    if (startPS_indentexpr(lnum))
 	return TRUE;
+
     return FALSE;
 }
+
 
 /*
  * The following routines do the word searches performed by the 'w', 'W',

バッファ毎に作られる構造体 buf_T に以下を追加(structs.h)。

1374a1375
>     char_u	*b_p_paragraphexpr; /* 'paragraphexpr' */

option.c にてオプション 'paragraphexpr'を定義。
これもそっくり 'indentexpr' を真似た。
この辺はアルファベット順になっていなければいけなかったりする可能性があるので注意。

121a122
> #define PV_PARA		OPT_BUF(BV_PARA)
310a312
> static char_u	*p_paragraphexpr;
1827a1830,1832
>     {"paragraphexpr", NULL,  P_STRING|P_ALLOCED|P_VI_DEF|P_VIM,
> 	(char_u *)&p_paragraphexpr, PV_PARA,
> 	    {(char_u *)"", (char_u *)0L}},
5068a5074
>     check_string_option(&buf->b_p_paragraphexpr);
5213a5220
> // オプション "opt_idx" のフラグ P_INSECURE に使われるフラグへのポインタを取得する
5243a5251
> 	    case  PV_PARA:	return &curbuf->b_p_paragraphexpr;
5244a5253
> 
9051a9061
> 	case PV_PARA:	return (char_u *)&(curbuf->b_p_paragraphexpr); 
9260a9271
> // オプションのグローバル値をバッファローカル値にコピーする
9421a9433
> 	    buf->b_p_paragraphexpr = vim_strsave(p_paragraphexpr);

ちなみにオプション構造体は↓のようになっている。
indir の意味がよくわからないが、バッファローカルオプションが設定されていなかったとき
の振るまいに関係するよう。

struct vimoption
{
    char	*fullname;	/* full option name */
    char	*shortname;	/* permissible abbreviation */
    long_u	flags;		/* see below */
    char_u	*var;		/* global option: pointer to variable;
				 * window-local option: VAR_WIN;
				 * buffer-local option: global value */
    idopt_T	indir;		/* global option: PV_NONE;
				 * local option: indirect option index */
    char_u	*def_val[2];	/* default values for variable (vi and vim) */
#ifdef FEAT_EVAL
    scid_T	scriptID;	/* script in which the option was last set */
#endif
};

option.h

934a942
>     , BV_PARA

buffer.h

1701a1702
>     clear_string_option(&buf->b_p_paragraphexpr);

'paragraphexpr' の設定例

set paragraphexpr=IsStartParagraph(v:lnum)
function! IsStartParagraph(num)
	let l = getline(a:num)
	if l =~ "^\\s*$" 
		    
		return 1
	endif
	return 0
endfunc

今回はハックの練習としてオプションを追加してみたが、これくらいの変更なら

nnoremap { /^\s*$<CR>
nnoremap } /^\s*$<CR>

で十分だった。