Comment configurer Vim pour fonctionner avec une phrase par ligne?

17

J'écris actuellement beaucoup de texte brut (et LaTeX avec une mise en forme minimale dans les paragraphes), et ce serait bien si je pouvais configurer vim pour conserver chaque phrase (pour plus de simplicité, le texte se termine par un '.', '!' , ou '?'; c'est-à-dire une ponctuation de fin suivie d'un espace pour éviter de casser les nombres décimaux) sur sa propre ligne afin que les différences VCS soient plus utiles.

Au minimum, je voudrais gqformater le texte de:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

À:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

Mais ce serait bien si vim effectuait également ce formatage pendant que je tape (comme il le fait avec la refusion de la largeur du texte). Est-ce possible?

Ma solution actuelle consiste à joindre un paragraphe avec J, puis à exécuter :'<,'>s/\. /.\r/gce qui est plutôt bien car il y a peu d'exclamations et de points d'interrogation, mais ce serait beaucoup mieux si je pouvais rendre gq légèrement plus intelligent.

Alex
la source

Réponses:

23

L' 'formatexpr'option

Vous pouvez y parvenir en utilisant l' 'formatexpr'option. De l'aide:

Expression qui est évaluée pour formater une plage de lignes pour l'opérateur gq ou le formatage automatique (voir «options de formatage»). Lorsque cette option est vide, «formatprg» est utilisé.

La définition de votre 'formatexpr'correctement fonctionnera à la fois lors de l'utilisation gqet lors de l'insertion de texte.

Un exemple simple

Voici une fonction VimScript simple et une 'formatexpr'valeur correspondante qui devraient faire le travail. Je ne l'ai pas testé dans tous les cas de bord, mais cela a bien fonctionné pour mes tests simples.

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

Explication

L'expression est un appel à la fonction MyFormatExpr(), passant les lignes de début et de fin sur lesquelles la mise en forme sera appliquée. Ces lignes sont calculées à l'aide des variables renseignées automatiquement v:lnum(la première ligne à formater) et v:count(le nombre de lignes à formater).

La MyFormatExpr()fonction construit une :substitutecommande avec le passé dans la gamme, et remplace un espacement après une fin de phrase signe de ponctuation ( ., !, ou ?) avec un saut de ligne ( \r).

Avertissements

  • La MyFormatExpr()fonction ne conserve pas l'indentation principale. Une logique plus sophistiquée serait nécessaire pour résoudre ce problème.
  • Il peut y avoir d'autres cas marginaux où cela s'effondre. Essayez-le et ajustez-le si nécessaire!
tommcdo
la source
Oh, ouais c'est totalement la voie à suivre, ignore ma réponse.
Sukima
C'est génial! Ce que je souhaite, c'est que la fonction exécute une macro, comme "passer à la phrase suivante )et insérer une nouvelle ligne; répétez jusqu'à ce que vous arriviez à la fin de la plage". Il appliquerait alors vraisemblablement toutes les règles d'indentation. Mais mon Vim-fu est trop faible pour ça. :)
Nathan Long
Cela se divise par exemple e.g. blah, et Blah et al. 2018ce qui est un peu ennuyeux. Vous pouvez dissocier des modèles comme celui-ci avec quelque chose comme 's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'. Ajoutez simplement plus de motifs au premier groupe pour éviter d'autres choses sur lesquelles vous ne voulez pas vous séparer. Sinon, c'est super utile, merci. Je ne l'avais jamais rencontré gqauparavant et gqipest super utile pour formater du texte que les éditeurs de texte du co-auteur ont mutilé.
naught101
Existe-t-il un moyen d'ajouter ce comportement au comportement par défaut? Je voudrais pouvoir encapsuler à une largeur de texte donnée, ainsi que fractionner à la fin des phrases ..
naught101
1

Eh bien, vous pouvez configurer certaines cartes et commandes automatiques:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

Ensuite, définissez simplement le type de fichier sur customtxt ou appelez la AddSentenceMapsfonction manuellement.

Sukima
la source
0

Je veux ajouter mes réflexions sur cette question. Habituellement, les gens veulent ce type de fonctionnalité parce qu'ils sautent par-dessus les lignes encapsulées lorsqu'ils naviguent dans le code avec les commandes jet kqui est le comportement par défaut de Vim. Pour la navigation à travers les lignes enveloppées, j'utilise gj- descendre et gk- monter. Il existe également une possibilité de remappage standard jet de kcommande sur les homologues à préfixe g, mais à mon humble avis, ce serait exagéré.

Alexander Myshov
la source
ou une clé pour faire de remaping jet kà gjet gkquand vous le voulez ;-)
anthony
0

Cela ne répond pas à votre question spécifique sur le reformatage, mais 'set wrap' ainsi que 'set linebreak' peuvent rendre l'édition de longues lignes beaucoup plus agréable. Combinez cela avec gj et gk pour naviguer dans les lignes enveloppées. Je mappe les flèches haut et bas respectivement sur gj et gk pour avoir le choix entre monter et descendre des lignes réelles ou des lignes visuelles. Comme pour Home / End à g0 / g $.

A dessiné
la source