Automatyczne wyróżnianie tekstu identycznych linii

13

Jakiś czas temu widziałem, jak wykwalifikowany ninja vim to robi, ale nie mam pojęcia, jak zacząć.

A) Czy istnieje sposób na ustawienie koloru tła vims, aby kolejne linie o identycznej treści były podświetlane.

B) Jeśli ktoś wie, jak to zrobić, fajną poprawką byłoby, gdyby wyróżnianie odbywało się w kolejnych wierszach, ale uwzględniało tylko pierwsze słowo (nie całą linię).

Druga poprawka, jeśli podświetlanie może być skonfigurowane dla różnych kolorów, jest używana na podstawie liczby pasujących linii (lub słów zależnych od AB jest aktywne). Mamy więc tylko dwie kolejne linie, które pasują, potem zielone, 3-5 kolejnych linii, potem pomarańczowe, 6+, a następnie czerwone.

Martin York
źródło

Odpowiedzi:

10

Następujące matchzestawy wydają się działać dla (A):

: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

Wygląda na to, że kolejność jest tutaj kluczowa. Jeśli mecze Lowlub MediumCriticalpóźniejsze, są przejmowane przez ich luźniejsze wymagania i podobnie jak Lowwrt Medium.

Podświetlanie nie pojawia się natychmiast po dodaniu, powiedzmy, trzeciego lub szóstego wiersza duplikatu, ale po poruszeniu się po dodaniu. Nie jestem pewien, co dokładnie to powoduje.

W przypadku B wyobrażam sobie, że możesz zastąpić wyrażenie regularne:

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

Ogólnie rzecz biorąc, należy wymienić wszystkie (.*)z (\S+).*i \1z \1.*, lub cokolwiek stanowi słowo dla Ciebie.

muru
źródło
Dałem tę odpowiedź kleszcza, ponieważ dla mnie jest to, jak zrobić wyróżnienie, którego potrzebowałem (jak wyrażono w pytaniu). @Matts wyrażenie regularne ładne, ale nie odpowiada na pytanie, które zadałem (zmiana podświetlenia).
Martin York
8

Na początek oto wzorzec wyszukiwania, który pasuje do zduplikowanych linii (ignorując zmiany w wiodących białych znakach):

              \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 dostarczy więcej informacji na temat tworzenia takich wyrażeń regularnych

:help syntax pokaże ci, jak wziąć to wyrażenie regularne i przekształcić je w coś, co jest dla ciebie wyróżnione

Nauka pisania skryptów składniowych może być trudna, więc dobrym rozwiązaniem krótkoterminowym jest zrobienie tego „w locie”, upewniając się, że 'incsearch'jest ustawione tak, że wyszukiwania są podświetlone i mapuje klucz do wykonania powyższego wyszukiwania, tj.nnoremap <F5> /^\s*\(.\+\)\n\zs\(\s*\1\n\)\+<CR>

Matt Boehm
źródło
Czy istnieje jakiś zautomatyzowany sposób dystrybucji tego wyrażenia regularnego? Zapewnia tak wyraźne przedstawienie.
muru
1
Robiłem to ręcznie. Najprostszym szybkim sposobem w vimie byłoby zrobienie czegoś takiego jak yy10pna linii z pełnym wyrażeniem regularnym, a następnie wybranie części, które chcesz usunąć i uderzyć r<space>. Może dodam polecenie „zamień wszystko oprócz zaznaczenia w tym wierszu spacjami”, aby nieco przyspieszyć.
Matt Boehm,
Łał! To sporo wysiłku!
muru
1
Zrobiłem (naprawdę brzydką) funkcję vima, aby uczynić to trochę szybszym: gist.github.com/mattboehm/da63a48eedf6f14375aa . Wybierz linię, naciśnij, ,ra następnie połącz linie razem <space>w trybie normalnym / wizualnym.
Matt Boehm