Vim: de la survie à la création de plugins
Motivation
L’éditeur de texte Vim déroute souvent ses utilisateurs venus du monde Windows, voire d'Emacs.
Cette page montre aux novices ce que fait Vim, et le rappelle aux vétérans rouillés, sans chercher à rentrer dans les détails.
C’est surtout un condensé des raccourcis utiles à l’auteur (qui la complète encore en 2019...), allant du novice à une utilisation assez avancée: mieux vaut y faire son marché que tâcher de tout retenir.
Note: sauf exception, on écrira a
pour une minuscule, A
pour une
majuscule. Les exceptions sont notamment C-
, S-
, ESC
et
RETURN
C-
désigne l'appui sur la toucheCtrl
,S-
l'appui sur la toucheShift
.Pour lever l'ambiguïté sur certaines majuscules, on peut alors écrire
S-c
pour C majuscule par exemple.ESC
etRETURN
désignent les touches du même nom
Certaines commandes tirent leur nom d'antiques machines comme le clavier du terminal ADM-3A utilisé par le développeur Bill Joy pour vi, l'ancêtre de Vim, et très grossièrement schématisé ci-dessous:
: +--------------------------------------------------------------+ : | ! | " | # | $ | % | & | ' | ( | ) | | * | = | { | } | Home | : | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | : | - | [ | ] | ^ ~ | : +-----------------------------------------------------------------+ : | Esc | Q | W | E | R | T | Y | U | I | O | P | LF | Enter | Here | : | | | | | | | | | | | | | | | : +-----------------------------------------------------------------+---+ : | Ctrl| A | S | D | F | G | H | J | K | L | + | ` | | | Rub | Break | : | | | | | | | <-| v | ^ | ->| ; | @ | \ | | | : +-------------------------------------------------------------------+ : | Ctrl | Z | X | C | V | B | N | M | < | > | ? | Shift | Rpt| Clear | : | | | | | | | | | , | . | / | | | | : +-------------------------------------------------------------------+
Survie
Les "Modes" de vim
L’effet d’une touche dépend du mode courant. Les modes
principaux sont assez nombreux (cf :h map-modes
). En pratique on a
souvent une des situations suivantes:
Mode normal: celui d’où on lance les autres commandes:
'i'
pour insertion':'
pour mode ed,'q'
pour macro,V
ouv
pour sélectionnerMode insertion: celui où on tape le texte:
ESC
revient en mode normal,C-v
entre un caractère spécial.Enregistrement de macro:
'q'
termine l'enregistrement et revient au mode normalLigne de commande (alias
ed
):ESC
revient en mode normal':!'
exécute une commande du shellSélection :
ESC
revient au mode normal
Pour les débutants absolus de Vim:
:h
: version courte de:help
, à lire avant toute chose:h tutor
: pour (re)découvrir les basesDans le manuel,
C-o
C-i
vont à l'emplacement précédent/suivant, etC-]
va au mot-clef situé sous le curseur;
Autant que possible, ce qui suit mentionnera:
la commande
:h {mot}
menant à la partie correspondante du manuel (extrêmement riche).une interprétation mnémotechnique du nom de la commande présentée. Souvent la première lettre donne un thème, et les autres y apportent une précision
Manipulations élémentaires des fichiers
:e {fichier}
: (Edit) ouvre un fichier dans un nouveau buffer.:bd
: (Buffer Delete) Ferme le buffer courant.:w
: (Write) Enregistre le buffer courant:q
: (Quit) Ferme Vim ou la fenêtre courante.:q!
: Ferme la fenêtre courante ou Vim sans rien enregistrer:x
: (eXit) Enregistre les changements et ferme la fenêtre.:v
: (View) Ouvre un fichier en lecture seule.
Passer en mode insertion de texte:
i I
: à gauche du caractère courant/en début de lignea A
: à droite du caractère courant/en fin le ligner R
: écraser un caractère/se mettre en mode 'écrasement'o O
: créer une nouvelle ligne en-dessous/au-dessus
Saisir du texte
En général le caractère voulu est sur le clavier;
En mode normal,
ga
(Get Ascii) donne le code hexa du caractère courant;En mode commande, on peut substituer un caractère spécial:
:%s/\%xHH/c/gc
pour changer (H
:chiffre hexadécimal, mettrexHH
pour deux chiffres,uHHHH
pour quatre,UHHHHHHHH
pour huit);-
Le mode insertion a de multiples façons de saisir un caractère spécial (voir cet article) et
:h c_digraph
:Composition:
C-k c ,
donneç
;Saisie hexa:
C-v u 00a9
donne©
; plus généralementC-vuxxxx
ouC-vUxxxxxxxx
insère un caractère unicodex...x
(voir sur wikia.com)Echappement:
C-v {ENTREE}
donne^M
(symptôme: le curseur ne va que sur le^
, et le group^M
est en couleur)
Fenêtres et onglets
Fenêtres
C-w
: (Window) commande sur les fenêtres, équivaut à:wincmd
C-w j, C-w k, C-w h, C-w l
: fenêtre du dessous/dessus/gauche/droit (hérité des flèches des anciens terminaux);C-w s, C-w v
: divise la fenêtre horizontalement (Split) ou verticalement (Vertical);:set lines={n} columns={m}
: taille de la fenêtre;C-w +
,C-w -
: Agrandir/réduire la fenêtre courante.5 C-w +
gagne 5 lignes.:close
: Ferme la fenêtre courante (mais pas son buffer);:only
: Etend la fenêtre courante et ferme les autres;
Les résultats de certaines fonctions avancées (compilation, fonctions des plugins) se trouvent dans des fenêtres d'interface spéciales:
Quickfix : partagée entre toutes les autres fenêtres
:copen
,:cc
,:cnext
,:cprevious
,:cclose
, surtout pour naviguer entre les messages d'erreur de compilation;Liste des emplacements : propre à une fenêtre
:lopen
,:ll
,:lnext
,:lprevious
,:lclose
, surtout pour lister les emplacements trouvés par une recherche;
Onglets
:tabnew :tabnext :tabprev :tabclose
: création/navigation de buffers dans des onglets.gt gT
: (Go to Tab) tab précédent/suivant
Folds (pliages)
Les commandes de "pliage" (to fold en anglais) cachent/montrent des
sections de texte. Elles commencent par z
(dont la forme évoque un
pliage) et sont décrites par :h fold-commands
zf{move}
,zc
,zo
: (Fold) crée un pli à la ligne du curseur, le contracter, l’ouvrirzC
,zO
: (Contract) ferme les plis à la ligne du curseur, (Open) les ouvre tous.zr
,zR
: Ouvrie partout un niveau de pli, tous les niveaux;zm
,zM
: (Minimize) ferme partout un niveau de pli, tous les niveaux;zd
,zD
,zE
: (Delete) supprime un pli existant sur un niveau, sur tous les niveaux, (Erase) sur tout le fichier.
Déplacements et marques
Fichiers et répertoires
:pwd
: (Print Working Directory) Affiche le nom du répertoire courant.:cd {rep}
: (Change Directory) change le répertoire courant.:ls
: (LiSte) liste les buffers (i.e. les fichiers ouverts):b{n}
: (Buffer) va au buffer{n}
:saveas {nom}
: enregistre le buffer courant sous un autre nom:bd {n}
: (Buffer Delete) ferme le buffer{n}
u
,C-r
: (Undo/redo): annule/rejoue les dernières modifications.g-
,g+
: (Undo/redo): idem, mais par ordre chronologique.
Se déplacer dans le texte.
Ces commandes sont souvent combinées avec celles de copier/coller par exemple:
h j k l
: bouge d'un caractère à gauche, en bas, en haut, à droite (héritage du terminal ADM-3A).b e
: (Beginning/End) Début/fin du mot courant0 $
: début/fin de ligne) } ]] ( { [[
: phrase/paragraphe/section d'après/avant.f {l}, F {l}
: (Find) va sur la lettre{l}
d'après/avant.t {l}
,T {l}
: (T) va juste avant la lettre{l}
d'après/avant.; ,
répète la dernière opérationf
ouF
dans le même sens ou non.m {m}
: (Mark) met une marquea-z
(par fichier)A-Z
(globale)0-9
(voir help)'{m} `{m}
: va à la ligne/au caractère de la marque{m}
< > . ' " ^
: marques de debut (<
)/fin(>
) de sélection, dernier changement(.
), dernière sortie de buffer ("
), dernière insertion (^
).{n}G
,{n}go
: (Go) aller à la ligne ou à l’octet{n}
Choisir la zone où opérer
Souvent on veut n'opérer que sur certaines portions de textes. Voici des
exemples appliqués à la commande :s
:
v
: (Visual) Sélection caractère par caractèreV
: Sélection ligne par ligneC-v
: Sélection rectangulaire:'<,'>s/avant/apres/gc
: Entre début et fin de sélection courante:%s/avant/apres/gc
: Sur tout (%
) le fichier, substituer (s
) avant par après, globalement (g
) sur chaque ligne et en demandant confirmation (c
).:13,25s/avant/apres
: Entre les lignes 13 et 25 incluses{ESC}
: n'affiche plus la sélection.gv
: affiche à nouveau la dernière sélection
En mode normal, la plupart des commandes attendant {move}
acceptent
aussi des objets textes (cf :h text-objects
) à la place:
iw
,iW
: mot ou MOT courantaw
,aW
: idem avec l'espace qui suitis
,as
: phrase (sans/avec espace)ip
,ap
: paragraphe (sans/avec espace)
Pouvoir préciser ainsi la portée d’une commande sans sortir du mode
normal est très confortable. Par exemple, viw
sélectionne le mot
courant, cip
écrase le paragraphe courant, etc.
Mieux encore, les objets textes peuvent aussi couvrir une zone entre deux délimiteurs:
ib
,ab
: inside / around parenthèse, oui)
,a)
;iB
,aB
: inside / around accolade (Brace), oui}
,a}
;it
,aT
: inside / around tag XML;i"
,a"
: inside / around quote;i'
,a'
: inside / around quote simple;
Recherche et remplacement
Rechercher du texte
Combinées avec les opérations sur une zone limitée, les commandes de recherche sont puissantes.
/{motif}
: recherche/\c{motif}
: recherche (indifférente à la casse)/\C{motif}
: recherche (sensible à la casse):%s/{avant}/{après}/gc;
: remplacer (et confirmer) toutes les occurrences de{avant}
par{après}
.:nohlsearch
: Ne plus surligner les résultats de recherche.&
: répète la dernière substitution sur la ligne courante.*
,#
: chercher le mot courant seul, en avant/arrière
Certaines commandes (souvent préfixées par g
)
concernent une navigation itérative:
g*
,g#
: cherche le mot courant (éventuellement inclus dans un autre mot) en avant, arrière;g,
,g;
: va à la modification suivante, précédente;C-i
,C-o
: va au saut suivant, précédent;gf
: ouvre le fichier dont le nom est sous le curseur;g'm
,g`m
: rejoint la marquem
, sans changer la jumplist;
Edition de code
Sans atteindre la puissance d'un IDE, Vim dispose de raccourcis commodes pour la programmation, notamment en C et C++:
Passer d'un bloc à l'autre
Ces commandes sont composées de [
ou ]
pour indiquer
précédent/suivant, et du délimiteur recherché;
[( [{ ]} ])
: parenthèses/accolades de début/fin du bloc courant.[m [M ]m ]M
: précédent([
)/prochain(]
) début(m
) ou fin (M
) de fonction.[# [/ ]# ]M
: idem pour directives de préprocesseur et commentaires C.
Aide en ligne
K
: appelle un programme d'aide sur le mot courant (par défautman
):h {mot}
: consulte le manuel Vim (ex::h :help
)
Registres et copier-coller
Copier/Coller du texte:
Les commandes de copier/couper/coller peuvent toutes être précédées d'un
nom de registre à utiliser, via la séquence "x
où x
est à
remplacer par le nom du registre à utiliser (défaut ").
Pour copier
y{d}
: (Yank) copie du point courant au déplacement{d}
qui suit. Par exempleye
copie jusqu'à la fin du mot courant."{R}y
: Ajoute la sélection au registre{r}
(c'est la majuscule qui dit qu'il faut ajouter au lieu d'écraser)
Pour couper (et passer en mode insertion):
c{move}
: (Cut) coupe (et stocke) le texte couvert par{move}
{count}s
: (Substitute) coupe (et stocke){count}
caractères.{count}C
: (Cut) coupe (et stocke){count}
lignes.{count}S
: (Substitute) idem, avec lignes entières.
Pour couper (et rester en mode normal)
{count}x
: (eXtract?) coupe (et stocke){count}
caractères.{count}X
: (eXtract?) idem, mais en arrière.{count}D
: (Delete) coupe (et stocke){count}
lignes à partir du caractère courant.{count}dd
: (Delete) idem, avec lignes entières.
Pour coller
P
: (Paste) insère à gauche du curseur ("{r}P
pour un autre registre{r}
).p
: (Paste) insère à droite du curseurJ
: (Join) Joint deux lignes (va au bout de la ligne courante et supprime le saut).
Compléments sur les registres:
:registers
: affiche le contenu de tous les registres:help registers
: à consulter pour les détailsC-r {r}
: en mode insertion, colle le contenu du registre{r}
C-rC-r {r}
: idem mais sans rien interpréter (utile avec des caractères de contrôle)Registres spéciaux:
%
(buffer courant)/
(dernière recherche)+
(presse-papier vim)*
(presse-papier global)0
(dernière copie)1-9
(dernières suppressions)"
(défaut)_
(NULL):
(dernière commande).
(dernière insertion) ...:let @{r} = "..."
: Décider du texte d'un registreC-r = {calcul}
: en mode insertion, insère le résultat de{calcul}
. Par exempleC-r = 3*5 RETURN
insère 15
Personnaliser Vim
Macros
La touche @
interprète un registre comme une suite d'appuis de
touches (une 'macro').
Créer:
q{m}{commandes}q
stocke{commandes}
dans le registre{m}
(attention: c’est bien le même que pour le copier-coller)Rejouer:
@{m}
ou@@
(rejoue la dermière macro)Ajouter:
q{M}{suite}q
: la majuscule{M}
fait ajouter{suite}
au registre{m}
.:{range} normal @m
: Exécute la macro sur certaines lignesMacro avec calculs: 100-(nombre courant):
:let @i="dei^R=100-^R\"^M^["
En plus d'enregistrer les macros, la touche q
permet des manips
utiles:
q:
: édition de commandes (Entrée pour exécuter la ligne courante)q/
: édite une chaîne à rechercher (Entrée pour débuter la recherche)Joker:
C-f
: pour retrouver l'effet deq:
ouq/
après avoir juste tapé:
ou/
Le fichier .vimrc
peut définir des macros dès le démarrage.
Le plus souvent :
let @r='chose'
, où chose peut être complété par les insertions littérales de caractères commeC-v{touche}
, ou de registres commeC-rC-r{reg}
;Piège:
let
ajoute^J
si la macro finit par^M
(touche RETURN). En cause, le mode ligne de 'let-@'. Solution: remplacerlet ...
parcall setreg("r",'chose','c')
, qui interprétechose
par caractère;
Clavier
Associer une touche à une action est plus sûr et plus durable qu’une macro, dont le registre risque sans cesse l'écrasement
Voici des raccourcis extraits du fichier .vimrc
de l'auteur:
"Pour l'édition de texte en général "* Redessiner l'écran sans surligner la recherche courante nnoremap <C-l> :redraw<CR>:nohlsearch<CR> "* Supprimer les espaces de fin de ligne nnoremap <F5>s :%s/[ <TAB>][ <TAB>]*$//gc<CR> "Pour compiler et chercher les erreurs nnoremap <F7> :make -k<CR> nnoremap <F4> :cnext<CR> nnoremap <S-F4> :cprev<CR>
Particularités des fonctions de la famille ...map
:
On pourrait écrire
:nnoremap ...
: le «:
» est facultatif dans le fichier.vimrc
, mais utile pour exécuter la commande sans recharger le fichier.La notation en
<>
évite d'entrer les caractères spéciaux littéralement:<CR>
représente la touche Entrée,<C-x>
la combinaison Ctrl-x, etc.Voir
:help map-modes
pour choisir entremap
,nmap
, ...,vmap
, etc. selon le mode où l’on veut appliquer le raccourci.Préférer les versions en
...noremap
, qui évitent les embrouilles en n’interprétant pas récursivement les raccourcis.:map
donne la liste des raccourcis déjà définis;:h map-multibyte
avertit des pièges des raccourcis à base de caractères non-ascii;La notation
<Leader>
désigne une touche personnalisable (voir:h Leader
) pour commencer vos raccourcis;
Plugins
L’utilité des plugins pour étendre les fonctions de base de Vim apparaît notamment sur de gros projets de code.
Idées pour rapprocher le comportement de Vim de celui d’un IDE: voir Wikia.com.
-
Mon installation "perso" utilise:
Fugitive : pour contrôle de version de code avec Git
Surround : change ou ajoute simplement un délimiteur autour d'une zone sélectionnée par les mouvements habituels.
Vim-rtags : extrêmement puissant pour des projets compilés en C/C++ (demande
clang
, et la compilation de l'utilitairertags
)
Options
Connaître les options de Vim évite de réinventer la roue à coups de plugins et de macros.
Manipulations
:options
: liste les options, leur rôle et leur valeur actuelle.:set
: liste les valeurs actuelles des options, sans expliquer.:set {option}?
: Affiche la valeur courante:set {option}!
: Change la valeur d'une option booléenne:set {option}
: Active une option booléenne:set {nooption}
: Désactive une option booléenne:set {option}={valeur}
: change la valeur globale de l'option non-booléenne.:setlocal {option}={valeur}
: change la valeur locale de l'option pour ce buffer.:setlocal {option}<
: met l'option à sa valeur globale.:setglobal {option}=...
: met une valeur globale:set {option}<
: enlève la valeur locale et n'utilise que la valeur globale.
Options quotidiennes
:set number / nonumber / number!
: numéroter les lignes:set syntax={type}
type pour la coloration syntaxique (:syntax
montre le fichier de syntaxe actuel):set nohlsearch
: ne pas/plus surligner les éléments cherchés par /.:set fileencoding=...
: encodage (utf-8,latin1,...) du buffer dans son fichier:set encoding=...
: encodage du buffer pour le terminal:set fileformat=dos,unix,mac
: format des fins de ligne:set autoread
: pour relire automatiquement un fichier changé ailleurs.:set noet
:noexpandtab
(ne pas convertir tabulations en espaces et faire suivre par:retab
):set tw=0
: ne pas couper les lignes de texte à l'insertion (par buffer).
Autocompletion
L’auto-complétion a énormément d’options (sans compter les plugins) dont voici des exemples pris dans Vim 8.
En mode commande, elle est décrite par :h cmdline-completion
:set wildmenu
: affiche une liste des choix par TAB, C-n, C-p, etc.:set wildmode=list:longest,full
: montre le plus long préfixe certain
En mode insertion, loire les commandes avec :h ins-completion
:
C-n
etC-p
affichent des choix puis naviguent entre eux.C-nC-p
raffine le filtrage en continu (pour valider, prendre le mot par un dernier `C-n` puis taper un espace).
Scripts, commandes et fonctions
Le fichier .vimrc
stocke un peu de tout: macros et touches, certes, mais aussi vos définitions de commandes, fonctions et plugins;
Ainsi, doc du langage vimscript (:h vim-script-intro`, :h write-plugin
), m’a guidé pour la mise en bouche suivante (définir une commande perso :Th
qui écrit l’heure et passe en mode insertion):
" Insère l’heure, sur une nouvelle ligne function Do_Th () "read! insère la sortie du shell dans une nouvelle ligne execute "read!date +\"\\%H:\\%M\"" "passe en mode insertion, ce que 'normal' ne fait pas call feedkeys('A: ') endfunction command! Th call Do_Th()
Même si ce n’est pas parfait, voici les raisons des choix d’écriture:
command!
délègue le travail à une fonction pour la facilité de lecture;execute "read!..."
fait comme si on tapait:read!...
qui invoque une commande du shell;feedkeys(...)
simule des appuis de touches et semble le seul moyen de passer du mode normal à l’insertion;
Autre besoin un tout petit peu plus évéolué: une commande :Search
qui cherche son argument dans le fichier courant, et montre la liste des résultats dans la fenêtre QuickFix:
"Rechercher toutes les occurrences d’un mot et les lister dans QuickFix function Do_Search (motif) execute "vimgrep /".a:motif."/ ".bufname("%") copen endfunction command! -nargs=1 Search :call Do_Search(<q-args>) nnoremap <Leader>/ :Search<SPACE>
Cet apéritif illustre quelques caractéristiques du langage:
set option = valeur
: affecter ou modifier une option;let variable = ....
: affecter ou modifier une variable;-
le nommage des variables y est important:
s:nom
,b:nom
: variables locales à un script ou à un buffer.noms spéciaux :
$nom
(environnement),&nom
(option),@nom
(registre)
execute ...
: exécution de commandes dynamiques;eval(...)
: évaluation (sans exécution);function(x, ...)
: définit une fonction, aveca:{index}
pour les arguments variables;supporte les listes et les dictionnaires;
comporte une structure
try
,catch
,finally
...;
Consultez l’Internet pour échapper aux nombreux pièges qui guettent le débutant enthousiate:
Confusion entre références des options par
&
, et des variables par leur nom;Confusion des affectations d’options par
set
, et de variables parlet
set
n'évalue rien, maislet
peut concaténer, référencer des variables, etc.
Pour aller plus loin
Sur les plugins:
Installation de plugin: avant d’écrire des plugins, il faut savoir où les mettre;
Wikia.com: incontournable pour les trucs et astuces;
LearnVimScriptTheHardWay: version électronique du livre du même nom qui vous apprend tout cela progressivement;
Vim scripts: un cours structuré;
Edition en hexadécimal:
Avec le programme xxd (pas si facile)
Avancé:
Practical Vim: une référence pour quiconque veut progresser vite dans les commandes courantes