Какой быстрый способ комментировать / раскомментировать строки в Vim?


1173

У меня есть файл кода Ruby, открытый в vi, есть строки с комментариями #:

class Search < ActiveRecord::Migration
  def self.up
    # create_table :searches do |t|
    #   t.integer :user_id
    #   t.string :name
    #   t.string :all_of
    #   t.string :any_of
    #   t.string :none_of
    #   t.string :exact_phrase
    # 
    #   t.timestamps
    # end
  end

  def self.down
    # drop_table :searches
  end
end

Скажем, я хочу раскомментировать все строки в первом def ... endразделе. Какой эффективный способ сделать это в Vim?

В общем, я ищу простой и плавный способ комментировать и раскомментировать строки. Здесь я имею дело с кодом Ruby, но это может быть JavaScript ( //) или Haml ( -#).


20
Принятый ответ должен быть заменен одним из ответов с подробными инструкциями о том, как выполнять комментирование / раскомментирование блоков без использования плагина. Текущий принятый ответ в основном только ссылка на сторонний плагин.
faintsignal

Ответ с лучшим рейтингом не содержит никаких плагинов, @rationalis ваш комментарий вводит в заблуждение, пожалуйста, исправьте его или удалите, спасибо.
бонобо

Ответы:


181

Я использую скрипт NERD Commenter . Это позволяет вам легко комментировать, раскомментировать или переключать комментарии в вашем коде.

Как уже упоминалось в комментариях :

для любого, кто смущен использованием, лидер по умолчанию - "\", поэтому 10 \ cc прокомментирует десять строк, а 10 \ cu раскомментирует эти десять строк


Интересно! Я читаю Док и нахожу там "сексуальный комментарий" - просто используйте "\ cs". Для Ruby он будет использовать =beginи =endкомментировать несколько строк вместо хеш-тегов.
Хегвин

Я думаю, что это не самый быстрый способ сделать это с vim, так как для этого требуется установить плагин. Также лучший ответ уже получил больше голосов, но он не был помечен как решение.
Whirmill

139
Не останавливайся здесь. Большинство проголосовавших ответов приведены ниже без каких-либо плагинов. stackoverflow.com/a/15588798/2117868 и stackoverflow.com/a/1676690/2117868
kuttumiah

@ whirmill Я думаю, что «лучший» действительно зависит от варианта использования. Режим визуального блока работает быстрее, если я хочу один раз в жизни переключать комментарии. Но если я не возражаю против установки плагина и хочу сделать как можно меньше нажатий клавиш, чтобы переключать комментарии, и не нужно различать операции между добавлением или удалением комментариев - тогда это может быть «лучшим ответом».
Кэрол

@Carolus Я бы согласился с вами, если бы вопрос начинался с «как лучше», а не «как быстро».
Whirmill

2547

Для этих задач я использую большую часть выбора временного блока .

Наведите курсор на первый #символ, нажмите CtrlV(или CtrlQдля gVim) и спускайтесь до последней прокомментированной строки и нажмите x, чтобы удалить все #символы по вертикали.

Для комментирования блок текста практически одинаков:

  1. Сначала перейдите к первой строке, которую вы хотите прокомментировать, нажмите CtrlV. Это переведет редактор в VISUAL BLOCKрежим.
  2. Затем с помощью клавиши со стрелкой и выберите до последней строки
  3. Теперь нажмите ShiftI, чтобы перевести редактор в INSERTрежим, а затем нажмите# . Это добавит хеш к первой строке.
  4. Затем нажмите Esc(дайте ему секунду), и он вставит #символ во все остальные выделенные строки.

Для урезанной версии vim, поставляемой с debian / ubuntu по умолчанию, введите : s/^/#третий шаг (любое оставшееся выделение первого символа каждой строки можно удалить с помощью :nohl).

Вот две маленькие записи экрана для наглядности.

Комментарий: Комментарий

Раскоментируйте: Раскоментируйте


87
По умолчанию это CTRL + V. Версия gvim для Windows использует Ctrl + Q, потому что Ctrl + V уже используется для вставки.
Р. Мартиньо Фернандес

8
@amindfv Ctrl + V, n(где n - количество строк - 1), j, n(где n - количество длин последовательности символов комментария - 1), l, x.
Майкл Бартнетт

28
Как бы вы сделали это с «//»?
Остин

74
Вы можете нажать Esc два раза, чтобы не ждать этой секунды;)
Ахмед Хегази

