Automatycznie twórz pasujące nawiasy klamrowe w vimie

17

Jak automatycznie tworzyć pasujące nawiasy klamrowe w vimie?

Powinno działać w następujący sposób: Jeśli wprowadzę nawias otwarty, to nawias zamykający powinien pojawić się automatycznie, a kursor powinien zostać umieszczony pomiędzy. Aby wyskoczyć z pary nawiasów, Ctrl-jużywana jest kombinacja .

Istnieje wiele wtyczek zapewniających automatyczne wstawianie nawiasów klamrowych. Ale oni

  • użyj innej kombinacji klawiszy niż Ctrl-jwyskoczyć z pary nawiasów klamrowych lub
  • zakłócać powiązania klawiszy UltiSnips .

Poniższe działa zgodnie z oczekiwaniami

:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a

Ale przy tych ustawieniach fragmenty UltiSnips już nie działają. Więc użyłem UltiSnips, aby wstawić klamrę zamykającą:

inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>

To prawie działa. Dopasowany klamra jest wstawiony i mogę pominąć zamykający za pomocą Ctrl-j. Działa to jednak tylko wtedy, gdy przed otwartą klamrą znajduje się przestrzeń.

main () // works, the closing parentheses is added
main(   // fails without a space

Moje rozwiązania albo wymagają innego przypięcia klucza, aby przeskoczyć nad klamrą zamykającą, albo wymagają miejsca przed otwartym. Jak to naprawić?

Uwaga: użyłem nawiasów jako przykładu. Powinien współpracować z nawiasami, nawiasami klamrowymi, nawiasami i znakami mniejszymi niż i nie powinien zakłócać wtyczki UltiSnips.

Marco
źródło
1
Czy próbowałeś zamknąć automatycznie ? Możesz wyskakiwać z par za pomocą ), zmiana mapowania c-jna to może działać.
Kevin

Odpowiedzi:

4

Jak automatycznie tworzyć pasujące nawiasy klamrowe w vimie?

