Как закомментировать набор строк, выбранных в визуальном режиме?

35

Как закомментировать несколько выделенных строк в визуальном режиме? Как мне сделать это конкретным языком?

Например, если выделены первые 4 строки:

def foo(a,b):
    for each in (a,b):
        print each
    return a+b
print "2"

Операция команды / макроса должна привести к этому (в Python):

#def foo(a,b):
#    for each in (a,b):
#        print each
#    return a+b
print "2"
Джон Х.К.
источник

Ответы:

31

Если вы хотите комментировать на конкретном языке, вам понадобится плагин, например, nerdcommenter .

В качестве альтернативы, хотя он не отвечает на ваш реальный вопрос, вы можете использовать встроенные действия vim и свое знание символов комментария каждого языка ...

Вариант № 1: V-блоки

  1. :1 Enter (Перейти к строке 1)
  2. Ctrl-V (режим V-Block)
  3. jjj (Вниз еще 3 строки)
  4. Shift-I (войти в режим вставки перед блоком)
  5. # (Вставьте «#»)
  6. Esc (Вернуться в нормальный режим)

Вариант № 2: Замена

:1,4s/^/#/

Сломать:

  1. : Экс команда следует
  2. 1,4 по строкам с 1 по 4
  3. s замена
  4. /разделитель для частей команды замещения.
    (Вы также можете использовать другой символ, например :)
  5. ^ начало строки
  6. / разделитель
  7. # символ комментария для python
  8. / последний разделитель

