から:help 'foldexpr'
:
折れ線のレベルを取得するために、ラインごとに評価されます
foldexpr
それはVIMLコードにする必要があるので、評価されます。「特別な構文」などについての言及はありません。この評価の結果は、Vimがフォールドと見なすかどうかを制御します。
可能な値は
0 the line is not in a fold
1, 2, .. the line is in a fold with this level
"<1", "<2", .. a fold with this level ends at this line
">1", ">2", .. a fold with this level starts at this line
これは完全なリストではありません。質問の例で使用されているものだけです。:help foldexpr
完全なリストについては、を参照してください。
最初
最初の1つは、スペースを追加し、これを:set
コマンドで機能させるために必要なバックスラッシュを削除すると、かなり単純になります。
getline(v:lnum)[0] == "\t"
getline(v:lnum)
行全体を取得します。
[0]
その最初の文字を取得します
- そして
== "\t"
、それがタブ文字かどうかをチェックします。
- VimLには「true」または「false」はありません。falseの場合は「0」、trueの場合は「1」のみを使用します。したがって、この行がタブで始まる場合は、foldlevel 1で折りたたまれます。そうでない場合は、折りたたまれていません(0)。
これを展開してタブの数を数えると、インデントに基づく折りたたみexpandtab
が可能になります(少なくとも、これが有効になっていない場合)。
第三
3番目のものは、最初のものほど複雑ではありません。最初の例と同様に、まず読みやすくします。
getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
- ライン全体を取得します
getline(v:lnum)
- これを正規表現として
=~
to と照合し'^\s*$'
ます。^
先頭へのアンカー\s
、空白文字、*
前の0回以上の繰り返し$
、最後へのアンカーを意味します。したがって、この正規表現は、空白行または空白のみの行に一致します(trueを返します)。
getline(v:lnum + 1)
次の行を取得します。
- これを
\S
に一致させます。これは、この行の任意の場所の空白以外の文字に一致します。
- これらの2つの条件に該当する場合は、と評価され
<1
、そうでない場合はと評価されます1
。これはif
、Cおよび他のいくつかの言語で知られている「3項」を使用して行われ ますcondition ? return_if_true : return_if_false
。
<1
折り目はこの行で終わり、折り目1
レベルは1 であることを意味します。
そのため、行が空白で次の行が空白でない場合に折りを終了すると、それ以外の場合は、foldlevel 1になります。または、次のように言います。:h foldexpr
これは空白行で区切られた段落を折りたたみます
第4
4番目の動作は3番目の動作と同じですが、動作が少し異なります。展開すると、次のようになります。
getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1
場合は、前の行が空白行で、現在の行は非空白行で、我々は、この行に折り目を開始(>1
)されていない場合、我々は1に折り畳みレベルを設定しています。
あとがき
したがって、3つすべての例のロジックは非常に単純です。困難のほとんどは、スペースの不足とバックスラッシュの使用の一部にあります。
関数の呼び出しにはある程度のオーバーヘッドがあると思います。これはすべての行に対して評価されるため、適切なパフォーマンスを得たいと考えています。しかし、最近のマシンでどれほど大きな違いがあるかはわかりません。パフォーマンスの問題がない限り、関数(2番目の例のように)を使用することをお勧めします。Knuthを思い出してください:「時期尚早な最適化はすべての悪の根源です」。
この質問はStackOverflowにもありますが、答えは少し異なります。しかし、私はもちろんより良いです;-)