fold-expr을 작성하는 방법?


10

fold-expr ( :h fold-expr) 에 대한 도움말 페이지를 읽었 지만 표현식에 사용 된 구문이 무엇인지 설명하지 않았습니다.

네 가지 예가있었습니다.

  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:lnumindention level을 필요로하는 행이고, expression 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전체 목록을 참조하십시오 .


먼저

첫 번째는 공백을 추가하고 :set명령 에서이 작업을 수행하는 데 필요한 백 슬래시를 제거하면 상당히 간단합니다 .

getline(v:lnum)[0] == "\t"
  1. getline(v:lnum) 전체 라인을 가져옵니다.
  2. [0] 그 첫 번째 문자를 가져옵니다
  3. == "\t"확인이 탭 문자 인 경우.
  4. VimL에는 "true"또는 "false"가 없으며 "0"을 false로, "1"을 true로 사용합니다. 따라서이 선이 탭으로 시작하면 접힘 선 1로 접 힙니다. 그렇지 않으면 접힘 선 (0)이 아닙니다.

이 탭을 확장하여 들여 쓰기 기반 접기 (적어도 사용하지 않는 경우) 가 있는 탭 수 를 계산 합니다 expandtab.


제삼

세 번째는 실제로 첫 번째만큼 그리 복잡하지 않습니다. 첫 번째 예제와 마찬가지로 먼저 더 읽기 쉽게 만들고 싶습니다.

getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
  1. 우리는 전체 라인을 얻을 getline(v:lnum)
  2. 우리와 정규 표현식으로 일치 =~하는 '^\s*$'; ^시작점에 고정, \s공백 문자를 *의미하고, 이전 0 번 이상 반복 $하고 끝까지 고정 함을 의미합니다. 따라서이 정규 표현식은 빈 줄이나 공백 만있는 줄과 일치합니다 (참을 반환합니다) .
  3. getline(v:lnum + 1)다음 줄을 가져옵니다 .
  4. 우리는 \S이것을이 줄의 어디에서나 공백이 아닌 문자와 일치시킵니다.
  5. 이 두 가지 조건이 충족되면로 평가하고 <1그렇지 않으면로 평가합니다 1. 이것은 ifC와 다른 언어로 알려진 "삼원" 으로 수행됩니다 condition ? return_if_true : return_if_false.
  6. <1이 줄에서 접기가 끝나고 접기 11을 의미합니다.

따라서 줄이 비어 있고 다음 줄이 비어 있지 않으면 접기를 냅니다 . 그렇지 않으면, 우리는 폴더 레벨 1에 있습니다.:h foldexpr

빈 줄로 구분 된 단락을 접습니다.


네번째

네 번째는 세 번째와 동일하게 동작하지만 약간 다른 방식으로 작동합니다. 확장하면 다음과 같습니다.

getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1

경우 이전 라인은 빈 줄, 그리고 현재 라인이 아닌 빈 줄, 우리는이 라인 (에 접어 시작 >1, 우리가 1로 foldlevel을 설정하는하지 않을 경우).


따라서 세 가지 예의 논리는 매우 간단합니다. 대부분의 어려움은 공간 부족과 일부 백 슬래시 사용에 있습니다.

함수 호출에 약간의 오버 헤드가 있다고 생각합니다. 이는 적절한 성능을 원하는 모든 라인에 대해 평가되기 때문에. 현대 기계의 차이점이 얼마나 큰지 잘 모르겠으며 성능 문제가 없으면 함수를 사용하는 것이 좋습니다 (두 번째 예와 같이). 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

실수로 내 답변을 의견으로 게시하고 일찍 제출했습니다. Darn mobile.

내 이해는 표현식이 숫자를 반환해야하며 해당 숫자는 주어진 줄이 접힐 수준을 결정하는 데 사용된다는 것입니다. 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.