Składanie według wzorca wyszukiwania wyrażeń regularnych

13

Mam zwykły plik tekstowy z oddzielonymi białymi kolumnami wartości. Lubię to:

AU 3030 .... ... ....  
AU 3031 .... ... ....  
AU 3032 .... ... .... 
AU 3033 .... ... .... 
IT 48100 ... .. .....
IT 40100 ... .. .....
IT 48123 ... .. .....
UK 3333 ... ... ..... 
UK 4444 ... ... .....
UK 5555 ... ... .....

Mam również ten wyrażenie regularne, które będzie pasować do dowolnego sąsiedniego wiersza o tej samej wartości w pierwszej kolumnie (zakładając, że plik jest posortowany w pierwszej kolumnie) oprócz ostatniej:

/^\(\([A-Z0-9]\+\)\s\+.*\n\)\(\2\)\@=

(lub aby było mniej „włochate”):

/^\v([A-Z0-9]+)\s+.*\n(\1)@=

Czy można złożyć linie nad linią, która nie została dopasowana? Mając ten wynik:

+-- 4 lines AU ....
+-- 3 lines IT ....
+-- 3 lines UK ....
guido
źródło

Odpowiedzi:

14

Wykonaj set foldmethod=expri użyj, 'foldexpr'aby ustawić wyrażenie skryptu vim, które określi punkty początkowe składania.

set foldmethod=expr
set foldexpr=get(split(getline(v:lnum-1)),0,'')!=get(split(getline(v:lnum)),0,'')?'>1':'='

Wygląda to bardziej skomplikowane niż jest, ponieważ nie możemy łatwo użyć spacji :set, ale ze spacjami i znakiem nowej linii lub 2 wygląda to tak:

get(split(getline(v:lnum - 1)), 0, '') != get(split(getline(v:lnum)), 0, '')
    \ ? '>1'
    \ : '='

Przegląd

Zasadniczo porównuje to pierwsze słowo każdego wiersza z poprzednim wierszem. Jeśli słowa są różne wtedy linia jest zacząć od owczarni, >1. W przeciwnym razie utrzymuje ten sam poziom krotnie =.

Chwała szczegółów

  • set foldmethod=expr aby powiedzieć Vimowi, aby użył wyrażenia skryptu vim do określenia folderów
  • 'foldexpr' opcja przechowuje wyrażenie skryptu vim
  • Ocena stanu za pomocą trójki, która powraca, >1kiedy należy rozpocząć składanie i =kiedy poziom składania powinien być kontynuowany
  • v:lnumjest bieżącą linią, która 'foldexpr'działa, aby zaktualizować fałdy
  • Pobierz zawartość bieżącej linii ( v:lnum) i poprzedniej linii ( v:lnum - 1) przezgetline()
  • Podziel każdą linię na słowa za pomocą split()
  • Użyj, get()aby uzyskać pierwszy indeks świeżo podzielonych słów
  • Użyj wartości domyślnej ''w przypadku pustej linii. na przykładget(words, 0, '')
  • Porównaj pierwsze słowo bieżącego wiersza z pierwszym słowem poprzedniego wiersza w części warunku trójskładnika

Uwaga: ta metoda może powodować problemy z wydajnością bardzo dużych dokumentów

Aby uzyskać więcej pomocy, zobacz:

:h 'foldmethod'
:h 'foldexpr'
:h getline(
:h v:lnum
:h split(
:h get(
Peter Rincker
źródło