45
Это не сработало для меня. Shift-я перешел в простой режим вставки.
Геремия,

829

Чтобы закомментировать блоки в vim:

  • нажмите Esc(чтобы выйти из режима редактирования или другого режима)
  • хит ctrl+ v(режим визуального блока)
  • используйте клавиши со стрелками /, чтобы выбрать строки, которые вы хотите (это не будет выделять все - все в порядке!)
  • Shift+ i(заглавная I)
  • вставьте нужный текст, например %
  • Нажмите EscEsc

Чтобы раскомментировать блоки в vim:

  • нажмите Esc(чтобы выйти из режима редактирования или другого режима)
  • хит ctrl+ v(режим визуального блока)
  • используйте клавиши со стрелками /, чтобы выбрать строки для раскомментирования.

    Если вы хотите выбрать несколько символов, используйте один или объедините эти методы:

    • используйте клавиши со стрелками влево / вправо, чтобы выбрать больше текста
    • для выделения фрагментов текста используйте клавишу shift+ / стрелка
    • Вы можете повторно нажимать клавиши удаления ниже, как обычная кнопка удаления

  • нажмите dили, xчтобы удалить символы, при необходимости повторно

35
@amelia: ярлык комментирования не работает для меня. Shift + я взял меня, чтобы вставить режим. Зависит ли это от версии vim?
user3527975

7
Почему это занимает секунду?
Конор Патрик

24
Единственная проблема, с которой я сталкиваюсь в этом ответе, заключается в том, что он говорит вам использовать клавиши со стрелками .
cozyconemotel

6
Вместо этого дважды нажмите Esc. :)
Аарон Альфонс

22
Сначала включение комментариев не сработало для меня, но после прочтения это снова сработало: 1. убедитесь, что вы используете Ctrl-V, а не V для выделения 2. при вставке вы увидите, что вы изменяете только одну строку 3. все вставки происходят, когда вы
нажимаете

336

Иногда я лежу в удаленной коробке, где мои плагины и .vimrc не могут мне помочь, или иногда NerdCommenter ошибается (например, JavaScript встроен в HTML).

В этих случаях низкотехнологичной альтернативой является встроенная normкоманда, которая просто запускает любые произвольные команды vim в каждой строке в указанном вами диапазоне. Например:

Комментируя с # :

1. visually select the text rows (using V as usual)
2. :norm i#

Это вставляет «#» в начале каждой строки. Обратите внимание, что при вводе: диапазон будет заполнен, поэтому он действительно будет выглядеть:'<,'>norm i#

Раскомментировать # :

1. visually select the text as before (or type gv to re-select the previous selection)
2. :norm x

Это удаляет первый символ каждой строки. Если бы я использовал комментарий из двух символов, например //, я бы просто :norm xxудалил оба символа.

Если комментарии с отступом, как в вопросе OP, вы можете закрепить удаление следующим образом:

:norm ^x

что означает «перейти к первому непробельному символу, затем удалить один символ». Обратите внимание, что в отличие от выбора блока, этот метод работает, даже если комментарии имеют неравные отступы!

Примечание : сnorm буквально просто выполняются обычные команды vim, вы не ограничены комментариями, вы также можете сделать несколько сложных изменений для каждой строки. Если вам нужен escape-символ как часть вашей последовательности команд, введите ctrl-v, затем нажмите клавишу escape (или даже проще, просто запишите быстрый макрос и затем используйте norm для выполнения этого макроса в каждой строке).

Примечание 2 : Конечно, вы также можете добавить отображение, если вы используете normмного. Например, поместив следующую строку в ~ / .vimrc, вы сможете печатать ctrl-nвместо :normтого, чтобы делать визуальный выбор

vnoremap <C-n> :norm

Примечание 3 : Vim иногда не имеетnorm команды, скомпилированной в нее, поэтому обязательно используйте расширенную версию, т.е. обычно / usr / bin / vim, а не / bin / vi

(Спасибо @Manbroski и @rakslice за улучшения, включенные в этот ответ)


