Vim: автокоммент в новой строке


9

Vim автоматически вставляет комментарий, когда я начинаю новую строку с закомментированной строки, потому что я установил formatoptions=tcroql. Например (курсор есть *):

// this is a comment*

и после нажатия <Enter>(режим вставки) или o(нормальный режим) я остаюсь с:

// this is a comment
// *

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

  • ударил <Esc>S
  • ударить <BS>три раза

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

// this is a comment
*

Важно, чтобы решение также работало с разными уровнями отступов, т.е.

int main(void) {
    // this is a comment*
}

ударил <Enter>

int main(void) {
    // this is a comment
    // *
}

ударил <Enter>

int main(void) {
    // this is a comment
    *
}

Я думаю, что видел эту функцию в каком-то текстовом редакторе несколько лет назад, но я не помню, какая это была. Кто-нибудь знает решение, которое сделает это для меня в Vim? Указатели в правильном направлении о том, как развернуть мое собственное решение, также очень приветствуются.


3
Вы можете использовать ctrl-u в режиме вставки, чтобы удалить автоматически вставленные маркеры комментариев в одном аккорде.
— Этан Рейснер

1
@EtanReisner это на самом деле лучше, но все же одно нажатие клавиши слишком много для меня, так как это такой распространенный случай использования
— Патрик Осци

Вы предположили, что хотите снова нажать Enter, чтобы получить желаемое поведение, но ctrl-u - это слишком много? Вы можете попытаться отобразить <enter> <enter> в режиме вставки, чтобы автоматически выполнить ctrl-u, но это может привести к задержке, если вы когда-нибудь нажмете <enter> только один раз (не нажимая ничего больше).
— Этан Рейснер

Кроме того, он должен срабатывать только в том случае, если закомментированная строка пуста. Заметная задержка при нажатии <Enter> также недопустима.
— Патрик Осци

Он задержится, если вы не нажмете другие клавиши, которые, я считаю, поскольку vim нужно будет подождать, чтобы убедиться, что вы все еще не планируете нажимать другую клавишу. Я думаю, что вы можете использовать функцию для выполнения этой проверки, хотя это может быть не так просто сделать.
— Этан Рейснер

Ответы:


4

Попробуй это:

function! EnterEnter()
  if getline(".") =~ '^\s*\(//\|#\|"\)\s*$'
    return "\<C-u>"
  else
    return "\<CR>"
  endif
endfunction

imap <expr> <CR> EnterEnter()

Спасибо выглядит отлично! Постараюсь, когда вернусь домой. Знаете ли вы способ расширить регулярное выражение, чтобы сопоставить язык маркеров комментариев независимо? Информация должна быть там в файлах синтаксиса или что-то. Может быть, я могу использовать функцию синтаксиса для этого ...
— Патрик Oscity

Я имею в виду, что в C он должен совпадать с // и / * и * (многострочными комментариями), а с ruby ​​# и т. Д.
— Patrick Oscity

Очевидно, что эта функция не является общей. Смотрите :h 'comment'и :h format-comment'.
— romainl

Функция модифицирована для работы с #ruby и "vimscript в дополнение к классическому //. На самом деле не имеет смысла что-либо делать для *многострочных комментариев в стиле C, потому что все равно должно заканчиваться */.
— romainl

Хм, может быть, <CR><CR>можно использовать для завершения многострочного комментария ...
— romainl

3

Я расширил ответ @ romainl для работы с произвольными языками, сгенерировав регулярное выражение из Vim &commentstring:

function! s:IsOnlyComment(getlineArg)
  let commentRegex='^\s*'.substitute(&commentstring,'%s','\\s*','').'$'
  return strlen(matchstr(getline(a:getlineArg), commentRegex)) > 0
endfunction

function! SmartEnter()
  if s:IsOnlyComment('.')
    return "\<Esc>S"
  else
    return "\<CR>"
  endif
endfunction

inoremap <expr> <CR> SmartEnter()

Тем не менее, я не могу переназначить <CR>вообще, это просто не будет работать. Пока пользуюсь <CR><CR>пока эта проблема не решена.


1
Почему <Esc>S? <C-u>делает то же самое, не выходя из режима вставки. В любом случае, у меня была пользовательская функция, которая выполняла кучу вещей <CR>и переименовала ее SmartEnter()только вчера, после того как я опубликовала свой ответ ;-). Также я не уверен, что &commentstringэто правильный выбор, так как он обычно содержит только одну форму и может быть «linewise» или «blockwise» ( /*%s*/в C, //%sв Javascript и т. Д.).
— romainl

2

Удалить r из 'formatoptions. Это то, что делает этот вариант. Отключение будет означать, что вы никогда не сделаете так, чтобы vim сделал это для вас, а это значит, что вам нужно будет добавить ведущие маркеры комментариев, когда вы действительно их захотите, но это компромисс.


2
Я действительно хочу, чтобы Vim добавил для меня маркеры комментариев, мне это нравится. Но я также хочу быстрый способ выйти из комментария. Спасибо за ваш ответ, хотя.
— Патрик Осцити

Для нормального режима команды 'o' необходимо удалить 'r' изformatoptions
— elig
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.