Blog Arolla

Dompter VIM en trois temps 1/3

Temps 1 : Les principaux modes de VIM

Comme énoncé dans l'introduction VIM est un éditeur modal. Chaque mode expose une manière différente d'interpréter les touches du clavier et d’interagir avec l'éditeur pour effectuer des actions sur le texte. On en distingue principalement quatre :

  • Mode Normal pour exécuter des commandes sur le texte
  • Mode Insert pour insérer du texte
  • Mode Command-line pour exécuter des commandes à travers le shell de VIM
  • Mode Visuel pour travailler sur une sélection

vim_modes_diagram

On verra pour chacun de ces modes quelques cas d'utilisation.

Nota : Dans la documentation on peut trouver Command Mode à la place de Normal Mode. Ne pas faire la confusion avec Command-Line Mode.

Le Mode Normal

C'est le mode par défaut, le mode naturel de VIM, là où l'on passera le plus de temps. La majeure partie des commandes de manipulation de texte (recherche, navigation, modification, suppression) s'effectue en mode Normal. Pour passer d'un mode à un autre on passe par le mode Normal. Il suffit d'appuyer sur <ESC> pour y arriver.

Navigation : On peut utiliser les touches fléchées du clavier pour se déplacer dans le texte. Mais pour rester fidèle à l'epsrit VIM il est recommandé d'utiliser les touches h(left), j(down), k(up) et l(right).

hjkl

nG : place le curseur sur la ligne n

H(High) : place le curseur en haut de l'écran.

M(Middle): place le curseur au milieu de l'écran.

L(Low) : place le curseur en bas de l'écran.

Notion de ligne : VIM fait la différence entre une ligne virtuelle et une ligne réelle. La ligne virtuelle est celle affichée à l'écran. La ligne réelle correspond à une ligne du fichier, elle se termine par le caractère <EOL>. Une ligne réelle peut correspondre à plusieurs lignes virtuelles.

j/k : Pour se déplacer à travers les lignes réelles.

gj/gk : Pour se déplacer à travers les lignes virtuelles.

linej

Déplacement avec j et k.

linegj

Déplacement avec gj et gk.

On peut compter 8 lignes réelles et 11 lignes virtuelles.

Notion de word : Une autre subtilité dans VIM est la différence entre word (avec w en minuscule) et WORD (avec W en majuscule). Voici ce qu'on peut lire dans le manuel (:help word) :

A word consists of a sequence of letters, digits and underscores, or a sequence of other non-blank characters, separated with white space (spaces, tabs, ). This can be changed with the 'iskeyword' option. An empty line is also considered to be a word.

A WORD consists of a sequence of non-blank characters, separated with white space. An empty line is also considered to be a WORD.

Word avec W n'est délimité que par des espaces (tab, space ou <CR>). Il correspond à la définition grammaticlale d'un mot tandis que word avec w englobe les ponctuations ".", ";", ";", "_", "-", ...

w : Pour passer d'un word à un autre

W : Pour passer d'un WORD à un autre

En mode normal les commandes de manipulation de texte sont de la forme : command <motion>. Sur son blog, Steve Losh parle d' "action + complément d'objet". L'action c'est le command et le complément d'objet correspond au motion qui peut être une suite de caractères, de mots ou de lignes.

Exemple :

d2d
command = d (delete)
motion = 2d (2 lines from cursor position)

y2y
command = y (yank)
motion = 2y (2 lines from cursor position)

caw
command = c (change)
motion = aw (arround word)

Chaque motion peut avoir un multiplicateur, 2d, 2y, 3w, ... Pour les lignes on peut préciser la direction, vers le bas (par défaut) ou vers le haut. La position du curseur est toujours le point de départ, le point 0.

line

d2d : supprimer la ligne courante et la ligne en dessous (0 et 1 vers le bas)

d2j : supprimer les lignes 0, 1 et 2 vers le bas

d2k : supprimer les lignes 0, 1 et 2 vers le haut

Précision pour copier/couper et coller

Pour faire une action de copier, couper ou coller on écrit ou lit dans le presse-papier. Avec VIM c'est dans le registre qu'on agit. Il existe plusieurs registres, et le presse-papier en est un. Quand on fait un yank, un delete ou un past on écrit dans un registre spécifique appelé registre par défaut. Un article spécifique pourra être consacré à la manipulation des registres.