Вариант № 3: Повторить применение макроса ( источник )

  1. :1 Enter (Перейти к строке 1)
  2. qa(Начать запись в реестре a)
  3. Shift-I (войти в режим вставки в начале строки
  4. # (Добавьте «#» в начале строки)
  5. Esc (Вернуться в нормальный режим)
  6. q (Остановить запись)

  7. :2,4 normal @a(повторно запустите записанный макрос для регистрации aв строках между 2 и 4)

    ИЛИ

    Вы можете выбрать линии в визуальном режиме и нажать, :чтобы автоматически заполнить строку Ex :'<,'>(диапазон от начала до конца визуального выделения), затем набрать normal @aи нажать Enter( источник ).

Теперь, когда вы хотите прокомментировать некоторые строки, просто перезапустите записанный макрос для регистрации aв этих строках:

:9,22 normal @a (comment out lines 9-22)
bsmith89
источник
1
Вариант 4: Плагин
Cody Poll
Я не понимаю, почему вы используете макрос для одной команды, когда вы можете сделать :9,22 normal I#согласно моему ответу.
Бен
Почему вы используете: 1 <enter>, когда вы можете использовать gg?
Танат
@Tanath Комментирование с первой строки было специфичным для этого примера. Если автор захочет прокомментировать строки с 9 по 22, он не сможет использовать gg.
bsmith89
@ Бен я ничего не знал о normalкоманде до написания этого ответа. Вы правы; :9,22 normal I#будет работать так же.
bsmith89
26

Используя режим Visual Block ( CtrlV), выберите начало строк. Затем нажмите I#(это заглавная буква I), чтобы вставить символ хеша в каждую из этих строк. Затем нажмите Escдля возврата из режима вставки в обычный режим.

200_success
источник
У меня не работает. Он вставляет комментарий только в первой строке.
gon1332
Вы толкаете ctrl? Потому ctrl+vчто это нечто отличное от всего v.
опрос Коди
@CodyPoll Я знаю. Все в порядке до I. Когда я нажимаю I, то #будет помещен только перед первой строкой.
gon1332
@CodyPoll Хорошо .. Я был просто в больнице. Я не нажимал Escпосле описанной процедуры.
gon1332
@ gon1332, насколько я знаю, Escв конце нужно нажать .
Гонсалу Рибейру
18

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

:norm 0i#

делает работу (Для каждой строки в обычном режиме перейдите к первому столбцу и вставьте #. Использование :norm I#будет вставлять его перед первым непробельным символом, что может быть не тем, что вы хотите.) Использование :norm i#также будет работать, потому что :normначинается в начале линия, но она менее четкая и менее понятная, если вы этого не знаете.

Конечно, если вы собираетесь делать это часто, вы захотите настроить отображение или искать плагин.

wchargin
источник
1
0 не требуется, так как по умолчанию normalкоманда выполняется с курсором в начале строки.
нитищ
1
Конечно, с помощью этой команды номера строк,%, отметки могут иметь префикс. Пример:: 1,5norm i # (или): 'a,' bnorm i # (или): 10% норма i #
SibiCoder
9

Чтобы сделать это автоматически, вам потребуется добавить что-то вроде следующего в ваш vimrcфайл ( источник ):

au FileType haskell,vhdl,ada let b:comment_leader = '-- '
au FileType vim let b:comment_leader = '" '
au FileType c,cpp,java let b:comment_leader = '// '
au FileType sh,make let b:comment_leader = '# '
au FileType tex let b:comment_leader = '% '
noremap <silent> ,c :<C-B>sil <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:noh<CR>
noremap <silent> ,u :<C-B>sil <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:noh<CR>

Используется ,cдля комментирования региона и ,uраскомментирования региона. Это вручную устанавливает символы комментария для разных языков.

Второй вариант - использовать такой плагин, как tcomment , vim-commentary или comments.vim . Я сам пользуюсь tcomment. Пожалуйста, прочитайте инструкции по использованию и установке на их страницах, так как я считаю, что это выходит за рамки вопроса.

Я бы посоветовал вам использовать плагин (один из приведенных выше или другой), так как это гораздо проще, чем поддерживать фрагмент кода в вашем vimrcфайле.

Изменить: я удалил ручной путь, как вопрос был изменен, а также правильный ответ 200_success.

tokoyami
источник
Дополнительное предложение для плагина: NERD Commenter - vim.org/scripts/script.php?script_id=1218
предоставлено
Примечание: это поддерживает только комментарии. Например, ANSI C не распознает //(только /* */).
wchargin
Хотя мне нравится этот подход, есть ли способ заставить его переключать комментарии?
ideasman42
1
@ ideasman42 Вместо этого вам нужно создать функцию и проверить, начинается ли текущая строка с комментария, а затем, в зависимости от этого вызова, любой из :sкоманд, показанных в выдержке из ответа. Сам чек будет что-то вроде getline('.') =~ "^" . escape(b:comment_leader, '\/'). Если это правда, раскомментируйте, иначе прокомментируйте. Это не проверено и должно служить только примером.
токоями
5

Я использую scrooloose / nerdcommenter для этого.

С помощью этого плагина вы можете визуально выбирать ваши строки и нажимать leader+, cчтобы переключать комментарии. В зависимости от типа файла для комментирования будут использоваться разные символы.

OrangeTux
источник
5

После того, как вы выбрали строки, просто введите

:norm I#

:автоматически добавит '<,'>в вашу командную строку, которая находится в диапазоне от начала вашего выбора до конца; normвыполняет команду нормального режима и будет действовать в этом диапазоне; I#является командой нормального режима, которая вставляет «#» в начале строки.

Бен
источник
4

Я большой поклонник TComment для этого; я могу не только создавать стили комментариев для конкретных типов файлов, но даже указывать блок против строки для языков, которые поддерживают комментарии блоков.

    gc{motion}   :: Toggle comments (for small comments within one line 
                    the &filetype_inline style will be used, if 
                    defined)
    gcc          :: Toggle comment for the current line

Explicit commenting/uncommenting:

    g<{motion}   :: Uncomment region
    g<c          :: Uncomment the current line
    g<b          :: Uncomment the current region as block

    g>{motion}   :: Comment region
    g>c          :: Comment the current line
    g>b          :: Comment the current region as block

In visual mode:

    gc           :: Toggle comments
    gC           :: Comment selected text
Коллин Грейди
источник
Спасибо за Ваш ответ! Не могли бы вы расширить его? Предоставление плагин-ответов - это хорошо, но сейчас это просто ссылка на плагин. По крайней мере, базовое описание того, что он делает и как его использовать, ожидается в ответе. также см. этот мета-пост .
Мартин Турной
Кажется глупым копировать / вставлять связки клавиш, но все готово; Я уже описал, что он делает.
Коллин Грэди
3

Я нахожу плагин vim-комментария , безусловно, самый простой способ сделать это. Выберите диапазон линий, затем просто нажмите gc. Он будет использовать соответствующий символ комментария для открытого вами типа файла. Даже без визуального выбора можно раскомментировать соседние закомментированные строки с помощью gcuили gcgc.

Эндрю Ферье
источник
2

Предполагая, что вы хотите добавить префикс к 5 строкам в начале строки, вы можете использовать Поиск и замену. :

:.,+5s/^/prefix_/g

или в конце строк:

:.,+5s/$/suffix_/g

Или используйте визуальный режим ( Ctrl+v ), чтобы выбрать вертикальный блок текста, затем войдите в режим вставки ( I), введите что-нибудь и нажмите, Escчтобы подтвердить и применить изменения к другим строкам.

Связанный:

kenorb
источник
2

Этот ответ здесь 1) показать правильный код, чтобы вставить в, .vimrcчтобы получитьvim 7.4+ возможность комментировать / раскомментировать блок, сохраняя уровень отступа с 1 ярлыком в визуальном режиме и 2), чтобы объяснить это.

Вот код:

let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.[ch]    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.cpp    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.py    let b:commentChar='#'
autocmd BufNewFile,BufReadPost *.*sh    let b:commentChar='#'
function! Docomment ()
  "make comments on all the lines we've grabbed
  execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
endfunction
function! Uncomment ()
  "uncomment on all our lines
  execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'
endfunction
function! Comment ()
  "does the first line begin with a comment?
  let l:line=getpos("'<")[1]
  "if there's a match
  if match(getline(l:line), '^\s*'.b:commentChar)>-1
    call Uncomment()
  else
    call Docomment()
  endif
