Этот ответ здесь, чтобы 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 :call Comment()
Как это работает:
let b:commentChar='//'
:Это создает переменную в vim. b
здесь относится к области, которая в данном случае содержится в буфере, то есть к текущему открытому файлу. Ваши символы комментариев являются строками и должны быть заключены в кавычки, кавычки не являются частью того, что будет заменено при переключении комментариев.
autocmd BufNewFile,BufReadPost *...
:Автокоманды срабатывают по разным причинам, в данном случае они срабатывают, когда новый файл или прочитанный файл заканчиваются определенным расширением. После запуска выполните следующую команду, которая позволяет нам изменить commentChar
в зависимости от типа файла. Есть и другие способы сделать это, но они больше запутывают новичков (вроде меня ).
function! Docomment()
:Функции объявляются начиная с function
и заканчивая endfunction
. Функции должны начинаться с большой буквы. !
гарантирует, что эта функция перезапишет любые предыдущие функции, определенные как Docomment()
с этой версией Docomment()
. Без !
у меня были ошибки, но это могло быть из-за того, что я определял новые функции через командную строку vim.
execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
:Execute вызывает команду. В этом случае мы выполняем 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
:vnoremap
означает отображение следующей команды в визуальном режиме, но не отображать ее рекурсивно (означает, что не следует изменять никакие другие команды, которые могут использоваться другими способами ). По сути, если вы новичок в vim, всегда используйте noremap
, чтобы ничего не сломать.
означает «Мне не нужны ваши слова, только ваши действия» и указывает не выводить ничего в командную строку.
- это то, что мы отображаем, в данном случае это ctrl+r (обратите внимание, что вы все еще можете использовать C -r в обычном режиме для «повторить» в обычном режиме с этим сопоставлением ). C-u
немного сбивает с толку, но в основном это гарантирует, что вы не потеряете визуальную подсветку (в соответствии с этот ответ заставляет вашу команду начинаться с '<,'>
, что нам и нужно ). call
здесь просто говорит vim выполнить названную нами функцию, а
относится к нажатию кнопки enter
. Нам нужно нажать ее один раз, чтобы действительно вызвать функцию (, иначе мы только что набрали call function()
в командной строке, и нам нужно нажать ее еще раз, чтобы наши заменители прошли весь путь (не совсем так. конечно почему, но что угодно ).
В любом случае, надеюсь, это поможет. Это займет все, что выделено с помощью v
, V
или C-v
, проверьте, прокомментирована ли первая строка, если да, попробуйте раскомментировать все выделенные строки, а если нет, добавьте дополнительный слой символов комментариев к каждой линия. Это мое желаемое поведение; Я не просто хотел, чтобы он переключал, была ли прокомментирована каждая строка в блоке или нет, поэтому он отлично работает для меня после множественных вопросов по теме .
Он установлен в /usr/sbin/tcpdump
, поскольку предполагается, что tcpdump
работает от имени пользователя root или с эквивалентными привилегиями.
Чтобы убедиться в этом, вы можете использовать dpkg -L
, чтобы показать, где на диске находятся установленные файлы:
$ dpkg -L tcpdump
/.
/etc
/etc/apparmor.d
/etc/apparmor.d/usr.sbin.tcpdump
/usr
/usr/sbin
/usr/sbin/tcpdump <- Here it is !
/usr/share
/usr/share/doc
/usr/share/doc/tcpdump
...
Итак, вы можете либо
sudo tcpdump
от имени обычного пользователя или tcpdump
или /usr/sbin
в переменную окружения PATH