Автоматически создавать соответствующие фигурные скобки в Vim

17

Как автоматически создать соответствующие фигурные скобки в vim?

Он должен работать следующим образом: если я введу открытую скобку, закрывающая должна появиться автоматически, а курсор должен быть помещен между ними. Чтобы выпрыгнуть из пары скобок, используется комбинация Ctrl-j.

Существует множество плагинов, обеспечивающих автоматическую вставку скобок. Но они

  • либо используйте другую комбинацию клавиш, чем Ctrl-jвыскочить из пары скобок, или
  • вмешиваться в привязки клавиш UltiSnips .

Следующие работы, как ожидалось

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

Но с этими настройками фрагменты UltiSnips больше не работают. Поэтому я использовал UltiSnips для вставки закрывающей скобки:

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

Это почти работает. Соответствующая скобка вставлена, и я могу пропустить закрывающую Ctrl-j. Это, однако, работает, только если есть пространство перед открытой скобой.

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

Мои решения либо требуют другой привязки клавиш для перепрыгивания через закрывающую скобку, либо требуют пробела перед открытой. Как это исправить?

Примечание: я использовал скобки в качестве примера. Он должен работать с круглыми скобками, скобками, скобками и знаками «меньше» и не мешать плагину UltiSnips.

Marco
источник
1
Вы пробовали автозаполнение ? Вы можете прыгать из пары с ), переназначение, c-jчто может работать.
Кевин

Ответы:

4

Как автоматически создать соответствующие фигурные скобки в vim?

Как вы увидите, эта проблема нетривиальна. Ответ прост: используйте плагин, такой как autoclose или smartinput . Просто наивно переназначьте ([.. ключи предоставят вам крайние регистры в несколько строк, вот почему эти плагины сделаны, и почему они обычно довольно сложны (если они хороши).

Поэтому я использовал UltiSnips, чтобы вставить закрывающую скобку

Вы можете попробовать это вместо этого (что отличается от моего первоначального предложения):

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

Где UltiSnips будет разделять линию (вместо включения mainв матч. Проблема с использованием плагина сниппета для этого состоит в том, что они (обычно) не поддерживают вложение, поэтому они забудут любые позиции перехода, когда вставлен следующий (вложенный) фрагмент.

Чтобы выпрыгнуть из пары скобок, используется комбинация Ctrl-j.

Вы можете переназначить Ctrl-jлибо для UltiSnips, либо для конфликтующего плагина. Если сопоставления не перечислены в документации, вы можете использовать :map/imap/nmap <key>для отображения сопоставления. Если вы хотите Ctrl-jвыбрать и выполнить работу обоих плагинов, вы просите:

  1. что-то намного более продвинутое, чем я подозреваю
  2. что-то я подозреваю, что вы не очень хотите

Рассмотрим этот цикл bash:

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

В этом случае вам нужно будет нажать Ctrl-j5 раз, чтобы попасть в тело цикла. Использование закрывающих скобок для выпрыгивания из соответствующей пары дает вам гораздо больший контроль над тем, куда вы действительно хотите переместить курсор. Вы можете реализовать стек для отслеживания вставленных пар и использовать его Ctrl-jдля перемещения и перемещения, но тогда у вас возникнут проблемы, если вы начнете удалять фигурные скобки вручную, не удаляя их из стека. Итак, вы начнете решать проблемы, которые пытаются решить подключаемые модули. Это сложное колесо для изобретения.

Расширяя это, вы можете получить то, что изначально просили, используя Ctrl-jвыпрыгивание из фигурных скобок и фрагментов. Если вы используете какое-то фиктивное значение для представления позиций фрагментов и помещаете их в стек в дополнение к закрывающим скобкам, с динамическим переназначением Ctrl-jдля соответствия обработке фрагментов или скобок. Но тогда вам нужно будет реализовать некоторые довольно продвинутые эвристики, чтобы выяснить, какая магия должна произойти, поскольку вы по сути берете на себя сразу две проблемы, которые в настоящее время решаются создателями плагинов для вставки фрагментов и плагинов для сопоставления скобок, и снова решить эти проблемы, в дополнение к их решениям, для достижения удобства и, что ж, волшебства.

Все сводится к контролю против удобства. Я думаю, что управление в этом случае будет вам лучше, а значит, вы должны разделить эти проблемы и связанные с ними плагины и сопоставления клавиш. Если вы все еще хотите удобство, это выполнимо, но это сложно.

aktivb
источник
1

Я думаю, что delimitMate делает то, что вам нужно.

Он автоматически закрывает скобки или кавычки и помещает курсор между ними. Чтобы выскочить из пары скобок (находясь в режиме вставки), вы должны сделатьCtrl-g +, gно вы можете переназначить это Ctrl-j, добавив это в ваш vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g
Матиас Браун
источник
Лучше предоставить более подробную информацию здесь, и использовать ссылку в качестве ссылки для дальнейшего чтения. Таким образом, ваш ответ не теряет всю свою ценность, когда ссылка становится недействительной.
Антон
1

Я обнаружил, что autoclose добавляет немного задержки, а также мешает моей настройке (Ultisnips и Supertab), но мне нравится его подход к эмуляции Eclipse CDT.

я использую delimitMate со следующими картами, чтобы помочь с навигацией и отступами, пытаясь получить те же результаты:

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)

Я использую это следующим образом: вставьте открывание { <CR><CR><C-K>и начните писать во внутренней строке с отступом.

phcerdan
источник
Я обнаружил, что delimitMate также добавляет небольшое отставание
icc97
1

Лично я использую smartinput для автоматической вставки скобок и кавычек. Например, печатать в {любом месте будет {}с вашим курсором в середине. Чтобы покинуть группу {скобок, просто введите « }рядом» со вставленным символом }.

Тем не менее, это поддерживает ваши требования табуляции и прыжков за пределы скобки. Он также не создает нового в скобках, но вам все равно нужен только один дополнительный ключ -<CR> .

Вы можете сопоставить, <C-J>чтобы перейти к следующей строке вниз:

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

или если вы хотите перейти к началу следующей строки:

:inoremap <C-J> <C-O>+
Том Камманн
источник
0

Нечто подобное может сработать для вас.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}
Марк Коэн
источник
То, что вы предлагаете, - это простое сопоставление, которое не позволяет перепрыгнуть через закрывающую скобку.
Марко
0

На самом деле, Ultisnips может сделать это почти идеально (это может быть новым). Немного изменив приведенные выше ответы, я добился успеха

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

Нужно печатать, ()что найти лучше, но это также можно изменить (. Затем дополнительные необязательные аргументы to UltiSnips#Anon- это описание и модификатор, iкоторый допускает раскрытие в слове.

Выпрыгивание из скобок с <c-j>работами, также вложенными в другие фрагменты. Тем не менее, использование вложенных ()скобок, кажется, нарушает эту функцию, что не имеет большого значения.

user3240588
источник