Copier avec y (yank)

y2y : copier la ligne courante et la ligne en dessous.

y2j : copier la ligne courante et les deux lignes en dessous.

y2k : copier la ligne courante et les deux ligne au dessus.

yaw : copier le mot courant

y2w ou 2yw : copier le mot courant et le mot qui vient juste après

Couper avec d (delete)

Il présente les mêmes motions que yy, avec daw, d2w, 2dw, d2d, d3k (4 line above)

D : Couper, à partir de la position du curseur, jusqu'à la fin de la ligne

D

p/P (past): passe le contenu du registre après/avant le curseur

Exemple avec yyp pour copier la ligne courante juste en dessous (effectue une duplication)

yyp

Exemple avec ddp pour inverser la ligne courante avec celle en dessous

ddp

o/O : insérer une ligne vide en dessous/au dessus de la ligne courante

s (substitute): Supprimer le caractère courant et passe en mode Insert (pour remplacer)

S : supprime la ligne courante et passe en mode Insert

f{char} : positionne le curseur sur la première occurrence du caractère. On peut ensuite taper ";" pour passer à l’occurrence suivante ou "," pour revenir à l’occurrence précédente.

Exemple avec fl (find l)

findCharacter

f{char} peut être utilisé comme motion. Ex dfx,cfx

u : Annule la dernière action et <Ctrl-R> pour revenir sur l'annulation

A : positionne le curseur en fin de ligne et passe en mode insert

Le motion "t" (till) est utilisé pour spécifier l'endroit où s'arrête l'action.

Exemple avec dt. (delete till the dot )

dt

Les actions opposées : Certaines commandes ont des effets opposés.

w / b : Se déplacer d'un caractère vers l'avant/arrière

. / ; : repète/annuler la dernière répétition

u / <Ctrl-r> : Undo/Redo

Le Mode Insert

On se retrouve dans ce mode très spécialement pour taper du texte. C'est l'ultime mode des éditeurs de textes classiques (notpad, sublime, ...). Il suffit de faire I, i, A ou la touche insert, depuis le mode Normal pour y arriver. D'autres commandes d'édition du mode Normal (c, s, A) nous basculent directement dans ce mode.

La commande <Ctrl-O>

Comme dit plus haut la majeure partie des commandes est utilisée en mode normal. En pleine édition on peut avoir besoin de supprimer des lignes, remplacer des caractères, copier/coller, sauvegarder les dernières modifications, ... La première solution est de faire <ESC> pour passer en mode normal, taper la commande, et faire "i" pour revenir en mode insert. Un autre moyen, plus rapide, c'est d'utiliser <Ctrl-O>. Il nous permet de passer provisoirement du mode Insert au mode Normal juste le temps de taper une commande du mode Normal.

