Standaryzuj \ n i \ r w składni wyszukiwania / zamiany Vima

1

W Vimie szuka się nowych linii jako \n, ale nowe linie w ciągu zastępującym należy wprowadzić jako \r. Rozumiem, że istnieją powody takiego zachowania , ale dla moich celów po prostu uważam to za irytujące. Chcę móc używać \n(zasadniczo) tej samej rzeczy zarówno we wzorcu wyszukiwania, jak i w łańcuchu zastępczym: w szczególności we wzorcu wyszukiwania powinien on pasować do nowych linii, a w łańcuchu zastępczym powinien wstawiać nowe linie.

Czy istnieje sposób na uzyskanie tego zachowania? Nie sądzę, aby proste zmiany mapowania działały, ponieważ polecenie zastępcze musi zostać przeanalizowane w celu ustalenia, czy \njest częścią wzorca wyszukiwania, czy ciągu zastępującego.

Kyle Strand
źródło
1
Tak, jest to frustracja dla praktycznie każdego, ale raczej nie ulegnie zmianie. Vim jest bardzo duży pod względem kompatybilności wstecznej, a ta szansa nie byłaby.
Heptyt
@Heptite Nie proszę o zmianę bazy kodu Vima; Zastanawiam się, czy możliwe jest uzyskanie tego zachowania poprzez jakąś formę dostosowywania, na przykład wtyczkę, prawdopodobnie wykorzystującą github.com/coot/CRDispatcher .
Kyle Strand
@Kyle nie edytuj odpowiedzi innych osób. Zamiast tego edytuj własny post, jeśli chcesz go rozwinąć.
kinokijuf
@kinkijuf Nie rozwijałem mojego pytania; Przyjmowałem sugestię odpowiadającego i współtworzyłem (zgodnie z jego własną sugestią) moją wersję wyrażenia regularnego używanego do ustalenia, czy wykonać zamianę. Ten dodatek z pewnością nie należy do mojego pytania, a od głównej części roztworu wynosiła trick korzystania c_CTRL-\_ez getcmdline() =~# , a nie szczegóły regex używane, nie sądzę, że zasługuje na swoją własną odpowiedź.
Kyle Strand

Odpowiedzi:

3

Musisz podpiąć się do linii poleceń; albo podczas wykonywania go za pośrednictwem <CR>, albo natychmiast po wprowadzeniu \n. Za pomocą :help c_CTRL-\_emożesz ocenić funkcję i zmodyfikować wiersz poleceń. Oto wersja demonstracyjna, którą możesz rozbudować i ulepszyć (kontrola zamiany jest teraz bardzo uproszczona):

cnoremap n <C-\>eTranslateBackslashN()<CR>
function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~# 's/.*/.*\\$' " Improve this!
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
Ingo Karkat
źródło
...fantazyjny. <C-\>eto całkiem fajna funkcja, o której nie wiedziałam.
Kyle Strand
Dodałem wyrażenie regularne, którego używam .vimrc, z wyjaśnieniem.
Kyle Strand
Nieważne, moja edycja została odrzucona. Nadal uważam, że zasługujesz na uznanie tego rozwiązania, ale zamierzam opublikować własną odpowiedź, aby pełne wdrożenie było widoczne.
Kyle Strand
1

Jak napisał Ingo Karkat, rozwiązanie można znaleźć za pomocą c_CTRL-\_e. Oto wersja, której używam, która jest identyczna z oryginalnym rozwiązaniem, z wyjątkiem wzorca wyrażenia regularnego. (Ponieważ jest to tak naprawdę odpowiedź Ingo Karkat z niewielkim ulepszeniem zasugerowanym przez Ingo Karkat , nie sądzę, że tak naprawdę zasługuje na swoją własną odpowiedź, ale chyba jestem przegłosowany: http://chat.stackexchange.com/transcript/ wiadomość / 15021397 # 15021397 )

function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~#
      \ '[%>]s\([um]\w*\)\?\(.\).\{-}\(\\\)\@<!\2.*\\$'
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
cnoremap n <C-\>eTranslateBackslashN()<CR>

Objaśnienie wzoru wyrażenia regularnego:

  • [%>]szapewnia, że ​​wymiana nastąpi tylko wtedy, gdy snastąpi natychmiast po zasięgu
  • \([um]\w*\)\?dopasowuje odmiany spolecenia, takie jak smagic.
  • \(.\)będzie pierwszym znakiem niebędącym słowem, ponieważ wszystkie znaki słowne zostaną już zjedzone \ww opcjonalnej grupie. Pamiętaj, że jest to grupa 2. Jest to zwykle znak separatora /. Zauważ, że _będący znakiem słownym jest również prawidłowym separatorem, więc wzorzec nie będzie działał poprawnie, jeśli _zostanie użyty w ten sposób. _Jednak nigdy nie używam jako separatora, więc nie będę się tym martwić. Podobnie, istnieją pewne znaki, które nie są znakami słownymi, ale których nie należy używać jako separatorów, ale nie martwię się o to tutaj, ponieważ w takim przypadku polecenie i tak powinno się nie powieść. Chciałem \Wtutaj skorzystać , ale z jakiegoś powodu to nie działało, kiedy go testowałem.
  • .\{-}powinien pasować do wzorca ( \{-}jest podobny do Perla *?).
  • \(\\\)\@<!\2dopasowuje następne wystąpienie znaku separatora nie poprzedzone ukośnikiem wstecznym. Odpowiednikiem Perla byłoby (?<!\\)\2.
  • .* pasuje do tego, co do tej pory znajdowało się w ciągu zastępującym.
  • \\$ pasuje tylko wtedy, gdy dotychczasowe polecenie kończy się odwrotnym ukośnikiem.
Kyle Strand
źródło
Spójrz na :h range. Nie łapiesz wszystkich zakresów (nie jestem pewien, czy istnieje dobry sposób, aby to zrobić.)
FDinoff 18.04.2014
@FDinoff Dopasowuję tylko dwa wyrażenia zakresu, których obecnie używam. Jednak nie wygląda na to, że byłoby tak trudno dopasować do innych, więc będę aktualizować, gdy będę potrzebować aktualizacji.
Kyle Strand
0

Alternatywna odpowiedź przy użyciu wtyczki (jest to rozwiązanie, z którego zdecydowałem się skorzystać, chociaż działa tylko z Vimem 7.4+):

Używając Enchanted Vim , włóż let g:VeryMagicSubstituteNormalise = 1swój .vimrc.

(Ta wtyczka korzysta z wtyczki CRDispatcher , która pozwala na zastępowanie tekstu w poleceniach po naciśnięciu klawisza Enter, ale przed wykonaniem polecenia. Nie \njest więc wymagane ponowne mapowanie , a podstawienie jest niewidoczne dla użytkownika, sprawiając \nwrażenie , jakby miał to samo „znaczenie” w obu kontekstach).

Kyle Strand
źródło