Jak wyszukać wzorzec w niektórych regionach składni?

10

Używam vima do edycji dokumentów lateksowych. Często będę chciał zmienić nazwę zmiennej na coś innego. Jednak szukanie nazwy zmiennej jest trochę denerwujące. Chciałbym wyszukiwać tylko w „strefach matematycznych” zdefiniowanych w pliku składniowym tex. Czy istnieje prosty sposób na ograniczenie wyszukiwania do określonego regionu składni?

Rob F.
źródło
1
Myślę, że odpowiedź brzmi nie: nie ma łatwego sposobu ograniczenia wyszukiwania do określonego regionu składni.
Karl Yngve Lervåg
2
To odwzorowanie wykorzystuje synIDattr()do uzyskania grup składni dla znaku pod kursorem. Możesz napisać funkcję, która wykonuje wyszukiwanie (lub wykonuje normal n), a następnie używa, synIDattr()aby zdecydować, czy pozostać w tej lokalizacji, czy kontynuować wyszukiwanie do przodu.
joeytwiddle
@joeytwiddle Widziałem Twój komentarz właśnie po opublikowaniu odpowiedzi z taką funkcją. Czy to jest to, co miałeś na myśli?
jjaderberg,
@jjaderberg Tak to jest. Dobra robota!
joeytwiddle
Dla kompletności (uważam, że to dobra odpowiedź): stackoverflow.com/a/2696143/5000478
VanLaser

Odpowiedzi:

4

Oto funkcja, którą możesz wypróbować. Testowałem to tylko trochę, ale wydaje się, że działa dobrze.

function! JJSyntaxSearch(pattern, syntaxitem)
  while search(a:pattern, 'W') > 0
    for id in synstack(line("."),col("."))
      if synIDattr(id,"name") =~? a:syntaxitem
        return line(".")
      endif
    endfor
  endwhile
  return 0
endfunc

command! -nargs=* JJSyntaxSearch call JJSyntaxSearch(<f-args>)

Funkcja wywołuje funkcję wyszukiwania Vima w pętli, dopóki nie znajdzie „zwykłego” dopasowania, które jest również „kwalifikowanym” dopasowaniem do określonego elementu składni lub dopóki nie osiągnie końca bufora.

Wymaga dwóch argumentów. Pierwszy to wzorzec wyszukiwania i jest on przekazywany bez zmian do search()funkcji Vima . Zobacz, :help search()jak działa ta funkcja. Drugi argument to nazwa elementu składni, na którym chcesz filtrować te dopasowania. Może to być również wzorzec i jest porównywany jako wyrażenie regularne bez rozróżniania wielkości liter.

Aby znaleźć wzór „alfa” w strefach matematycznych, możesz to zrobić

:JJSyntaxSearch alpha texMathZone.

Na .końcu znajduje się atom wzoru dla każdego pojedynczego znaku, patrz :help /.. To dlatego, że wiele elementów składniowych strefa matematyki nazywa texMathZoneA, texMathZoneBetc.

search()Funkcja przesuwa kursor do następnego „zwykłym” meczu. Następnie nasza funkcja pobiera wszystkie identyfikatory pozycji składni dla tej nowej pozycji kursora za pomocą synstack(). Pętląc je, pobiera po kolei nazwę każdego elementu i testuje go pod syntaxitemkątem argumentu. Zobacz :help synstack()i :help synIDattr(). Jeśli istnieje dopasowanie „kwalifikowane”, zwraca numer linii. Jeśli osiągnie koniec bufora bez znalezienia „dopasowanego” dopasowania, zwraca 0. Celem funkcji jest przesunięcie kursora do następnego dopasowania „kwalifikowanego”, aby można było tam wykonać jakąś operację, ale warto zwrócić „numer linii lub 0”, aby wskazać, czy sensowne jest ponowne wywołanie funkcji, ponieważ wystąpienie, jeśli chcesz wywoływać funkcję wielokrotnie z innej funkcji lub makra.

Zdecydowałem się użyć Wflagi do, search()ponieważ zapobiega to owijaniu się końca bufora. W przeciwnym razie funkcja może utknąć, ponieważ ciągle znajduje te same „zwykłe” dopasowania, ale nie ma „kwalifikowanych” dopasowań.

jjaderberg
źródło
Dzięki za pomoc! Nie próbowałem jeszcze tej funkcji, ale wygląda na to, co chciałem.
Rob F.
1

W przypadku, gdy twoje „strefy matematyczne” są zaklasyfikowane według jakiegoś wzorca składniowego, powiedzmy, ciągu „matematycznego”, możesz przynajmniej użyć sekwencji wzorców, aby znaleźć linię z pasującym wzorcem, jak w:

:/math//your pattern/

(Uwaga: dwa wzory mogą znajdować się na różnych liniach!)

To może nie ograniczać twoich dopasowań do stref - w tym celu musisz określić koniec strefy - ale wyświetli tylko te dopasowania po początkowym wzorcu / matematyce /. Możesz powtórzyć wyszukiwanie następnego wystąpienia, używając historii trybu ex ( : up-arrow enter).


Uwaga: ISTR, że we wcześniejszych wersjach vim / vi mogłem również używać tej metody bezpośrednio jako polecenia wyszukiwania (w przeciwieństwie do polecenia trybu ex) /math//your pattern/z zaletą mniejszego wpisywania i używania poleceń ni N, ale nie mogę potwierdzić to dla mojej obecnej wersji vima.

Janis
źródło
1

Jeśli szukasz ciągu foowewnątrz $...$lub $$...$$, powinno to działać:

\$.*\zsfoo

To zakotwicza dopasowanie do $znaku, ale wybiera tylko ciąg foo.

To nie jest naprawdę łatwe rozwiązanie, ale można użyć :global+, :substituteaby znaleźć „strefy matematyczne” i przeszukać w nich:

:global /\v\\begin\{%(align|alignat|displaymath)\}/ +1,/\\end/-1 s/foo/&/gc

Udając, że :substitutejest to polecenie wyszukiwania, możesz przejść do następnego wystąpienia za pomocą ni wyjść z q. Jeśli przez pomyłkę potwierdzisz zamianę, nie powinno być problemu.

Będziesz musiał ustawić listę wewnątrz %(... )na nazwy środowisk matematycznych, z których korzystasz (pełna lista jest nieco mocna:) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Zauważ, że używam tutaj bardzo magicznego ( \v) wzoru.

Wyjaśnienie:

:globalwykonać polecenie Ex ( :s) na każdej linii, gdzie mecze wzór ( :help :global)
/\vrozpocząć bardzo magicznego wzoru ( :h /, :h pattern, :h magic)
\\begin\{pasuje dosłownym \begin{
%(align|alignat|displaymath)pasuje do żadnego z tych słów ( :h /\%(, :h /bar)
\}/pasuje dosłownym }i zakończyć wzór.

+1,/\\end/-1zakres składający się z następnego wiersza (licząc od znalezionego przez :global) do wiersza poprzedzającego znaleziony przez wzorzec wyszukiwania /\\end. W tym zakresie

s/foo/&/gcwyszukaj i zamień każde wystąpienie literału na foosiebie, po potwierdzeniu ( :h :substitute)

Peter Lewerin
źródło
Z pewnością jest to początek, ale często używam środowiska równania, wyrównywania i środowiska IEEEeqnarray i nie chcę wykluczać tych z mojego wyszukiwania.
Rob F.
@RobF .: całkiem możliwe jest dopasowanie w różnych środowiskach, ale nie będzie to łatwe, chyba że ktoś to zrobi. Jeśli jednak konsekwentnie używasz \mathitnazw zmiennych, znalezienie ich jest znacznie łatwiejsze.
Peter Lewerin
0

Jeśli szukasz ciągu „rano” w pliku, /morninga następnie enternaciśnij przycisk, naby przejść do przodu

Arvind Gangwar
źródło
1
Pytanie mówiło, że I would like to search only in "math zones"twoja metoda wyszukuje cały plik, który nie ogranicza strefy badawczej.
statox
0

Nie ma innej opcji niż napisanie dedykowanej do tego funkcji. Napisałem funkcję, która wyszukuje żądany ciąg i zatrzymuje się tylko, jeśli:

  1. kończy się zapałek
  2. istnieje dopasowanie, które znajduje się w środowisku matematycznym (zatrzyma się na meczu)

Po prostu wywołujesz go ciągiem, który chcesz wyszukać.

function! Finmath(nextstr)
    while 1
        if search(a:nextstr)==0
            break
        endif
        if searchpairpos('\(', '','\)','n')!=[0,0]
            break
        endif
        if searchpairpos('\[', '','\]','n')!=[0,0]
            break
        endif
        let a = getcurpos() 
        if count(strpart(getline('.'),0,a[2]),'$')%2==1
            break
        endif 
    endwhile 
endfunction

Zamierzam napisać podobną funkcję dla GrammerousCheck, która zatrzymuje się tylko na błędach gramatycznych poza matematyką.

eyal karni
źródło