'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>
で十分だった。