Я думал, что это был путь, пока я не прокрутил, чтобы прочитать этот ответ stackoverflow.com/a/1676690/850996 Выбор блока с помощью CTRL + V (в отличие от выбора строки с помощью SHIFT + V) дает намного более хороший контроль над тем, где комментарий вставка символов происходит.
Shyam Habarakada

2
@Shyam Техника ctrl-v в сочетании со специальными командами только для выбора блоков - это то, что рекомендует большинство других ответов; однако лично я нахожу описанную мной технику «нормы» более простой, поскольку она не вводит никакого нового синтаксиса, кроме самой команды нормы, поэтому я могу использовать то, что я уже знаю о vim.
Магнус

2
Полезно сказать, что для раскомментирования отступа блока :norm ^x. Этот метод в целом имеет преимущество работы с областями выбора (например vi{, выберет фигурные скобки). Такие селекторы текстовых объектов не работают с Visual Block.
Иван-к

1
Ах, я только что разобрался - на centos 6 /bin/viесть vim 7.2, но он отличается от сборки /usr/bin/vim, и у него такие функции отключены.
Ракслице

4
Это, безусловно, лучший ответ. Особенно в сочетании с vipвыбором целого абзаца.
Мех

122

У меня есть следующее в моем .vimrc:

" Commenting blocks of code.
autocmd FileType c,cpp,java,scala let b:comment_leader = '// '
autocmd FileType sh,ruby,python   let b:comment_leader = '# '
autocmd FileType conf,fstab       let b:comment_leader = '# '
autocmd FileType tex              let b:comment_leader = '% '
autocmd FileType mail             let b:comment_leader = '> '
autocmd FileType vim              let b:comment_leader = '" '
noremap <silent> ,cc :<C-B>silent <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:nohlsearch<CR>
noremap <silent> ,cu :<C-B>silent <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:nohlsearch<CR>

Теперь вы можете набрать, ,ccчтобы прокомментировать строку и ,cuраскомментировать строку (работает как в обычном, так и в визуальном режиме).

(Я украл его с какого-то сайта много лет назад, поэтому я не могу полностью объяснить, как он работает :). Есть комментарий, где это объясняется.)


Какой ярлык я должен использовать? Я не совсем уверен в самом коде vim!
Гидеон

в обычном или визуальном режиме используйте «, cc» (последовательность из 3 символов), чтобы прокомментировать текущую строку, и «, cu», чтобы раскомментировать текущую строку.
Дан

8
мне это нравится :)! Спасибо! С другой стороны, мне не трудно это объяснить. а) он переназначает команду (не рекурсивно [см. это] ( stackoverflow.com/questions/3776117/… )), поэтому теперь, когда вы нажимаете, cc the: ... вещь выполняется. b) теперь это в основном sed (s Команда / what / towhat / where) изменяет ^ (начало строки) на правильно заданный символ комментария в зависимости от типа файла, который вы открыли в), а для скрытых вещей они просто подавляют вывод команд. d): nohlsearch останавливает выделение поиска sed
ramrunner

14
Обратите внимание, что это неправильный способ загрузки автокоманд. Они должны быть внутри группы, иначе они будут добавлены в vim несколько раз, что приведет к значительному замедлению. См .: learnvimscriptthehardway.stevelosh.com/chapters/14.html . Я добавил свой ответ на этот вопрос.

Ницца. Это фактический ответ на мой вопрос о том, как (не) комментировать, пока у вас есть выбор блока.
Эрвин Ройяккерс

120

Укажите, какие строки комментировать в vim:

Покажите номера строк:

:set number

тогда

:5,17s/^/#/     this will comment out line 5-17

или это:

:%s/^/#/        will comment out all lines in file

11
Так как вы просто меняете 1-й символ в каждой строке, вам не нужна буква "g" в конце
Магнус

1
Некоторые vims на встроенных коробках (например, openwrt) не имеют визуального режима .. Так что это
чертовски круто

Вы можете объяснить, почему :%s/^/#/gзакомментируйте все строки? Мне было интересно знак процента%
Бен

18
И чтобы раскомментировать эти строки, вы можете написать: 5,17s / ^ # /
Ираклис Мутидис

