Od :help 'foldexpr'
:
Jest oceniany dla każdej linii w celu uzyskania poziomu zagięcia
foldexpr
Jest oceniany, więc to musi być kod VimL; nie ma wzmianki o „specjalnej składni” lub podobnej. Wynik tej oceny kontroluje to, co Vim uważa za pasowanie, czy nie.
Możliwe wartości to
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
To nie jest pełna lista; tylko te użyte w przykładach w twoim pytaniu. Zobacz :help foldexpr
pełną listę.
Pierwszy
Pierwszy z nich jest dość prosty po dodaniu spacji i usunięciu ukośników odwrotnych potrzebnych do uruchomienia tego :set
polecenia:
getline(v:lnum)[0] == "\t"
getline(v:lnum)
pobiera całą linię.
[0]
dostaje pierwszą tego postać
- i
== "\t"
sprawdza, czy jest to znak tabulacji.
- VimL nie ma „true” ani „false”, po prostu używa „0” dla false i „1” dla true. Więc jeśli ta linia zaczyna się od tabulatora, jest składana na foldlevel 1. Jeśli nie, to nie jest ona składana (0).
Jeśli rozwinąłbyś to, by policzyć liczbę zakładek, miałbyś składanie oparte na wcięciach (przynajmniej wtedy, gdy expandtab
nie jest włączone).
Trzeci
Trzeci nie jest tak naprawdę bardziej skomplikowany niż pierwszy; tak jak w pierwszym przykładzie, najpierw chcemy, aby był bardziej czytelny:
getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
- Otrzymujemy całą linię
getline(v:lnum)
- Dopasowujemy to jako wyrażenie regularne
=~
do do '^\s*$'
; ^
zakotwiczenia na początku, \s
oznacza dowolny znak spacji, *
oznacza powtórzenie poprzedniego zero lub więcej razy i $
zakotwiczenie na końcu. Tak więc wyrażenie regularne dopasowuje (zwraca true) dla pustych linii lub linii tylko z białymi spacjami.
getline(v:lnum + 1)
dostaje następną linię.
\S
Dopasowujemy to do , co odpowiada dowolnemu znakowi spoza dowolnego miejsca w tym wierszu.
- Jeśli te 2 warunki są prawdziwe, oceniamy
<1
, w przeciwnym razie 1
. Odbywa się to z „trójskładnikowego” if
znanego z C oraz niektórych innych językach: condition ? return_if_true : return_if_false
.
<1
oznacza, 1
że zakładka kończy się na tej linii, i oznacza zakładkę pierwszego poziomu.
Więc jeśli zakończymy pas, jeśli linia jest pusta, a następna linia nie będzie pusta. W przeciwnym razie jesteśmy na foldlevel 1. Lub, jak :h foldexpr
to mówi:
Spowoduje to, że składanie akapitów zostanie oddzielone pustymi liniami
Czwarty
Czwarty zachowuje się tak samo jak trzeci, ale robi to w nieco inny sposób. Rozszerzony, to:
getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1
Jeśli poprzednia linia jest pustą linią, a bieżąca linia jest >1
niepustą linią, rozpoczynamy składanie na tej linii ( ), jeśli nie, ustawiamy poziom foldelowania na 1.
Posłowie
Logika wszystkich 3 przykładów jest naprawdę bardzo prosta. Większość trudności wynika z braku spacji i użycia odwrotnego ukośnika.
Podejrzewam, że wywołanie funkcji ma pewne obciążenie, a ponieważ jest to oceniane dla każdej linii, chcesz mieć przyzwoitą wydajność. Nie wiem jednak, jak duża jest różnica na nowoczesnych komputerach, i zaleciłbym użycie funkcji (jak w drugim przykładzie), chyba że masz problemy z wydajnością. Pamiętajmy o Knutcie: „przedwczesna optymalizacja jest źródłem wszelkiego zła” .
To pytanie dotyczy także StackOverflow , który ma nieco inną odpowiedź. Ale mój jest oczywiście lepszy ;-)