(Dans le prochain chapitre on montrera d'autres astuces plus pratique pour taper des commandes depuis le mode insert sans avoir à le quitter.)

Le Mode Command-Line

C'est un peu l'équivalent du shell pour vim. On y arrive en tapant ":" depuis le mode normal. Le prompt s'affiche ensuite et nous laisse la main pour taper une commande. On peut aussi faire des recherches dans ce mode avec “/” ou faire des filtres avec “!”

Les numéros de lignes

Toutes les lignes d'un fichier possèdent un numéro et la numérotation commence à 1. Le numéro d'une ligne peut être “absolu” ou “relatif”, en référence à la position courante, le point 0. Pour la plupart des actions sur les lignes on aura besoin des numéros “relatifs”.

Pour afficher ou masquer les numéros absolus

:set nu
:set nonu

Pour afficher ou masquer les numéros relatifs

:set relativenumber
:set norelativenumber

line

Play with range

La force du mode Command-Line est la facilité de travailler sur des blocks de lignes, range.

Exemple de ranges :

1 : la première ligne

$ : la dernière ligne

. : la ligne courante

1,$ : de la ligne jusqu'à la dernière ligne

.,2 : de la ligne courante jusqu'à la deuxième ligne

% : l'ensemble des lignes (texte complet)

On peut aussi référencer les lignes de manières relatives, en ajoutant le signe “+” (vers le haut) ou “–“ (vers le bas) devant les bornes.

-1, -2 : De la première ligne (1) au dessus de la ligne courante jusqu'à la deuxième ligne au dessus de la ligne courante.

1,+3 : De la première ligne (1) jusqu'à la troisième en dessous de la ligne courante.

Exemples

:23d4 : Supprimer les lignes 23, 24, 25 et 26 .

:+1,$d : Supprimer de la ligne courante +1 jusqu'à la fin.

:2,5p : Afficher de la ligne 2 jusqu'à la ligne 5 ( p = print) .

:range move/copy x : Déplacer/Copier les lignes spécifiées dans range s à la ligne x

Exemple avec :1,2move5

move

On peut exécuter une commande du mode normal tout en étant en mode Command -Line

:range normal {command}

Exemple avec :% normal A ;

normal

:% sélectionner toutes les lignes
normal passer en mode Normal
A aller à la fin de la ligne et passer en mode Insert
; écrire un point virgule
Quand on valide avec Entrée la commande s'applique sur toutes les lignes

Find and replace avec s

:s/oldWord/newWord : Remplacer, sur la ligne courante, la première occurrence de oldWord par newWord

:s/oldWord/newWord/g : Remplacer, sur la ligne courante, toutes les occurrences de oldWord par newWord

:s/oldWord/newWord/c : Demande confirmation avant d'effectuer le remplacement

Exemple avec :s/line4/LINE4/g

findReplace

On peut appliquer le find and replace sur un range. Exemple la commande :%s/oldWorld/newWorld/g remplace toutes les occurrences de oldWorld par newWorld sur l'ensemble du texte. Sans l'option g le remplacement ne portera que sur les premières occurrences de oldWorld des différentes lignes du texte.

Les filtres

:r !{cmd} : Insérer le résultat d'une commande juste en dessous de la position du curseur

Exemple avec :r !ls ou :r !git status

La recherche

/{pattern}<CR> : depuis le mode normal nous permet de faire une recherche sur un mot
n : pour passer à l'occurrence suivante
N : pour passer à l'occurrence précédente

Exemple avec /line

find

Le Mode Visual

En mode visual, comme son nom l'indique, on travaille sur une sélection de manière intuitive. La zone de sélection peut porter sur des mots (commande v), des lignes ( commande V), ou un block (ensemble de colonnes) avec la commande <Ctrl-V>. Une fois la sélection effectuée on peut exécuter une commande du mode normal, faire <ESC> et observer le résultat.

Exemple avec <Ctrl-V>

CV

<Ctrl-V> pour activer le mode visual
lll... pour sélectionner les colonnes
jjj... pour sélectionner les lignes
gU pour transformer en majuscule

La commnde gv : Revenir en mode visual, avec la dernière sélection.

gv

<Ctrl-V> pour activer le mode visual
lll... pour sélection les colonnes
jjj... pour sélectionner les lignes
gU pour transformer en majuscule
gv pour revenir sur la sélection
d pour supprimer le block sélectionné

La commande  o : pour modifier la sélection

o

<Ctrl-V> pour activer le mode visual
lll... pour sélection les colonnes
jjj... pour sélectionner les lignes
o pour modifier la sélection
lll... pour désélectionner les colonnes
jjj... pour désélectionner les lignes

What's next ... ?

Pour ce qui est de la magie de VIM on aurait pu s'en tenir à ce qu'on vient de voir, les différents modes de VIM avec les commandes de base qui nous accompagnent au quotidien et les quelques cas d'utilisation. Des fonctionnalités qu'on ne trouve pas ailleurs… Mais pour le plus timide des développeurs il en faudra encore plus pour s'intéresser à un nouvel outil. Certaines commandes peuvent être fastidieuses à taper. La tâche sera d'autant plus difficile qu'on peut avoir à utiliser ces commandes tous les jours. Peut-on toujours se permettre de faire des aller-retours entre le mode Insert et le mode Normal juste pour enregistrer, supprimer des lignes, mettre en majuscule, … ? On verra, dans le prochain article, à travers le fichier de configuration .vimrc, comment on peut personnaliser notre éditeur pour simplifier les tâches courantes.

Plus de publications

2 comments for “Dompter VIM en trois temps 1/3

  1. Pingback: Dompter VIM en trois temps 0/3 | Blog Arolla