Wie richte ich Vim so ein, dass es mit einem Satz pro Zeile arbeitet?

17

Ich schreibe derzeit viel einfachen Text (und LaTeX mit minimaler Formatierung in Absätzen), und es wäre schön, wenn ich vim so einrichten könnte, dass jeder Satz beibehalten wird (der Einfachheit halber wird der Text durch ein '.', '!' , oder '?', das ist eine abschließende Interpunktion, gefolgt von einem Leerzeichen (um das Aufbrechen von Dezimalzahlen zu vermeiden) in einer eigenen Zeile, sodass die VCS-Diffs nützlicher sind.

Zumindest möchte ich gqText formatieren aus:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

Zu:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

Aber es wäre schön, wenn vim diese Formatierung auch während der Eingabe durchführen würde (wie es bei textwidth reflow der Fall ist). Ist das möglich?

Meine aktuelle Lösung ist, einen Absatz mit zu verbinden Jund dann auszuführen, :'<,'>s/\. /.\r/gwas ziemlich gut ist, da es nur wenige Ausrufezeichen und Fragezeichen gibt, aber es wäre viel besser, wenn ich gq etwas schlauer machen könnte.

Alex
quelle

Antworten:

23

Die 'formatexpr'Option

Dies erreichen Sie mit der 'formatexpr'Option. Aus der Hilfe:

Ausdruck, der ausgewertet wird, um einen Zeilenbereich für den gq-Operator oder die automatische Formatierung zu formatieren (siehe 'formatoptions'). Wenn diese Option leer ist, wird 'formatprg' verwendet.

Die 'formatexpr'korrekte Einstellung funktioniert sowohl beim Verwenden gqals auch beim Einfügen von Text.

Ein einfaches Beispiel

Hier ist eine einfache VimScript-Funktion und ein entsprechender 'formatexpr'Wert, der den Job erledigen sollte. Ich habe es nicht an allen Randfällen getestet, aber es hat für meine einfachen Tests gut funktioniert.

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

Erläuterung

Der Ausdruck ruft die Funktion auf MyFormatExpr()und übergibt die Start- und Endzeilen, auf die die Formatierung angewendet wird. Diese Zeilen werden mit den automatisch ausgefüllten Variablen v:lnum(die erste zu formatierende Zeile) und v:count(die Anzahl der zu formatierenden Zeilen) berechnet .

Die MyFormatExpr()Funktion erstellt einen :substituteBefehl mit der im Bereich geführt und ersetzt ein Leerzeichen nach eineine End-of-Satz Satzzeichen ( ., !oder ?) mit einer Neuen - Zeile ( \r).

Vorbehalte

  • Die MyFormatExpr()Funktion behält den führenden Einzug nicht bei. Um dies zu beheben, wäre eine ausgefeiltere Logik erforderlich.
  • Es kann andere Randfälle geben, in denen dies auseinanderfällt. Probieren Sie es aus und optimieren Sie es nach Bedarf!
tommcdo
quelle
Oh ja, das ist der richtige Weg, ignoriere meine Antwort.
Sukima,
Das ist fantastisch! Ich wünschte, ich könnte die Funktion ein Makro ausführen lassen, z. B. "Vorwärts zum nächsten Satz gehen )und eine neue Zeile einfügen. Wiederholen, bis Sie das Ende des Bereichs erreicht haben." Dann würde es vermutlich irgendwelche Einrückungsregeln anwenden. Dafür ist mein Vim-Fu zu schwach. :)
Nathan Long
Das spaltet sich zB auf e.g. blah, und Blah et al. 2018das ist etwas nervig. Sie können solche Muster mit so etwas aufheben 's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'. Fügen Sie der ersten Gruppe einfach weitere Muster hinzu, um andere Dinge zu vermeiden, die Sie nicht aufteilen möchten. Ansonsten ist das super nützlich, danke. Ich war noch nie zuvor darauf gestoßen gqund gqipeignet sich hervorragend zum Formatieren von Text, den die Texteditoren des Mitautors entstellt haben.
Naught101
Gibt es eine Möglichkeit, dieses Verhalten dem Standardverhalten hinzuzufügen? Ich möchte in der Lage sein, einen Zeilenumbruch mit einer bestimmten
Textbreite
1

Nun, Sie können einige Karten und Autobefehle einrichten:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

Stellen Sie dann einfach den Dateityp auf customtxt ein oder rufen Sie die AddSentenceMapsFunktion manuell auf.

Sukima
quelle
0

Ich möchte meine Gedanken zu diesem Thema hinzufügen. Normalerweise möchten Leute diese Art von Funktion, weil sie über umbrochene Zeilen springen, wenn sie mit jund kKommandos durch den Code navigieren, was das Standardverhalten von Vim ist. Für die Navigation durch umbrochene Zeilen verwende ich gj- nach unten und gk- nach oben. Es gibt auch die Möglichkeit, Standard jund kBefehl auf den Gegenstücken mit dem Präfix g neu zuzuordnen , aber meiner Meinung nach wäre es übertrieben.

Alexander Myshov
quelle
oder einen Schlüssel haben, um das Remaping von jund knach gjund gkwann immer Sie wollen zu tun ;-)
anthony
0

Es beantwortet nicht Ihre spezifische Frage zur Neuformatierung, aber 'Zeilenumbruch setzen' zusammen mit 'Zeilenumbruch setzen' kann das Bearbeiten langer Zeilen wesentlich angenehmer machen. Kombinieren Sie dies mit gj und gk, um in umbrochenen Zeilen zu navigieren. Ich ordne die Aufwärts- und Abwärtspfeile gj bzw. gk zu, so dass ich die Wahl habe, ob ich echte Linien oder visuelle Linien nach oben und unten bewegen möchte. Wie weise für Home / End zu g0 / g $.

Drew
quelle