보낸 사람 :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"
getline(v:lnum)
전체 라인을 가져옵니다.
[0]
그 첫 번째 문자를 가져옵니다
- 및
== "\t"
확인이 탭 문자 인 경우.
- VimL에는 "true"또는 "false"가 없으며 "0"을 false로, "1"을 true로 사용합니다. 따라서이 선이 탭으로 시작하면 접힘 선 1로 접 힙니다. 그렇지 않으면 접힘 선 (0)이 아닙니다.
이 탭을 확장하여 들여 쓰기 기반 접기 (적어도 사용하지 않는 경우) 가 있는 탭 수 를 계산 합니다 expandtab
.
제삼
세 번째는 실제로 첫 번째만큼 그리 복잡하지 않습니다. 첫 번째 예제와 마찬가지로 먼저 더 읽기 쉽게 만들고 싶습니다.
getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
- 우리는 전체 라인을 얻을
getline(v:lnum)
- 우리와 정규 표현식으로 일치
=~
하는 '^\s*$'
; ^
시작점에 고정, \s
공백 문자를 *
의미하고, 이전 0 번 이상 반복 $
하고 끝까지 고정 함을 의미합니다. 따라서이 정규 표현식은 빈 줄이나 공백 만있는 줄과 일치합니다 (참을 반환합니다) .
getline(v:lnum + 1)
다음 줄을 가져옵니다 .
- 우리는
\S
이것을이 줄의 어디에서나 공백이 아닌 문자와 일치시킵니다.
- 이 두 가지 조건이 충족되면로 평가하고
<1
그렇지 않으면로 평가합니다 1
. 이것은 if
C와 다른 언어로 알려진 "삼원" 으로 수행됩니다 condition ? return_if_true : return_if_false
.
<1
이 줄에서 접기가 끝나고 접기 1
1을 의미합니다.
따라서 줄이 비어 있고 다음 줄이 비어 있지 않으면 접기를 끝 냅니다 . 그렇지 않으면, 우리는 폴더 레벨 1에 있습니다.:h foldexpr
빈 줄로 구분 된 단락을 접습니다.
네번째
네 번째는 세 번째와 동일하게 동작하지만 약간 다른 방식으로 작동합니다. 확장하면 다음과 같습니다.
getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1
경우 이전 라인은 빈 줄, 그리고 현재 라인이 아닌 빈 줄, 우리는이 라인 (에 접어 시작 >1
, 우리가 1로 foldlevel을 설정하는하지 않을 경우).
후
따라서 세 가지 예의 논리는 매우 간단합니다. 대부분의 어려움은 공간 부족과 일부 백 슬래시 사용에 있습니다.
함수 호출에 약간의 오버 헤드가 있다고 생각합니다. 이는 적절한 성능을 원하는 모든 라인에 대해 평가되기 때문에. 현대 기계의 차이점이 얼마나 큰지 잘 모르겠으며 성능 문제가 없으면 함수를 사용하는 것이 좋습니다 (두 번째 예와 같이). Knuth를 기억하십시오 : "조기 최적화는 모든 악의 근원" 입니다.
이 질문 은 또한 약간 다른 답변을 가진 StackOverflow 에 있습니다. 그러나 내 것이 물론 더 좋습니다.