Большой! Это действительно хорошо работает с выбором блоков, например: va{или с varрубином.
Артур Малецкий

58

Вот как я это делаю:

  1. Перейти к первому символу в первой строке, которую вы хотите закомментировать.

  2. Нажмите Ctrl+ qв GVIM или Ctrl+ vв VIM, затем нажмите вниз, чтобы выбрать первый символ в строках для комментариев.

  3. Затем нажмите cи добавьте символ комментария.

Раскомментирование работает так же, просто введите пробел вместо символа комментария.


44
cудаляет также первый символ. Ответ CMS имеет правильное значение, то есть нажатие, Iзатем ввод символов комментария и затем Esc(это на windows vim)
Samaursa

6
Это работает, за исключением того, что на третьем шаге нужно нажать «r», а не «c».
Дэвид Баукум

в качестве альтернативы вы можете нажать ESCдважды после нажатия, cи это должно сделать трюк
nihiser

Все эти параметры разрушительны для первого символа в строке.
Иосия

36

Я придумала простое дополнение к моему файлу .vimrc, которое работает довольно хорошо и может быть легко расширено. Вы просто добавляете новый тип файла в comment_map и его лидер комментариев.

Я добавил отображение в обычный и визуальный режимы, но вы можете переназначить все что угодно. Я предпочитаю использовать только функцию стиля «тумблер». Один имеет несколько отображений и т. Д.

let s:comment_map = { 
    \   "c": '\/\/',
    \   "cpp": '\/\/',
    \   "go": '\/\/',
    \   "java": '\/\/',
    \   "javascript": '\/\/',
    \   "lua": '--',
    \   "scala": '\/\/',
    \   "php": '\/\/',
    \   "python": '#',
    \   "ruby": '#',
    \   "rust": '\/\/',
    \   "sh": '#',
    \   "desktop": '#',
    \   "fstab": '#',
    \   "conf": '#',
    \   "profile": '#',
    \   "bashrc": '#',
    \   "bash_profile": '#',
    \   "mail": '>',
    \   "eml": '>',
    \   "bat": 'REM',
    \   "ahk": ';',
    \   "vim": '"',
    \   "tex": '%',
    \ }

function! ToggleComment()
    if has_key(s:comment_map, &filetype)
        let comment_leader = s:comment_map[&filetype]
        if getline('.') =~ "^\\s*" . comment_leader . " " 
            " Uncomment the line
            execute "silent s/^\\(\\s*\\)" . comment_leader . " /\\1/"
        else 
            if getline('.') =~ "^\\s*" . comment_leader
                " Uncomment the line
                execute "silent s/^\\(\\s*\\)" . comment_leader . "/\\1/"
            else
                " Comment the line
                execute "silent s/^\\(\\s*\\)/\\1" . comment_leader . " /"
            end
        end
    else
        echo "No comment leader found for filetype"
    end
endfunction


nnoremap <leader><Space> :call ToggleComment()<cr>
vnoremap <leader><Space> :call ToggleComment()<cr>

Замечания:

Я не использую обратные вызовы или хуки для типов файлов / загрузки, потому что я считаю, что они замедляют запуск Vim больше, чем .vimrcстатическая функция / карта, но это только мои предпочтения. Я также пытался сделать это простым и производительным. Если вы используете автокоманды, вы должны обязательно поместить их в группу автокоманд, иначе обратные вызовы будут добавлены к типу файла несколько раз для каждого загруженного файла и вызовут значительное снижение производительности.


1
Я абсолютно новичок в vim, какую кнопку я должен нажать, чтобы переключить сопоставленную функцию? Что это за <leader><Space>декларация внизу?
Йенс Коля

2
Вы можете заменить <leader> ключом вроде <,>. Затем вы нажимаете, ПРОБЕЛ, и это переключит состояние комментария строки. Лидер, каким бы ни был ваш лидер, по умолчанию <Vim> по умолчанию является Vim, но вы можете установить свой собственный, например, «let mapleader = ','»

Отличный ответ, хотя одно раздражение, комментируя блоки, у которых уже есть некоторые комментарии, поменяется местами закомментированные строки без комментариев. QtCreator, например, удаляет комментарии только в том случае, если все непустые строки имеют начальные комментарии, в противном случае добавьте ведущий комментарий.
ideasman42

1
Я сделал немного другую версию , используя \zsи \zeрегулярное выражение трюк, код стал немного меньше. Вы можете увидеть это здесь
SergioAraujo

33

Переключить комментарии

Если все, что вам нужно, это переключать комментарии, я бы предпочел использовать commentary.vim от tpope .

введите описание изображения здесь

Установка

Возбудитель:

cd ~/.vim/bundle
git clone git://github.com/tpope/vim-commentary.git

ВИМ-штекер:

Plug 'tpope/vim-commentary'

Vundle:

Plugin 'tpope/vim-commentary'

Дальнейшая настройка

Добавьте это в ваш файл .vimrc: noremap <leader>/ :Commentary<cr>

Теперь вы можете переключать комментарии, нажимая Leader+ /, как Sublime и Atom.


Спасибо! собирается ли он поддерживать комментирование CSS внутри HTML когда-нибудь в будущем?
Дэн Оук

25

Используйте Control-V для выбора прямоугольников текста: перейдите к первому #символу, введите Ctrl+ V, переместитесь вправо один раз, а затем вниз, до конца комментариев. Теперь введите x: вы удаляете все #символы, за которыми следует один пробел.


18

Вот мой раздел .vimrc:

"insert and remove comments in visual and normal mode
vmap ,ic :s/^/#/g<CR>:let @/ = ""<CR>
map  ,ic :s/^/#/g<CR>:let @/ = ""<CR>
vmap ,rc :s/^#//g<CR>:let @/ = ""<CR>
map  ,rc :s/^#//g<CR>:let @/ = ""<CR>

В обычном и визуальном режиме это позволяет мне нажимать, ,icчтобы вставлять комментарии и ,rcудалять комментарии.


Это очень полезно для начинающего, как научиться писать самостоятельно .vimrc.
самое крутое

3
mapохватывает нормальный и визуальный режимы, поэтому вам не нужны vmapлинии
doubleDown

Лучшее место в after/ftplugin/ruby.vim.
Сантош Кумар

также использовать <leader>icи<leader>rc
Ганс Кристиан

16

Я использую vim 7.4, и это работает для меня.
Предполагая, что мы комментируем / раскомментируем 3 строки.

Комментировать:

если линия не имеет вкладки / пространство в начале:
ctrl + Vто jjjтогда shift + I (cappital i)то //тогда , esc esc
если линия имеет вкладку / пространство в начале , вы все еще можете сделать выше или замены для c:
ctrl + Vзатем jjjзатем cзатем //затем esc esc

раскомментировать:

если строки не имеют табуляции / пробела в начале:
ctrl + Vтогда jjjтогда ll (lower cap L)тогдаc

если линии имеют вкладки / пространство в начале, то пространство над одним и esc
ctrl + Vзатем jjjзатем ll (lower cap L)затем cзатем spaceзатемesc



9

С 30 ответами передо мной, я попытаюсь дать еще более простое решение: вставьте #в начале строки. Затем идите вниз по линии и нажмите точку ( .). Чтобы повторить, не j, ., j, .и т.д. ... раскомментировать, удалить #(вы можете нажать xнад #), и сделать обратное с помощью k, .и т.д. ...


1
Это очень простой ответ, который даже начинающий может понять и использовать. Тем не менее, он работает довольно медленно на большом количестве строк для комментариев. Чтобы обойти это, вы можете записать I#<Esc>jв буфер - скажем, c- и затем сделать 10@c, или сколько угодно строк.
Daerdemandt

9

Как раскомментировать следующие три строки в vi:

#code code
#code
#code code code

Поместите курсор на верхний левый #символ и нажмите CtrlV. Это переводит вас в режим визуального блока. Нажмите стрелку вниз или Jтри раза, чтобы выбрать все три строки. Затем нажмите D. Все комментарии исчезают. Чтобы отменить, нажмите U.

Как прокомментировать следующие три строки в vi:

code code
code
code code code

Наведите курсор на верхний левый символ, нажмите CtrlV. Это переводит вас в режим визуального блока. Нажмите или Jтри раза, чтобы выбрать все три строки. Затем нажмите:

I//Esc

Это заглавная буква I, // и Escape.

При нажатии ESCвсе выделенные строки получат обозначенный вами комментарий.


1
если вы пропустили «верхний левый» хеш, вы можете нажать o , чтобы переместить курсор в «другую сторону» в визуальном режиме.
Dylnmc

Я думаю, что это лучше всего использовать. Не нужно никаких третьих лиц, просто используйте родной vim
Ardi Nusawan

Лучший ответ, просто и без каких - либо третьих лиц
AZE

8

Да, на этот вопрос уже есть 33 (в основном повторяющихся) ответа.

Вот еще один подход к тому, как комментировать строки в Vim: движения . Основная идея заключается в том, чтобы закомментировать или раскомментировать строки, используя тот же метод, что и для извлечения абзаца, набрав yipили удалив 2 строки, набрав dj.

Этот подход позволит вам делать такие вещи, как:

  • ccjзакомментировать следующие 2 строки и cukраскомментировать их;

  • cci{закомментировать блок и cui{раскомментировать его;

  • ccipзакомментировать целый абзац и cuipраскомментировать его.

  • ccGзакомментировать все до последней строки и cuggраскомментировать все до первой строки.

Все, что вам нужно, это 2 функции, которые работают с движениями , и 2 сопоставления для каждой функции. Во-первых, сопоставления:

nnoremap <silent> cc  :set opfunc=CommentOut<cr>g@
vnoremap <silent> cc  :<c-u>call  CommentOut(visualmode(), 1)<cr>
nnoremap <silent> cu  :set opfunc=Uncomment<cr>g@
vnoremap <silent> cu  :<c-u>call  Uncomment(visualmode(), 1)<cr>

(См. Руководство об g@операторе иoperatorfunc переменной.)

А теперь функции:

function! CommentOut(type, ...)
  if a:0
    silent exe "normal!  :'<,'>s/^/#/\<cr>`<"
  else
    silent exe "normal!  :'[,']s/^/#/\<cr>'["
  endif
endfunction

function! Uncomment(type, ...)
  if a:0
    silent exe "normal!  :'<,'>s/^\\(\\s*\\)#/\\1/\<cr>`<"
  else
    silent exe "normal!  :'[,']s/^\\(\\s*\\)#/\\1/\<cr>`["
  endif
endfunction

Измените приведенные выше регулярные выражения на свой вкус и укажите, где они #должны быть:


«совершенно новые [...] движения» кажутся немного чрезмерными: плагины t_comment и vim-commentary, предшествующие этому ответу, позволяют комментировать, используя движения.
Богатый

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

7

Если вы уже знаете номера строк, то n,ms/# //будет работать.


на самом деле это должно быть: n, ms / ^ \ s. # // Потому что у вас может быть начальный пробел и вы не можете следовать за хешем с одним
Пропустить Хаффман

7

Я отмечаю первую и последнюю строки (ma и mb), а затем делаю: 'a,' bs / ^ # //


6

Я использую EnhancedCommentify . Он комментирует все, что мне нужно (языки программирования, скрипты, файлы конфигурации). Я использую его с привязками в визуальном режиме. Просто выделите текст, который вы хотите прокомментировать, и нажмите co / cc / cd.

vmap co :call EnhancedCommentify('','guess')<CR>
vmap cc :call EnhancedCommentify('','comment')<CR>
vmap cd :call EnhancedCommentify('','decomment')<CR> 

5

Я объединил ответ Фила и jqno и оставил комментарий без пробелов:

autocmd FileType c,cpp,java,scala let b:comment_leader = '//'
autocmd FileType sh,ruby,python   let b:comment_leader = '#'
autocmd FileType conf,fstab       let b:comment_leader = '#'
autocmd FileType tex              let b:comment_leader = '%'
autocmd FileType mail             let b:comment_leader = '>'
autocmd FileType vim              let b:comment_leader = '"'
function! CommentToggle()
    execute ':silent! s/\([^ ]\)/' . b:comment_leader . ' \1/'
    execute ':silent! s/^\( *\)' . b:comment_leader . ' \?' . b:comment_leader . ' \?/\1/'
endfunction
map <F7> :call CommentToggle()<CR>

5

Существует изменения плагина, эта жизнь tpopeназываетсяvim-commentary

https://github.com/tpope/vim-commentary

Этот плагин обеспечивает :

  • вменяемость
  • Правильно отступленные комментарии
  • Не комментирует пустые / ненужные строки

Использование :

  • Установить через Vundle (или, я думаю, Pathogen).
  • Выделите ваш текст и нажмите, :который будет отображаться как:<,'>
  • Введите комментарий здесь :<,'>Commentaryи нажмите Enter.
  • Boom. Твой готовый бутон.

vim-commentary(как и все плагины tpope) имеет преимущество быть идиоматическим vim. gc= "комментировать", gcap= "комментировать абзац" и т. д.
goldenratio

Могло ли это быть редактированием ответа Дима Стюарта, написанного Тимом Папой?
jdk1.0

5

Этот ответ наиболее полезен, если вы не можете установить плагины, но по-прежнему хотите, чтобы символы комментариев соответствовали существующим уровням отступов.

Этот ответ здесь: 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>entercall function() в командной строке, и нам нужно нажать ее снова, чтобы наши заменители прошли весь путь (не совсем понятно, почему, но как угодно).

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



3

Вы можете использовать vim-comment по tpope ( https://github.com/tpope/vim-commentary ), вы можете использовать его следующим образом:

Войдите в визуальный режим, нажав

'v'

Затем нажмите

'j' repeatedly or e.g 4j to select 4 row

Теперь все, что вам нужно сделать с выбором, это клавиши ввода:

'gc'

Это закомментирует весь выбор, чтобы раскомментировать повторные ключи:

'gc'

3

Вот основной однострочник на основе C-vследующихI методом , описанным выше.

Эта команда ( :Comment) добавляет выбранную строку в начало любых выбранных строк.

command! -range -nargs=1 Comment :execute "'<,'>normal! <C-v>0I" . <f-args> . "<Esc><Esc>"

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

Например, если выбран следующий текст:

1
2

и вы запустите это:, :Comment //результат будет:

//1
//2

3

Начав с идей в ответах здесь, я запустил собственную функцию комментирования. Он включает и выключает комментарии. Он может обрабатывать такие вещи, как //print('blue'); //this thing is blueи просто переключает первый комментарий. Кроме того, он добавляет комментарии и один пробел именно там, где находится первый не пробел, а не в самом начале строки. Кроме того, он не копирует пробелы без необходимости, а использует масштабирование (: h \ zs для справки), чтобы избежать этой дополнительной работы, при комментировании и отступе строки. Надеюсь, это поможет некоторым минималистам. Предложения приветствуются.

" these lines are needed for ToggleComment()
autocmd FileType c,cpp,java      let b:comment_leader = '//'
autocmd FileType arduino         let b:comment_leader = '//'
autocmd FileType sh,ruby,python  let b:comment_leader = '#'
autocmd FileType zsh             let b:comment_leader = '#'
autocmd FileType conf,fstab      let b:comment_leader = '#'
autocmd FileType matlab,tex      let b:comment_leader = '%'
autocmd FileType vim             let b:comment_leader = '"'

" l:pos   --> cursor position
" l:space --> how many spaces we will use b:comment_leader + ' '

function! ToggleComment()
    if exists('b:comment_leader')
        let l:pos = col('.')
        let l:space = ( &ft =~ '\v(c|cpp|java|arduino)' ? '3' : '2' )
        if getline('.') =~ '\v(\s*|\t*)' .b:comment_leader
            let l:space -= ( getline('.') =~ '\v.*\zs' . b:comment_leader . '(\s+|\t+)@!' ?  1 : 0 )
            execute 'silent s,\v^(\s*|\t*)\zs' .b:comment_leader.'[ ]?,,g'
            let l:pos -= l:space
        else
            exec 'normal! 0i' .b:comment_leader .' '
            let l:pos += l:space
        endif
        call cursor(line("."), l:pos)
    else
        echo 'no comment leader found for filetype'
    end
endfunction

nnoremap <Leader>t :call ToggleComment()<CR>
inoremap <Leader>t <C-o>:call ToggleComment()<CR>
xnoremap <Leader>t :'<,'>call ToggleComment()<CR>

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

Круто. Вы можете отредактировать мой пост и добавить свое решение (из-за сходства)!
Майк

Это изменилось, чтобы избежать обратной косой черты c, cpp, java и использования другого разделителя в подстановках, чтобы избежать E488. Также меняется интервал для java, cpp, потому что комментарии имеют три символа, // плюс пробел, это делает l: space.
SergioAraujo,

3

Я использую comments.vim от Jasmeet Singh Anand (найдена на vim.org),

Работает с C, C ++, Java, PHP [2345], proc, CSS, HTML, htm, XML, XHTML, vim, vimrc, SQL, sh, ksh, csh, Perl, tex, fortran, ml, caml, ocaml, VHDL, HASKEL и нормальные файлы

Он комментирует и не комментирует строки в разных исходных файлах как в обычном, так и в визуальном режиме.

Применение:

  • CtrlCчтобы прокомментировать одну строку
  • CtrlXдля ООН-комментарии в одну строку
  • ShiftVи выберите несколько строк, CtrlCчтобы прокомментировать выбранные несколько строк
  • ShiftVи выберите несколько строк, CtrlXчтобы откомментировать выбранные несколько строк

3

Самый быстрый и интуитивно понятный из всех этих методов - это переназначение )для комментирования строк, а затем (для раскомментирования. Попробуйте, и вы не вернетесь.

В Ruby или Bash с двумя пробелами:

map ) I# <Esc>j
map ( k^2x

В C / C ++ или PHP с отступами в 4 пробела:

map ) I//  <Esc>j
map ( k^4x

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

А для C-стиля длинные комментарии лучше всего обрабатывать с помощью:

set cindent
set formatoptions=tcqr

... Который хорошо сочетается с использованием, V[move]gqчтобы переделать перенос слов.


2

Этот простой фрагмент взят из моего .vimrc:

function! CommentToggle()
    execute ':silent! s/\([^ ]\)/\/\/ \1/'
    execute ':silent! s/^\( *\)\/\/ \/\/ /\1/'
endfunction

map <F7> :call CommentToggle()<CR>

Это для // - Комментарии, но вы можете легко адаптировать его для других персонажей. Вы можете использовать autocmd для установки лидера, как предложено jqno.

Это очень простой и эффективный способ естественной работы с диапазонами и визуальным режимом.


2

Мне нравится /* ... */(комментирует), так что вот мой трюк для вас. Конечно, вы можете адаптировать его для использования в разных случаях.


Комментарий с / * ... * /

Выделите текст (перейти к началу, запустить визуальный блок, перейти с помощью }):

<c-V>}

Введите команду, которая будет применена в выборе

:norm i/* <c-v><esc>$a */

Команда будет выглядеть так: :'<,'>norm i /* ^[$a */

Смотрите (i *) для деталей.


Раскомментируйте / * ... * /

Выделите текст (как и раньше или другим способом):

<c-V>}

Введите команду, которая будет применена в выборе

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

Команда будет выглядеть так: :'<,'>norm :s-\s*/\*\s*-^M$bbld$

Смотрите (ii *) для деталей.


Результат

Эффект - комментарии построчно:

Comment block
Comment block
Comment block

Становится (и наоборот):

/* Comment block */
/* Comment block */
/* Comment block */

Лучше сохранить это как часть mapили @regв вашем .vimrc, потому что это много, чтобы напечатать. Если вы предпочитаете один /*и */весь блок, используйте:

Комментарий с одним / * * / целым блоком

Сохраните его в реестре, записав, скажем qc, затем в начале абзаца комментарий:

v}di/*  */<esc>hhhp

