Vim: auto-comentario en nueva línea

9

Vim inserta automáticamente un comentario cuando comienzo una nueva línea desde una línea comentada, porque lo he configurado formatoptions=tcroql. Por ejemplo (el cursor es *):

// this is a comment*

y después de presionar <Enter>(modo de inserción) o o(modo normal) me queda:

// this is a comment
// *

Esta característica es muy útil al escribir comentarios largos de varias líneas, pero a menudo solo quiero un comentario de una sola línea. Ahora, si quiero finalizar la serie de comentarios, tengo varias opciones:

  • golpear <Esc>S
  • golpear <BS>tres veces

Ambos ofrecen tres pulsaciones de teclas, junto con <Enter>esto significa cuatro pulsaciones de teclas para una nueva línea, lo que creo que es demasiado. Idealmente, me gustaría golpear <Enter>una segunda vez para quedarme con:

// this is a comment
*

Es importante que la solución también funcione con diferentes niveles de sangría, es decir

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

golpear <Enter>

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

golpear <Enter>

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

Creo que he visto esta característica en algún editor de texto hace unos años, pero no recuerdo cuál era. ¿Alguien sabe de una solución que haga esto por mí en Vim? Los punteros en la dirección correcta sobre cómo lanzar mi propia solución también son muy bienvenidos.

Patrick Oscity
fuente
3
Puede usar ctrl-u en modo de inserción para eliminar los marcadores de comentarios insertados automáticamente en un acorde de tecla.
Etan Reisner
1
@EtanReisner eso es realmente mejor, pero aún así una pulsación de tecla demasiado para mí, ya que es un caso de uso tan común :)
Patrick Oscity
¿Sugeriste que querías poder presionar enter nuevamente para obtener el comportamiento que querías pero ctrl-u es demasiado? Puede intentar asignar <enter> <enter> en modo de inserción para realizar automáticamente el ctrl-u por usted, pero eso introduciría un retraso si alguna vez presiona <enter> solo una vez (sin presionar nada más).
Etan Reisner
Bueno, además, solo debería activarse si la línea comentada está vacía. Un retraso notable al presionar <Enter> también es inaceptable.
Patrick Oscity el
Creo que solo se retrasará si no presionas ninguna otra tecla, ya que vim tendrá que esperar para asegurarte de que todavía no planeas presionar otra tecla. También podría usar una función para realizar esa verificación, aunque podría no ser particularmente fácil de hacer.
Etan Reisner el

Respuestas:

4

Prueba esto:

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

imap <expr> <CR> EnterEnter()
romainl
fuente
Gracias se ve genial! Lo intentaré cuando llegue a casa. ¿Conoces una forma de extender la expresión regular para que coincida con el lenguaje de los marcadores de comentarios de forma independiente? La información debe estar allí en los archivos de sintaxis o algo así. Tal vez pueda aprovechar la función de sintaxis para esto ...
Patrick Oscity
Quiero decir que en C debe coincidir con // y / * y * (comentarios multilínea) y en ruby ​​# y así sucesivamente
Patrick Oscity el
Obviamente, esta función no es genérica en absoluto. Ver :h 'comment'y :h format-comment'.
romainl
Función modificada para trabajar con el #ruby y el "vimscript además del clásico //. Realmente no tiene sentido hacer nada por los *comentarios multilínea de estilo C porque debe terminar con el de */todos modos.
romainl
Hmm, tal vez <CR><CR>podría usarse para terminar el comentario multilínea ...
romainl
3

Extendí la respuesta de @ romainl para trabajar con lenguajes arbitrarios generando la expresión regular de 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()

Sin embargo, parece que no puedo reasignar <CR>en absoluto, esto simplemente no funcionará. Por ahora, lo uso <CR><CR>hasta que se resuelva este problema.

Patrick Oscity
fuente
1
¿Por qué <Esc>S? <C-u>hace lo mismo sin salir del modo de inserción. De todos modos, tenía una función personalizada que hacía un montón de cosas <CR>y la renombré SmartEnter()solo ayer después de publicar mi respuesta ;-). Tampoco estoy seguro de que &commentstringsea ​​la opción correcta, ya que generalmente solo contiene un formulario y puede ser "en línea" o "en bloque" ( /*%s*/en C, //%sen Javascript, etc.).
romainl
2

Eliminar r de 'formatoptions. Eso es lo que hace esa opción. Desactivarlo significará que nunca tendrás vim haciendo eso por ti, lo que significa que tendrás que agregar los marcadores de comentarios principales cuando realmente los quieras, pero eso es una compensación.

Etan Reisner
fuente
2
De hecho, quiero que Vim agregue los marcadores de comentarios para mí, me encanta esto. Pero también quiero una forma rápida de salir del comentario. Gracias por tu respuesta sin embargo.
Patrick Oscity el
Para el comando 'o' en modo normal, uno debe eliminar 'r' deformatoptions
eleg