Von :help 'foldexpr'
:
Es wird für jede Linie ausgewertet, um ihre Falzstufe zu erhalten
Das foldexpr
wird ausgewertet, daher muss es sich um VimL-Code handeln. "spezielle Syntax" oder ähnliches wird nicht erwähnt. Das Ergebnis dieser Bewertung steuert, was Vim als Falte ansieht oder nicht.
Mögliche Werte sind
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
Dies ist nicht die vollständige Liste; nur die in den Beispielen in Ihrer Frage verwendeten. Siehe :help foldexpr
für die vollständige Liste.
Zuerst
Der erste ist ziemlich einfach, wenn wir einige Leerzeichen hinzufügen und die Backslashes entfernen, die wir benötigen, damit dies in einem :set
Befehl funktioniert :
getline(v:lnum)[0] == "\t"
getline(v:lnum)
bekommt die ganze Zeile.
[0]
bekommt den ersten Charakter davon
- und
== "\t"
prüft, ob dies ein Tabulatorzeichen ist.
- VimL hat nicht "true" oder "false", sondern verwendet nur "0" für "false" und "1" für "true". Wenn diese Zeile also mit einem Tab beginnt, wird sie auf Faltebene 1 gefaltet. Wenn dies nicht der Fall ist, befindet sie sich nicht in einer Falte (0).
Wenn Sie dies erweitern würden, um die Anzahl der Registerkarten zu zählen , hätten Sie einrückungsbasiertes Falten (zumindest, wenn expandtab
es nicht aktiviert ist).
Dritte
Der dritte ist wirklich nicht viel komplizierter als der erste; Wie beim ersten Beispiel möchten wir es zunächst lesbarer machen:
getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
- Wir bekommen die ganze Linie mit
getline(v:lnum)
- Wir stimmen das als regulären Ausdruck mit
=~
zu '^\s*$'
; ^
Anker am Anfang, \s
bedeutet ein beliebiges Leerzeichen, *
bedeutet, dass die vorherigen null oder mehrmals wiederholt werden, und $
Anker am Ende. Dieser reguläre Ausdruck entspricht also (gibt true zurück) für leere Zeilen oder Zeilen mit nur Leerzeichen.
getline(v:lnum + 1)
bekommt die nächste Zeile.
- Wir passen dies an
\S
, was mit jedem Nicht-Leerzeichen irgendwo in dieser Zeile übereinstimmt.
- Wenn diese beiden Bedingungen zutreffen, bewerten wir
<1
andernfalls 1
. Dies geschieht mit dem if
aus C und einigen anderen Sprachen bekannten "ternären" : condition ? return_if_true : return_if_false
.
<1
bedeutet, dass eine Falte auf dieser Linie endet und 1
eine Faltebene bedeutet.
Wenn wir also eine Falte beenden, wenn die Zeile leer ist und die nächste Zeile nicht leer ist. Ansonsten sind wir auf Foldlevel 1. Oder, wie :h foldexpr
es heißt:
Dadurch werden Absätze gefaltet, die durch Leerzeilen getrennt sind
Vierte
Der vierte verhält sich genauso wie der dritte, macht es aber etwas anders. Erweitert ist es:
getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1
Wenn die vorherige Zeile eine leere Zeile ist und die aktuelle Zeile eine nicht leere Zeile ist, beginnen wir eine Falte in dieser Zeile ( >1
). Wenn nicht, setzen wir die Falzstufe auf 1.
Nachwort
Die Logik aller drei Beispiele ist also sehr einfach. Die größte Schwierigkeit ergibt sich aus dem Platzmangel und der Verwendung von Backslashs.
Ich vermute, dass das Aufrufen einer Funktion einen gewissen Overhead hat, und da dies für jede Zeile ausgewertet wird, möchten Sie eine anständige Leistung erzielen. Ich weiß jedoch nicht, wie groß der Unterschied bei modernen Maschinen ist, und würde empfehlen, dass Sie eine Funktion (wie im zweiten Beispiel) verwenden, es sei denn, Sie haben Leistungsprobleme. Denken Sie an The Knuth: "Vorzeitige Optimierung ist die Wurzel allen Übels" .
Diese Frage bezieht sich auch auf StackOverflow , das eine etwas andere Antwort hat. Aber meins ist natürlich besser ;-)