и не забудьте qснова, чтобы закончить запись.

Смотрите (iii *) для деталей.


Раскомментировать один / * * / из блока

Сохранить его в реестре, скажем, @u. Поместите курсор в любое место внутри блока и:

?/\*<enter>xx/\*/<enter>xx

Сохранить регистр, закончив q команду.

Смотрите (iv *) для деталей.


Результат

Эффект - один комментарий для нескольких строк:

Comment block
Comment block
Comment block

Становится (и наоборот):

/* Comment block
Comment block
Comment block */

Пояснения

(i *) Это работает, используя, normкоторый применяет ту же команду несколько раз в каждой выбранной строке. Команда просто вставляет /*, находит конец этой строки и завершает, вставляя*/

:norm i/* <c-v><esc>$a */

(ii *) Он также используется normдля повторения поиска / замены в каждой строке. Ищите spaces /* spacesи заменяйте ничем. После этого находит конец строки, вернет два слова, справа букву, удалите до конца.

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

(iii *) Выделите абзац v}, удалите его, вставьте открытый и закрытый комментарий, переместитесь в его середину и вставьте удаленный блок.

v}di/*  */<esc>hhhp

(iv *) В любом месте посередине находит назад a /*, удаляет его; находит вперед */, удаляет его.

?/\*<enter>xx/\*/<enter>xx
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.