Vim: commentaire automatique dans une nouvelle ligne

9

Vim insère automatiquement un commentaire lorsque je commence une nouvelle ligne à partir d'une ligne commentée, car je l'ai définie formatoptions=tcroql. Par exemple (le curseur est *):

// this is a comment*

et après avoir frappé <Enter>(mode insertion) ou o(mode normal) je me retrouve avec:

// this is a comment
// *

Cette fonctionnalité est très pratique lors de l'écriture de longs commentaires sur plusieurs lignes, mais souvent je veux juste un commentaire sur une seule ligne. Maintenant, si je veux terminer la série de commentaires, j'ai plusieurs options:

  • frappé <Esc>S
  • frappé <BS>trois fois

Les deux offrent trois touches, combinées avec <Enter>cela signifie quatre touches pour une nouvelle ligne, ce qui, je pense, est trop. Idéalement, je voudrais juste frapper <Enter>une deuxième fois pour me retrouver avec:

// this is a comment
*

Il est important que la solution fonctionne également avec différents niveaux d'indentation, c.-à-d.

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

frappé <Enter>

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

frappé <Enter>

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

Je pense avoir vu cette fonctionnalité dans un éditeur de texte il y a quelques années, mais je ne me souviens pas laquelle. Quelqu'un connaît-il une solution qui me permettra de le faire à Vim? Des conseils dans la bonne direction sur la façon de déployer ma propre solution sont également les bienvenus.

Patrick Oscity
la source
3
Vous pouvez utiliser ctrl-u en mode insertion pour supprimer les marqueurs de commentaire insérés automatiquement dans un accord de touche.
Etan Reisner
1
@EtanReisner c'est en fait mieux, mais encore une touche de trop pour moi car c'est un cas d'utilisation courant :)
Patrick Oscity
Vous avez suggéré que vous vouliez pouvoir appuyer à nouveau sur Entrée pour obtenir le comportement que vous vouliez, mais ctrl-u est trop? Vous pouvez essayer de mapper <enter> <enter> en mode d'insertion pour effectuer automatiquement le ctrl-u pour vous, mais cela introduirait un retard si vous frappiez <enter> une seule fois (sans rien toucher d'autre).
Etan Reisner
De plus, il ne devrait se déclencher que si la ligne commentée est vide. Un retard notable lorsque vous appuyez sur <Entrée> est également inacceptable.
Patrick Oscity
Cela ne tardera que si vous n'appuyez sur aucune autre touche, je crois, car vim devra attendre pour vous assurer que vous ne prévoyez pas encore d'appuyer sur une autre touche. Vous pouvez également utiliser une fonction pour effectuer cette vérification, même si ce n'est pas particulièrement simple à faire.
Etan Reisner

Réponses:

4

Essaye ça:

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

imap <expr> <CR> EnterEnter()
romainl
la source
Merci a fière allure! J'essaierai quand je rentrerai. Connaissez-vous un moyen d'étendre l'expression régulière pour faire correspondre le langage des marqueurs de commentaires indépendamment? Les informations doivent être présentes dans les fichiers de syntaxe ou quelque chose. Peut-être que je peux tirer parti de la fonction de syntaxe pour cela ...
Patrick Oscity
Je veux dire en C, il doit correspondre à // et / * et * (commentaires multilignes) et en ruby ​​# et ainsi de suite
Patrick Oscity
De toute évidence, cette fonction n'est pas générique du tout. Voir :h 'comment'et :h format-comment'.
romainl
Fonction modifiée pour fonctionner avec le #rubis et le "vimscript en plus du classique //. Cela n'a pas vraiment de sens de faire quoi que ce soit pour les *commentaires multilignes de style C, car cela doit se terminer de */toute façon.
romainl
Hmm, peut <CR><CR>-être pourrait être utilisé pour terminer le commentaire multiligne ...
romainl
3

J'ai étendu la réponse de @ romainl pour travailler avec des langages arbitraires en générant l'expression régulière à partir 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()

Cependant, je n'arrive pas du tout à remapper <CR>, cela ne fonctionnera tout simplement pas. Pour l'instant, j'utilise <CR><CR>jusqu'à ce que ce problème soit résolu.

Patrick Oscity
la source
1
Pourquoi <Esc>S? <C-u>fait de même sans quitter le mode d'insertion. Quoi qu'il en soit, j'avais une fonction personnalisée qui a fait un tas de choses <CR>et SmartEnter()je l'ai renommée juste hier après avoir posté ma réponse ;-). De plus, je ne suis pas sûr que ce &commentstringsoit le bon choix car il ne contient généralement qu'un seul formulaire et il peut être "linewise" ou "blockwise" ( /*%s*/en C, //%sen Javascript, etc.).
romainl
2

Supprimez r de 'formatoptions. C'est ce que fait cette option. Si vous le désactivez, vous n'aurez jamais à faire cela pour vous, ce qui signifie que vous devrez ajouter les principaux marqueurs de commentaire lorsque vous en aurez réellement besoin, mais c'est le compromis.

Etan Reisner
la source
2
En fait, je veux que Vim ajoute les marqueurs de commentaire pour moi, j'adore ça. Mais je veux aussi un moyen rapide de quitter le commentaire. Merci pour votre réponse.
Patrick Oscity
Pour la commande «o» en mode normal, il faut supprimer «r» deformatoptions
elig