Vim, passez à l'action !
Chose promise, chose due ! Dans la première partie de cette série d’articles traitant de notre éditeur favori — intitulée Faisons le point sur Vim — j’ai mentionné la construction de commande et je m’étais engagé à vous expliquer cette notion. Soyons plus précis : nous nous focaliserons ici sur les commandes nous permettant de réaliser une action sur le texte de notre fichier. Nous appellerons ce type de commande une action. Sans plus attendre, décomposons-la.
Opérateur + Mouvement = Action
Une action peut être décomposée en deux parties : l’opérateur (operator) et le mouvement (motion). Vim tire sa force de la manière dont les opérateurs et les mouvements peuvent être combinés. Voyons comment cela fonctionne et quelles en sont les implications.
La commande d{motion}
peut opérer sur un simple caractère (dl
), un mot
entier (daw
) ou tout un paragraphe (dap
). Son champ d’application est
défini par le mouvement (motion). Il en va de même pour la commande
c{motion}
, y{motion}
et bien d’autres. Ces commandes sont appelées des
opérateurs.
Voici une liste des opérateurs les plus courants :
Opérateur | Effet |
---|---|
c | Changer (change) |
d | Effacer (delete) |
y | Couper (yank) et mémoriser dans un registre |
g~ | Alterner la casse (majuscule / minuscule) |
gu | Convertir en minuscule |
gU | Convertir en majuscule |
> | Décaler vers la droite |
< | Décaler vers la gauche |
= | Indenter automatiquement |
L’on remarque que certains opérateurs sont composés de g
suivi d’un
caractère. Nous pouvons simplement considérer g
comme un préfixe altérant le
comportement du caractère qu’il précède.
Un peu de grammaire
La combinaison d’opérateurs et de mouvements constitue une sorte de grammaire. La première règle est simple. Nous l’avons vu, il suffit d’adjoindre un mouvement à un opérateur. Ainsi, lorsque nous découvrons de nouveaux opérateurs ou de nouveaux mouvements à mesure de notre apprentissage de Vim, nous acquérons davantage de vocabulaire. Avec ce vocabulaire et la connaissance de la grammaire, nous pouvons construire de nouvelles actions.
Supposons que nous sachions déjà effacer un mot à l’aide de l’action daw
et
que nous découvrions l’existence de la commande gU
. Connaissant la grammaire
de Vim, nous pouvons en déduire l’action gUaw
qui va convertir le mot sous
le curseur en majuscule.
Des mouvements fluides et précis
Par défaut, lorsque nous exécutons une action, celle-ci commence sous le
curseur et prend fin à l’endroit défini par son mouvement. Par exemple,
l’action dw
va supprimer tous les caractères depuis celui sous le curseur
jusqu’à la fin du mot. Nous avons pourtant utilisé dans les exemples
précédents le mouvement aw
. Qu’est-ce que cela ? Vim fait référence à ces
mouvements sous le nom de text objects. Ils sont composés de deux caractères
dont le premier est forcément soit i
, soit a
. Ils permettent
respectivement d’effectuer une sélection en excluant le délimiteur ou
en l’incluant. Pour vous en souvenir, dites-vous que i
signifie à
l’intérieur (inside) et a
autour (around ou all).
Voici donc les text objects que nous pouvons rencontrer :
Text Object | Sélection |
---|---|
iw | Mot courant |
aw | Mot courant plus un espace |
iW | MOT courant |
aW | MOT courant plus un espace |
is | Phrase courante |
as | Phrase courante plus un espace |
ip | Paragraphe courant |
ap | Paragraphe courant plus une ligne blanche |
D’un mot à l’autre
La différence entre un mot et un MOT tient de la manière dont nous définissons ce qu’est un mot. Prenons un exemple.
p.s. s'agit-il d'un mot ?
Combien de mots avez-vous compté ? Cinq ou douze ? Quelque chose entre les deux ? Et bien il y a là cinq MOTS et douze mots. La ponctuation compte comme des mots, donc si nous parcourons la ligne mot par mot, voici ce qu’il se passe :
p.s. s'agit-il d'un mot ?
⇡
wwww p.s. s'agit-il d'un mot ?
⇡
www p.s. s'agit-il d'un mot ?
⇡
Voyons voir maintenant ce qu’il se passe si nous parcourons cette même ligne MOT par MOT :
p.s. s'agit-il d'un mot ?
⇡
W p.s. s'agit-il d'un mot ?
⇡
W p.s. s'agit-il d'un mot ?
⇡
Vim nous offre donc un outil d’une extrême précision pour effectuer les actions les plus subtiles. Mais pourquoi s’arrêter en si bon chemin ?
Les text objects sous stéroïdes
Voilà que vous m’apostrophez ! Non pas pour me donner l’accolade, mais pour me faire remarquer, entre parenthèses, que vous êtes développeur et pas écrivain. Et que des mots, des paragraphes, tout ce beau monde est bien joli mais que ça n’arrange pas vos affaires quand vous avez un gabarit HTML sous les yeux !
Qu’à cela ne tienne, prenons un exemple et voyons ce que Vim nous réserve :
var tpl = [
'<a href="{url}">{title}</a>'
⇡
]
vi} var tpl = [
'<a href="{url}">{title}</a>'
•—⬏
]
a" var tpl = [
'<a href="{url}">{title}</a>'
•—————⬏
]
i> var tpl = [
'<a href="{url}">{title}</a>'
•————————————⬏
]
it var tpl = [
'<a href="{url}">{title}</a>'
•—————⬏
]
at var tpl = [
'<a href="{url}">{title}</a>'
•—————————————————————————⬏
]
a] var tpl = [
•
'<a href="{url}">{title}</a>'
—————————————————————————————
]
⬏
Habituellement, lorsque nous entrons en mode visuel, un bout de la sélection
est ancrée sur un caractère et l’autre extrémité est mobile. Ainsi lorsque
nous utilisons des mouvements tels que l
ou w
, nous déplaçons cette
extrémité mobile.
Ce qui se passe ici est différent. Nous demandons à Vim de sélectionner tout
ce qui se trouve à l’intérieur des accolades grâce à la commande vi}
. Puis
nous étendons la sélection au contenu des guillemets, guillemets compris avec
a"
. Puis à l’intérieur des chevrons à l’aide de i>
. Ensuite nous décidons
de sélectionner le contenu de la balise (tag) avec it
. Puis nous nous
ravisons et optons pour la balise dans son ensemble avec at
. Pour finalement
choisir de sélectionner les crochets et leur contenu avec la commande a]
.
Nous retrouvons ici nos préfixes i
et a
accolés à des délimiteurs d’un
nouveau genre dits “de bloc”. En voici une liste partielle.
Text Object | Sélection |
---|---|
a) ou ab | Autour d'une paire de (parenthèses) |
i) ou ib | À l'intérieur d'une paire de (parenthèses) |
a} ou aB | Autour d'une paire d'{accolades} |
i} ou iB | À l'intérieur d'une paire d'{accolades} |
a] | Autour d'une paire de [crochets] |
i] | À l'intérieur d'une paire de [crochets] |
a> | Autour d'une paire de <chevrons> |
i> | À l'intérieur d'une paire de <chevrons> |
a’ | Autour d'une paire de 'guillemets simples' |
i’ | À l'intérieur d'une paire de 'guillemets simples' |
a" | Autour d'une paire de "guillemets doubles" |
i" | À l'intérieur d'une paire de "guillemets doubles" |
a` | Autour d'une paire de `backtick` |
i` | À l'intérieur d'une paire de `backtick` |
at | Autour d'une paire de <xml>balises</xml> |
it | À l'intérieur d'une paire de <xml>balises</xml> |
Il est à noter que l’on peut indifféremment utiliser
i)
oui(
et il en va de même pour les autres délimiteurs de bloc.
Bien entendu, il est possible d’effectuer des actions avec ces text objects avancés. Voyons comment remplacer le contenu générique d’un gabarit :
'<a href="{url}">{title}</a>'
⇡
ci"#<Esc> '<a href="#">{title}</a>'
⇡
citici<Esc> '<a href="#">ici</a>'
⇡
Nous pouvons interpréter ces commandes ainsi : “changer à l’intérieur des double guillemets”, puis “changer à l’intérieur de la balise”.
Peut-on aller plus loin ?
Vous n’avez pas trouvé votre bonheur ? Vous souhaiteriez définir d’autres
opérateurs ? D’autres délimiteurs ? Et bien c’est tout à fait possible ! C’est
d’ailleurs ce qu’ont fait certains contributeurs comme Tim Pope avec son
plugin commentary.vim
qui définit un nouvel opérateur gc
. Ainsi, l’action gcap
par exemple,
commentera le paragraphe sous le curseur. Kana Natsuno a quant à lui créé deux
nouveaux text objects avec son plugin vim-textobj-entire :
ae
et ie
qui agissent sur le fichier tout entier.
Conclusion
Nous avons ainsi vu comment, avec une grammaire succincte et finalement assez peu de vocabulaire de base, Vim nous offre une grande souplesse dans les actions que nous pouvons effectuer sur nos fichiers.
J’espère que cet article vous a donné envie d’explorer Vim davantage !