Automatische Hervorhebung von identischem Linientext

13

Ich habe vor einiger Zeit einen erfahrenen Vim Ninja gesehen, aber ich habe keine Ahnung, ob ich anfangen soll.

A) Gibt es eine Möglichkeit, die Hintergrundfarbe von vims so einzustellen, dass aufeinanderfolgende Zeilen mit identischem Inhalt hervorgehoben werden?

B) Wenn jemand weiß, wie man das macht, wäre es eine nette Änderung, wenn die Hervorhebung in aufeinanderfolgenden Zeilen erfolgt, aber nur das erste Wort (nicht die ganze Zeile) berücksichtigt.

Eine zweite Optimierung, wenn die Hervorhebung auf unterschiedliche Farben konfiguriert werden kann, wird basierend auf der Anzahl der übereinstimmenden Zeilen verwendet (oder Wörter, je nachdem, ob AB aktiv ist). Wir haben also nur zwei aufeinanderfolgende Linien, die dann grün, 3-5 aufeinanderfolgende Linien dann orange, 6+ dann rot sind.

Martin York
quelle
Ähnliches Posting: Falten nach Regex-Suchmuster
Peter Rincker

Antworten:

10

Die folgenden matchSätze scheinen für (A) zu funktionieren:

:syn match Low /\v(.+)\n(\1\n)/
:syn match Medium /\v(.+)\n(\1\n){2,4}/
:syn match Critical /\v(.+)\n(\1\n){5,}/
:hi Critical  ctermfg=red
:hi Medium  ctermfg=yellow
:hi Low  ctermfg=green

Hier scheint die Reihenfolge entscheidend zu sein. Wenn die Lowoder MediumStreichhölzer nachher kommen Critical, wird es durch die lockereren Anforderungen von diesen und ähnlich für Lowwrt subsumiert Medium.

Die Hervorhebung erscheint nicht sofort, nachdem Sie beispielsweise eine dritte oder sechste Dupe-Linie hinzugefügt haben, sondern sobald Sie sich nach dem Hinzufügen ein wenig bewegt haben. Ich bin nicht sicher, was genau das auslöst.

Ich stelle mir für B vor, Sie könnten den regulären Ausdruck ersetzen durch:

/\v(\S+).*\n(\1.*\n)/

Ersetzen Sie im Allgemeinen alles (.*)mit (\S+).*und \1mit \1.*oder was auch immer ein Wort für Sie darstellt.

muru
quelle
Ich gab dieser Antwort das Häkchen, weil ich weiß, wie die Hervorhebung erfolgen soll, die ich benötigte (wie in der Frage ausgedrückt). @ Matts regulärer Ausdruck ist nett, beantwortet aber nicht die eigentliche Frage, die ich gestellt habe (Änderung der Hervorhebung).
Martin York
8

Als Ausgangspunkt sehen Sie hier ein Suchmuster, das mit doppelten Zeilen übereinstimmt (Änderungen in führenden Leerzeichen werden ignoriert):

              \zs                marks start of the pattern. Everything before here will not be highlighted
 ^                               start of the line
  \s*                            leading whitespace
       .\+                       match 1 or more non-newline characters
     \(   \)                     and use parens to capture this in match group 1

            \n                   match the newline character
                 \(        \)\+  1 or more
                      \1         copies of what was in the match group 1
                   \s*  \n       with leading whitespace followed by a newline
/^\s*\(.\+\)\n\zs\(\s*\1\n\)\+   the full regex

:help pattern Hier erfahren Sie mehr darüber, wie Sie solche regulären Ausdrücke erstellen können

:help syntax zeigt Ihnen, wie Sie diesen regulären Ausdruck in etwas verwandeln, das für Sie hervorgehoben wird

Das Schreiben von Syntax-Skripten zu lernen kann schwierig sein. Daher ist es eine gute kurzfristige Lösung, dies im Handumdrehen zu tun, indem Sie sicherstellen 'incsearch', dass die Suchvorgänge hervorgehoben sind, und einen Schlüssel für die oben beschriebene Suche zuordnen, d. Hnnoremap <F5> /^\s*\(.\+\)\n\zs\(\s*\1\n\)\+<CR>

Matt Boehm
quelle
Gibt es eine automatisierte Methode, um den regulären Ausdruck so zu verteilen? Es bietet eine so klare Darstellung.
muru
1
Ich habe es von Hand gemacht. Der einfachste schnelle Weg in vim wäre, etwas yy10pmit der vollen Regex auf der Linie zu machen und dann Teile auszuwählen, die Sie entfernen und treffen möchten r<space>. Vielleicht füge ich einen Befehl für "Alles außer der Auswahl in dieser Zeile durch Leerzeichen ersetzen" hinzu, um die Dinge etwas zu beschleunigen.
Matt Boehm
Beeindruckend! Das ist ein ziemlicher Aufwand!
muru
1
Ich habe eine (wirklich hässliche) Vim-Funktion erstellt, um dies ein bisschen schneller zu machen: gist.github.com/mattboehm/da63a48eedf6f14375aa . Wählen Sie eine Linie aus, drücken Sie ,rund verbinden Sie dann die Linien <space>im normalen / visuellen Modus.
Matt Boehm