Vim: comentar automaticamente em nova linha

9

O Vim insere automaticamente um comentário quando inicio uma nova linha a partir de uma linha comentada, porque defini formatoptions=tcroql. Por exemplo (o cursor é *):

// this is a comment*

e depois de pressionar <Enter>(modo de inserção) ou o(modo normal), fico com:

// this is a comment
// *

Esse recurso é muito útil ao escrever comentários longos com várias linhas, mas geralmente quero apenas um comentário com uma única linha. Agora, se eu quiser terminar a série de comentários, tenho várias opções:

  • acertar <Esc>S
  • bateu <BS>três vezes

Ambos oferecem três pressionamentos de tecla, somados a <Enter>isso, significam quatro pressionamentos de tecla para uma nova linha, o que eu acho demais. Idealmente, gostaria de apertar <Enter>uma segunda vez para ficar com:

// this is a comment
*

É importante que a solução também funcione com diferentes níveis de indentação, ou seja,

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

acertar <Enter>

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

acertar <Enter>

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

Acho que vi esse recurso em algum editor de texto há alguns anos, mas não me lembro qual era. Alguém está ciente de uma solução que fará isso por mim no Vim? Ponteiros na direção certa sobre como rolar minha própria solução também são muito bem-vindos.

Patrick Oscity
fonte
3
Você pode usar ctrl-u no modo de inserção para excluir os marcadores de comentários inseridos automaticamente em um acorde de tecla.
Etan Reisner 1/11
1
@EtanReisner que é realmente melhor, mas ainda um keystroke demais para mim, pois é um caso de uso comum :)
Patrick Oscity
Você sugeriu que queria pressionar Enter novamente para obter o comportamento desejado, mas ctrl-u é demais? Você pode tentar mapear <enter> <enter> no modo de inserção para executar automaticamente o ctrl-u para você, mas isso introduziria um atraso se você pressionar <enter> apenas uma vez (sem pressionar mais nada).
Etan Reisner 1/11
Além disso, ele deve ser acionado apenas se a linha comentada estiver vazia. Um atraso perceptível ao pressionar <Enter> também é inaceitável.
Patrick Oscity
Só atrasará se você não pressionar nenhuma outra tecla que acredito, pois o vim precisará esperar para garantir que você ainda não esteja planejando pressionar outra tecla. Você também pode usar uma função para executar essa verificação, embora não seja particularmente fácil de executar.
Etan Reisner '

Respostas:

4

Tente o seguinte:

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

imap <expr> <CR> EnterEnter()
romainl
fonte
Obrigado parece ótimo! Tentarei quando eu chegar em casa. Você conhece uma maneira de estender a regex para corresponder ao idioma dos marcadores de comentários independentemente? A informação deve estar lá nos arquivos de sintaxe ou algo assim. Talvez eu possa alavancar o recurso de sintaxe para isso ...
Patrick Oscity
Quero dizer em C deve corresponder // e / * e * (comentários de várias linhas) e em ruby # e assim por diante
Patrick Oscity
Obviamente, essa função não é genérica. Veja :h 'comment'e :h format-comment'.
Romainl
Função modificada para trabalhar com o #ruby e o "vimscript, além do clássico //. Realmente não faz sentido fazer nada pelos *comentários de múltiplas linhas no estilo C, porque deve terminar com o */mesmo.
Romainl #
Hmm, talvez <CR><CR>poderia ser usado para terminar o comentário de várias linhas ...
romainl
3

Estendi a resposta do @ romainl para trabalhar com idiomas arbitrários, gerando o regex do 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()

No entanto, não consigo remapear <CR>, isso simplesmente não funciona. Por enquanto, uso <CR><CR>até que esse problema seja resolvido.

Patrick Oscity
fonte
1
Por que <Esc>S? <C-u>faz o mesmo sem sair do modo de inserção. Enfim, eu tinha uma função personalizada que fazia várias coisas <CR>e a renomei para SmartEnter()ontem, depois de postar minha resposta ;-). Também não tenho certeza de que &commentstringé a escolha certa, pois geralmente contém apenas um formulário e pode ser "em sentido de linha" ou "em sentido de bloco" ( /*%s*/em C, //%sem Javascript etc.).
precisa saber é o seguinte
2

Remova r das formações. É isso que essa opção faz. Desativá-lo significa que você nunca conseguirá fazer o vim fazer isso por você, o que significa que você precisará adicionar os principais marcadores de comentários quando realmente quiser, mas essa é a desvantagem.

Etan Reisner
fonte
2
Na verdade, eu quero que o Vim adicione os marcadores de comentários para mim, eu amo isso. Mas também quero uma maneira rápida de sair do comentário. Obrigado pela sua resposta embora.
Patrick Oscity
Para o modo normal 'o' comando, é preciso remover 'r' deformatoptions
qualificação