endfunction
vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>

Как это работает:

  • let b:commentChar='//': Это создает переменную в vim. bздесь относится к области, которая в данном случае содержится в буфер, то есть открытый в данный момент файл. Ваши символы комментариев являются строками и должны быть заключены в кавычки, кавычки не являются частью того, что будет подставлено при переключении комментариев.

  • autocmd BufNewFile,BufReadPost *...: Автокоманды запускаются для разных вещей, в этом случае они запускаются, когда новый файл или прочитанный файл заканчивается с определенным расширением. После запуска выполните следующую команду, которая позволяет нам изменитьcommentChar зависимости зависимости от типа файла. Есть и другие способы сделать это, но они больше сбивают с толку новичков (таких как я).

  • function! Docomment(): Функции объявляются, начиная с functionи заканчивая endfunction. Функции должны начинаться с заглавной буквы. что !гарантирует , что эта функция переопределяет все предыдущие функции , определенные как Docomment()с этой версией Docomment(). Без этого у !меня были ошибки, но это могло быть потому, что я определял новые функции через командную строку vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Выполнить вызывает команду. В этом случае мы выполняем substitute, который может принимать диапазон (по умолчанию это текущая строка), например, %для всего буфера или '<,'>для выделенного раздела. ^\s*является регулярным выражением, чтобы соответствовать началу строки, за которой следует любое количество пробелов, которые затем добавляются (из-за &). .Здесь используется для конкатенации, так как escape()не может быть завернуты в кавычки. escape()позволяет вам экранировать символ, commentCharкоторый соответствует аргументам (в данном случае \и /), добавляя их с помощью \. После этого мы снова соединяем конец нашей substituteстроки, который имеетeфлаг. Этот флаг позволяет нам молча потерпеть неудачу, что означает, что если мы не найдем совпадения в данной строке, мы не будем кричать об этом. В целом, эта строка позволяет поставить символ комментария, за которым следует пробел перед первым текстом, что означает, что мы сохраняем наш уровень отступа.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'Это похоже на нашу последнюю огромную длинную команду. У нас есть уникальная возможность \v, которая гарантирует, что нам не нужно избегать наших (), и 1которая относится к группе, которую мы создали с нашей (). По сути, мы сопоставляем строку, начинающуюся с любого количества пробелов, а затем наш символ комментария, за которым следует любое количество пробелов, и мы сохраняем только первый набор пробелов. Опять же, eдавайте молча потерпим неудачу, если у нас нет символа комментария в этой строке.

  • let l:line=getpos("'<")[1]: это устанавливает переменную так же, как мы сделали с нашим символом комментария, но lссылается на локальную область видимости (локальную для этой функции). getpos()получает позицию, в данном случае, начала нашего выделения, и [1]означает, что мы заботимся только о номере строки, а не о других вещах, таких как номер столбца.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1Знаете, как ifработает. match()проверяет, содержит ли первая вещь вторую, поэтому мы берем строку, с которой мы начали выделение, и проверяем, начинается ли она с пробела, за которым следует символ комментария. match()возвращает индекс, где это правда, и -1если совпадений не найдено. Так как ifвсе ненулевые числа оцениваются как истинные, мы должны сравнить наш вывод, чтобы увидеть, больше ли он -1. Сравнение в vimвозвращает 0, если ложь, и 1, если истина, что и ifнужно видеть, чтобы оценить правильно.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapозначает отображать следующую команду в визуальном режиме, но не отображать ее рекурсивно (то есть не изменять никакие другие команды, которые могут использоваться другими способами). По сути, если вы новичок Vim, всегда используйте, noremapчтобы убедиться, что вы не сломать вещи. <silent>означает «Я не хочу ваших слов, только ваши действия» и говорит, что ничего не печатать в командной строке. <C-r>это то, что мы отображаем, в данном случае это ctrl + r (обратите внимание, что вы все равно можете использовать Cr обычно для «повторения» в обычном режиме с этим отображением). C-uэто немного сбивает с толку, но в основном это гарантирует, что вы не потеряете свою визуальную подсветку (в соответствии с этим ответом ваша команда начинает с '<,'>чего мы и хотим).call здесь просто говорит vim выполнить функцию, которую мы назвали, и <cr>ссылается на нажатиеenterкнопка. Мы должны нажать ее один раз, чтобы фактически вызвать функцию (в противном случае мы просто набрали ее call function()в командной строке, и нам нужно нажать ее снова, чтобы наши заменители прошли весь путь (не совсем понятно, почему, но что угодно).

В любом случае, надеюсь, это поможет. Это будет принимать что - либо подсвечены v, Vили C-v, проверить , если первая строка комментариев, если да, попробуйте раскомментировать все выделенные строки, а если нет, добавить дополнительный слой символы комментария к каждой строке. Это мое желаемое поведение; Я не просто хотел, чтобы он переключался независимо от того, была ли прокомментирована каждая строка в блоке или нет, поэтому он отлично работает после того, как я задал несколько вопросов на эту тему.

jeremysprofile
источник