Автоматично вставляйте відповідні фігурні дужки у Vim


78

Я витрачаю шлях надто багато часу нишпорити навколо , тому що Vim і не виконує жодних закривають фігурні дужки , як і більшість Іди зробити. Ось, що я хочу, щоб сталося:

Введіть це:

if( whatever )
{ <CR>

і отримати це:

if( whatever )
{
  |  
}

де <CR>середнє значення натискає ENTERклавішу і |є позицією курсора. Це те, що робить Eclipse. Це те, що робить Visual Studio. І я хочу, щоб це зробив Вім.

Я бачив кілька плагінів, пробував кілька, і, здається, жоден з них не дає мені такої поведінки. Звичайно, я не можу бути першим програмістом, який цього хоче.



2
Примітка: Vim - настільки потужний текстовий редактор, що може діяти як IDE по-різному ... але це не IDE. У цьому випадку це функція редагування тексту, у чому Vim добре працює, тож ви золоті.
Кіт Пінсон,

Відповіді:


44

У VimL ви можете встановити карту, {щоб зробити саме так, як ви хочете:

inoremap { {<CR>}<Esc>ko

залежно від налаштування автовідступу, ви можете додати <BS>після <CR>.

Для більш повного рішення я б запропонував вам поглянути на плагіни Luc Hermitte vim . Вони ніколи не підводили мене дотепер.


1
чи {<CR>можливо також картографування ? Я маю на увазі, що якщо я наберу лише хеш {"something":"like this"}у python, js або ruby?
Раплі Андраш,

4
Так, {<CR>можливо. Це те, що я маю у своєму .vimrc{<CR> {<CR>}<Esc>ko
AgmLauncher

Привіт @AgmLauncher, це працює, якщо я набираю, {але є проблема, коли я вставляю блок коду, який містить {, він додасть a }в кінці.
Еван Ху

2
@Evan - При вставці коду багато речей можуть піти не так, особливо з автоматичним відступом та подібними. try: встановіть пасту перед вставкою, а потім: встановіть nopaste після закінчення. Це перемикає режим вставки.
Абхінав Гуджяр

11

Користування функцією AutoClose з наведеними нижче правильними результатами

inoremap {<CR> {<CR>}<C-o>O

Це справедливо як мінімум для моєї системи (термінал Unix на Mac OS X).


7

Ось що я маю у своєму vimrc:

let s:pairs={
            \'<': '>',
            \'{': '}',
            \'[': ']',
            \'(': ')',
            \'«': '»',
            \'„': '“',
            \'“': '”',
            \'‘': '’',
        \}
call map(copy(s:pairs), 'extend(s:pairs, {v:val : v:key}, "keep")')
function! InsertPair(left, ...)
    let rlist=reverse(map(split(a:left, '\zs'), 'get(s:pairs, v:val, v:val)'))
    let opts=get(a:000, 0, {})
    let start   = get(opts, 'start',   '')
    let lmiddle = get(opts, 'lmiddle', '')
    let rmiddle = get(opts, 'rmiddle', '')
    let end     = get(opts, 'end',     '')
    let prefix  = get(opts, 'prefix',  '')
    let start.=prefix
    let rmiddle.=prefix
    let left=start.a:left.lmiddle
    let right=rmiddle.join(rlist, '').end
    let moves=repeat("\<Left>", len(split(right, '\zs')))
    return left.right.moves
endfunction
 noremap! <expr> ,f   InsertPair('{')
 noremap! <expr> ,h   InsertPair('[')
 noremap! <expr> ,s   InsertPair('(')
 noremap! <expr> ,u   InsertPair('<')

І для деяких типів файлів:

inoremap {<CR> {<C-o>o}<C-o>O

// Я знаю, що функція InsertPair є тривіальною, але це економить час, оскільки за допомогою неї я можу визначити як відображення команд, так і нормальний режим однією командою, не писаючи багато <Left>s.


6

Помістіть у свій файл .vimrc наступне:

inoremap { {}<ESC>ha

Кожного разу, коли ви натискаєте {в режимі вставки, {}генерується і кладе курсор на праву фігурну дужку, щоб ви могли одразу почати друкувати між ними. Розміщуючи фігурні дужки послідовно, а не на різних лініях, ви можете розміщувати вкладки перед }вручну. Таким чином, перед вами ніколи не буде неправильної кількості вкладок.

Можливо, хтось може зрозуміти, як підрахувати кількість вкладок, на яких знаходиться курсор, а потім генерувати однакову кількість вкладок перед }новим рядком.


6

Рішення для фігурних дужок, дужок та дужок з табуляцією між ними.

" Automatically closing braces
inoremap {<CR> {<CR>}<Esc>ko<tab>
inoremap [<CR> [<CR>]<Esc>ko<tab>
inoremap (<CR> (<CR>)<Esc>ko<tab>

Результат:

function() {
  |
}

4

Я завжди вважав за краще щось на зразок того, що робить піднесений текст там, де він додає фінальну дужку як наступний символ, тому я додав у свій .vimrc наступне:

inoremap (  ()<ESC>hli

який переміщує курсор між двома фігурними дужками.


Це замінює (в ()hli. Vim8 на Mac.
Віталій Зданевич

3

Для тих, хто стикається з цим, як я, і шукав щось недавно оновлене, ніж AutoClose: delimitMate, який, як я переконався, є не лише кращим рішенням для AutoClose, з розумом, але і в активному розвитку. За даними vim.org , AutoClose не оновлювався з 2009 року.


1
Зверніть увагу, що delmitMateExpandпараметри за замовчуванням вимкнено. Вам потрібно додати let delimitMate_expand_cr = 1 до вашого .vimrc.
Себастьян

3

Я пробував різні плагіни, але знайшов найбільш точні та найпростіші у використанні автоматичні пари . Це справді інтуїтивно зрозуміло, і при його встановленні ви отримуєте те, що очікували, з коробки.


1
З моменту публікації цієї відповіді пройшло п’ять років. Якщо хтось інший стикається з подібною проблемою, це спрацювало у мене, принаймні, не ламаючи інші плагіни.
dekarpaulvictor

3

Як ви побачите в наконечнику Вікіі : Є багато рішень цього рекурентний питання ( у мене навіть є мій ).

Тобто, якщо ви обмежитеся парами дужок. Ось ви в контексті твердження контролю. Таким чином, ви з більшою ймовірністю знайдете системи фрагментів, які не очікують від вас набору символу ") {" під час введення оператора "if". Ярлик Vim, як правило, коротший від того, що я читав у вашому запитанні. Тут знову є багато варіантів, ви, швидше за все, знайдете snipmate і, можливо, це мій пакет C & C ++ .


Просто досвід: Google видає 404 при спробі отримати вімбол lh-cpp-1.0.0.vba. Я користувався svn і ніколи раніше цього не помічав.
Michael Foukarakis

Справді. Моя помилка. Я хочу закінчити документацію, перш ніж робити офіційний реліз із vimball та всім іншим.
Luc Hermitte

2

delimitMate має налаштування для цього.


Більше інформації, будь ласка. Яке налаштування?
docwhat

Хм, це було деякий час тому. Я міг би мати на увазі delimitMate_expand_cr, хоча, здається, це робить не саме те, про що просять. Здається, правильно вставляє розриви рядків, але, можливо, не додає кінцеву дужку. Файл довідки знаходиться тут: github.com/Raimondi/delimitMate/blob/master/doc/delimitMate.txt Особисто я в наші дні використовую лише endwise ( github.com/tpope/vim-endwise ) і інакше відповідаю власним дужкам , оскільки немає автоматизації цілком зрозуміло.
Генрік Н

Дякуємо за вказівник на endwise. Я не розумів, що це було, коли бачив це раніше.
docwhat

2

Виправлення Vim 7.4.849 додало прив’язку, що дозволяє рухати курсор без перезапуску послідовності скасування. Після оновлення до> = 7.4.849, щось подібне чудово працює.

inoremap ( ()<C-G>U<Left>

Зауважте, що я схопив це прямо з документації, що міститься у патчі. Найкраще просте рішення для цієї функції.


Це виправлення '.' не працює з автоматично підібраними панелями.
Джон Айкенберрі

2
inoremap ( ()<ESC>i
inoremap " ""<ESC>i
inoremap ' ''<ESC>i
inoremap { {<Cr>}<Esc>O

2

Нарешті я виявив, що плагін не потрібен, але це, напевно, ідеально для мене:

inoremap { {}<Esc>ha
inoremap ( ()<Esc>ha
inoremap [ []<Esc>ha
inoremap " ""<Esc>ha
inoremap ' ''<Esc>ha
inoremap ` ``<Esc>ha

1

Встановіть і використовуйте сценарій Vim AutoClose, як рекомендовано у статті під назвою Автоматично додавати закриваючі символи .


2
AutoClose робить не те, що я хочу. Це залишає фінальну дужку на тому самому рядку, змушуючи мене двічі натиснути Enter, повернутися до командного режиму, перейти вгору по рядку, вставити режим, вкладку і нарешті ввести.
Боб

1

Просто примітка @Bob.

Автозакриття Карла Гертіна має функцію під назвою `` подвійна дужка '', тобто ви можете двічі набирати фігурні дужки, як показано нижче.

int func_name(void) {{ ==> Type `{' twice here.

призведе до:

int func_name(void) {
| ==> Cursor here.
}

Потім ви можете ввести одну вкладку, щоб отримати відступ відповідно до налаштування `shiftwidth ', а потім введіть.


0

Для цього вам не потрібен спеціальний плагін - але це двоетапний процес.

Спочатку додайте наступне до свого, .vimrcщоб з’їсти ініціюючий символ:

" eat characters after abbreviation
function! Eatchar(pat)
    let c = nr2char(getchar(0))
    return (c =~ a:pat) ? '' : c
endfunction

а потім додайте це скорочення до свого .vimrc:

inoreabbr <silent> { {
      \<cr><space><space>
      \<cr><esc>0i}<esc>k$i<c-r>=Eatchar('\m\s\<bar>\r')<cr>

На \початку рядків два і три - це просто символ продовження рядка. Ви могли зробити все це в одному рядку, однак, і я додав це, щоб я міг розповсюдити абревіатуру так, щоб відображати вихідний результат, який ви шукаєте - просто так, щоб речі були трохи більш інтуїтивними.


0

Моє рішення:

inoremap <expr> <CR> InsertMapForEnter()
function! InsertMapForEnter()
    if pumvisible()
        return "\<C-y>"
    elseif strcharpart(getline('.'),getpos('.')[2]-1,1) == '}'
        return "\<CR>\<Esc>O"
    elseif strcharpart(getline('.'),getpos('.')[2]-1,2) == '</'
        return "\<CR>\<Esc>O"
    else
        return "\<CR>"
    endif
endfunction

Пояснення:

Наведений вище код спочатку перевірте, чи використовуєте ви Enterдля підтвердження заповнення коду, якщо ні, він буде відступати {|}при введенні Enter. Крім того, він забезпечує автовідступ тегів html.

Приклади:

if( whatever ){|}

натисніть Enterі ви отримаєте

if( whatever )
{
  |  
}

Це також працює для файлу html. Дивіться наступний приклад

<html>|<html>

натисніть Enterі ви отримаєте

<html>
    |
</html>

0

Якщо ви введете {}та натиснете, altiви будете знаходитись між брекетами в INSERTрежимі (принаймні в терміналі). Потім ви можете натиснути, ENTERа потім altshiftoвставити розрив рядка. Ви також можете просто зробити {<CR>}і altshifto.

Це може бути не повністю автоматично, але я вважаю це напівавтоматичним. Це позбавляє від необхідності використовувати додаткові модулі та корисну інформацію для інших випадків використання. Наприклад, я використовую altshiftoвесь час, щоб вставляти порожні рядки без явного виходу з INSERTрежиму, а також altiдля потрапляння всередину ()тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.