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()
romainl
источник
Спасибо выглядит отлично! Постараюсь, когда вернусь домой. Знаете ли вы способ расширить регулярное выражение, чтобы сопоставить язык маркеров комментариев независимо? Информация должна быть там в файлах синтаксиса или что-то. Может быть, я могу использовать функцию синтаксиса для этого ...
Патрик 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