Ten problem nie jest trywialny, jak się przekonacie. Odpowiedź jest prosta: użycie wtyczki, jak AutoClose lub smartinput . Wystarczy naiwnie odwzorować (klucze [... pokażą ci edgecases w kilku liniach), dlatego te wtyczki są tworzone i dlaczego są zwykle dość złożone (jeśli są jakieś dobre).

Więc użyłem UltiSnips, aby wstawić klamrę zamykającą

Możesz spróbować zamiast tego (co różni się od mojej oryginalnej sugestii):

inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>

Gdzie UltiSnips podzieli linię (zamiast brać udział mainw meczu. Problem z używaniem wtyczki do tego fragmentu polega na tym, że (zwykle) nie obsługują one zagnieżdżania, więc zapomną o pozycjach skoku po włożeniu następnego (zagnieżdżonego) fragmentu.

Aby wyskoczyć z pary nawiasów, Ctrl-jużywana jest kombinacja .

Możesz zmienić mapowanie Ctrl-jdla UltiSnips lub wtyczki powodującej konflikt. Jeśli mapowania nie ma na liście w dokumentacji, możesz użyć :map/imap/nmap <key>do wyświetlenia mapowania. Jeśli chcesz Ctrl-jwybrać, wybrać i wykonać pracę obu wtyczek, poprosisz o:

  1. coś o wiele bardziej zaawansowanego, niż podejrzewam
  2. coś, co podejrzewam, że tak naprawdę nie chcesz

Rozważ tę pętlę bash:

while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
  [next_snippet_position_marker]
done

W takim przypadku musisz nacisnąć Ctrl-j5 razy, aby dostać się do ciała pętli. Użycie zamykających nawiasów w celu wyskoczenia z odpowiedniej pary daje o wiele większą kontrolę nad tym, gdzie faktycznie chcesz przesunąć kursor. Możesz zaimplementować stos, aby śledzić wstawione pary i używać ich Ctrl-jdo pop i przesuwania, ale wtedy wystąpią problemy, jeśli zaczniesz ręcznie usuwać nawiasy klamrowe bez usuwania ich ze stosu. Zaczniesz więc rozwiązywać problemy, które wtyczki klamrowe próbują rozwiązać. To jest trudne koło do wymyślenia na nowo.

Rozwijając to, możesz uzyskać to, o co początkowo prosiłeś, używając Ctrl-jwyskakując z nawiasów klamrowych i fragmentów. Jeśli użyjesz jakiejś wartości fikcyjnej do reprezentowania pozycji urywków i wepchniesz je na stos oprócz zamykających nawiasów klamrowych, z dynamicznym odwzorowaniem Ctrl-jodpowiadającym przekazywaniu urywków lub nawiasów klamrowych. Ale wtedy musisz wdrożyć dość zaawansowaną heurystykę, aby dowiedzieć się, co magia powinna się wydarzyć, ponieważ zasadniczo bierzesz na siebie dwa problemy, które są obecnie rozwiązywane przez twórców wtyczek wstawiania fragmentów i osobno dopasowywania wtyczek i ponownie rozwiązując te problemy, oprócz ich rozwiązań, aby uzyskać wygodę i, no cóż, magię.

Wszystko sprowadza się do kontroli vs. wygody. Myślę, że kontrola w tym przypadku będzie ci lepiej służyć, co oznacza, że ​​powinieneś oddzielić te problemy od powiązanych z nimi wtyczek i mapowań kluczy. Jeśli nadal chcesz wygody, jest to wykonalne, ale trudne.

aktivb
źródło
1

Myślę, że delimitMate robi to, czego potrzebujesz.

Automatycznie zamyka nawiasy lub cudzysłowy i umieszcza kursor pomiędzy nimi. Aby wyskoczyć z pary nawiasów (będąc w trybie wstawiania), możesz zrobić Ctrl-g+, gale możesz to zmienić Ctrl-j, dodając to do vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g
Matthias Braun
źródło
Lepiej podać więcej szczegółów tutaj i użyć linku jako odniesienia do dalszego czytania. W ten sposób twoja odpowiedź nie traci całej wartości, gdy link traci ważność.
Anthon
1

Odkryłem, że automatyczne zamykanie dodaje trochę opóźnienia, a także zakłóca moją konfigurację (Ultisnips i Supertab), ale podoba mi się jego podejście do emulacji CDT Eclipse.

Używam delimitMate z następującymi mapami, aby pomóc w nawigacji i wcięciach, starając się uzyskać te same wyniki:

imap <C-F> <C-G>g           " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)

Używam tego w ten sposób: wstawianie otworu { <CR><CR><C-K>i zacznij pisać w wciętej linii wewnętrznej.

phcerdan
źródło
Zauważyłem, że delimitMate również dodaje niewielkie opóźnienie
icc97
1

Osobiście używam smartinput do automatycznego wstawiania nawiasów i cytatów. Na przykład pisanie w {dowolnym miejscu spowoduje utworzenie {}kursora pośrodku. Aby opuścić {grupę nawiasów, wpisz po prostu }obok wstawionego }.

Jednak to potwierdza twoje wymagania dotyczące tabstops i przeskakiwania poza nawias. Nie tworzy też nowego między nawiasami, ale i tak potrzebujesz tylko jednego dodatkowego klucza - <CR>.

Możesz mapować, <C-J>aby przejść do następnej linii w dół:

:inoremap <C-J> <C-O>j

lub jeśli chcesz przejść do początku następnego wiersza:

:inoremap <C-J> <C-O>+
Tom Cammann
źródło
0

Coś takiego może się dla ciebie sprawdzić.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}
Mark Cohen
źródło
Sugerujesz proste mapowanie, które nie pozwala przeskoczyć nawiasu klamrowego.
Marco,
0

W rzeczywistości Ultisnips może to zrobić prawie idealnie (może to być nowy). Nieznacznie modyfikując odpowiedzi podane powyżej, mam spory sukces

inoremap () ()<C-R>=UltiSnips#Anon('($1)$0', '()', 'double parentheses', 'i')<CR>

Trzeba pisać, ()które są lepsze, ale można je również zmienić (. Następnie dodatkowe opcjonalne argumenty UltiSnips#Anonto opis i modyfikator, iktóry umożliwia rozwijanie w słowie.

Wyskakiwanie z nawiasów za pomocą <c-j>utworów, również zagnieżdżonych w innych fragmentach. Jednak wywoływanie zagnieżdżonych ()nawiasów wydaje się przerywać tę funkcję, co nie jest niczym wielkim.

użytkownik3240588
źródło