fold-exprの書き方は?


10

fold-expr(:h fold-expr)に関するヘルプページを読みましたが、式で使用されている構文を説明していません。

4つの例がありました。

  1. :set foldexpr=getline(v:lnum)[0]==\"\\t\"
  2. :set foldexpr=MyFoldLevel(v:lnum)
  3. :set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1
  4. :set foldexpr=getline(v:lnum-1)=~'^\\s*$'&&getline(v:lnum)=~'\\S'?'>1':1

v:lnumそれがインデントレベルを必要とする行であり、式2が関数の呼び出しであることを理解しました。

式1、3、および4はどうですか?誰か私に説明してくれませんか?


私の理解では、式は数値を返す必要があり、その数値は、指定された行が折り返されるレベルを決定するために使用されます。0は折り畳まれていません、1は最も外側の折り畳み、2はレベル1の折り畳みの中に入れ子になっている折り畳みなどです
tommcdo

回答:


12

から: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"
  1. getline(v:lnum) 行全体を取得します。
  2. [0] その最初の文字を取得します
  3. そして== "\t"、それがタブ文字かどうかをチェックします。
  4. VimLには「true」または「false」はありません。falseの場合は「0」、trueの場合は「1」のみを使用します。したがって、この行がタブで始まる場合は、foldlevel 1で折りたたまれます。そうでない場合は、折りたたまれていません(0)。

これを展開してタブの数を数えると、インデントに基づく折りたたみexpandtabが可能になります(少なくとも、これが有効になっていない場合)。


第三

3番目のものは、最初のものほど複雑ではありません。最初の例と同様に、まず読みやすくします。

getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
  1. ライン全体を取得します getline(v:lnum)
  2. これを正規表現として=~to と照合し'^\s*$'ます。^先頭へのアンカー\s、空白文字、*前の0回以上の繰り返し$、最後へのアンカーを意味します。したがって、この正規表現は、空白行または空白のみの行に一致します(trueを返します)。
  3. getline(v:lnum + 1)次の行を取得します。
  4. これを\Sに一致させます。これは、この行の任意の場所の空白以外の文字に一致します。
  5. これらの2つの条件に該当する場合は、と評価され<1、そうでない場合はと評価されます1。これはif、Cおよび他のいくつかの言語で知られている「3項」を使用して行われ ますcondition ? return_if_true : return_if_false
  6. <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にもありますが、答えは少し異なります。しかし、私はもちろんより良いです;-)


3

あなたは本質的にこれらの式の他の要素が何であるかを尋ねています、それ:helpはそれらのいずれかを順番に呼び出すことで見つけることができます:

v:lnum: the line being evaluated
getline(): get the line of text for a line number
==: equals
=~: matches
<cond>?<if-true>:<if-false>: evaluates to <if-true> if <cond> is true, else to <if-false>

これらの表現を以下の部分ごとに分解して、意味を説明します。

1タブで始まるすべての行で1を返し、その他の行で0を返します。

v:lnum                      the current line number
getline(v:lnum)             the text of the current line
getline(v:lnum)[0]          the first character of the current line
getline(v:lnum)[0]==\"\\t\" the first char of the current line is 'tab'

3段落の後の空白行で折り目を終了します。

 getline(v:lnum)=~'^\\s*$'                                       current line is only spaces
                              getline(v:lnum+1)=~'\\S'           next line has non-space
(getline(v:lnum)=~'^\\s*$' && getline(v:lnum+1)=~'\\S') ? '<1'   if both of these: <1
                                                              :1 otherwise: 1
(getline(v:lnum)=~'^\\s*$' && getline(v:lnum+1)=~'\\S') ? '<1':1

4段落から始まる空白行で折り目を開始します。

(getline(v:lnum-1)=~'^\\s*$'                                     previous line only spaces
                                getline(v:lnum)=~'\\S'           this line has non-space
(getline(v:lnum-1)=~'^\\s*$' && getline(v:lnum)=~'\\S') ? '>1'   if both of these: >1
                                                              :1 otherwise: 1
(getline(v:lnum-1)=~'^\\s*$' && getline(v:lnum)=~'\\S') ? '>1':1 

、などの意味は<1>1これらの式のすぐ下にあります:help fold-expr


1

誤って私の回答をコメントとして投稿し、早めに提出しました。くそーモバイル

私の理解では、式は数値を返す必要があり、その数値は、指定された行が折り返されるレベルを決定するために使用されます。0は折りたたまれていません、1は最も外側の折りたたみ、2はレベル1の折りたたみ内にネストされた折りたたみなどです。

例の式は、trueまたはfalseに評価されるように見えます。VimScriptには適切なブール型がないため、これは実際には有効な折り畳みレベルである1または0になります。

VimScriptを使用して、1または0を返すのと同じくらい簡単な、またはより複雑な独自の式を記述して、折りたたみをネストすることができます。


数値のみを使用しても機能しますが、foldexprが=、a1、s1、> 1、<1、-1などのその他の特別な値に評価できることは注目に値します
Matt Boehm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.