Table des matières

Vim

Ouvrir un fichier

La manière la plus simple d'ouvrir un fichier est de le fournir comme paramètre lors du lancement du programme :

vim <fichier>

Dans ce cas, le curseur se positionnera sur le premier caractère du fichier. Il est possible d'ajouter des options lors de l'ouverture pour se positionner ailleurs dans le fichier :

# Pour positionner le curseur sur une ligne sélectionnée par son numéro
vim +<numéro> <fichier>
 
# Pour positionner le curseur sur une ligne sélectionnée par son contenu
vim +/<contenu> <fichier>
 
# Pour positionner le curseur sur la dernière ligne
vim +$ <fichier>

Il est également possible d'ouvrir un fichier à partir d'un répertoire. Dans ce cas, le contenu du répertoire sera listé et il suffira de sélectionner le fichier ou le répertoire désiré en appuyant sur la touche Enter.

vim <répertoire>

Enfin, il est possible d'ouvrir un fichier une fois que vim est ouvert en saisissant la commande suivante :

:open <fichier>

Enregistrer un fichier en lecture seule

On oublie tous un jour ou l'autre d'ouvrir un fichier avec les droits appropriés. Quand on se retrouve dans cette situation, on sauve les modifications dans un fichier temporaire puis on applique les modifications dans le fichier original avec les droits appropriés.

Il est possible de ne plus faire ça en utilisant la commande suivante :

:w !sudo tee % >/dev/null

Cette commande lance la commande sudo tee <fichier> et transfère le contenu du fichier sur son entrée standard. La commande tee s'exécute avec les droits appropriés et transfère le contenu de son entrée standard sur le fichier.

On peut même se passer de cette commande en ajoutant l'alias suivant dans le fichier ~/.vimrc :

cnoremap sudow w !sudo tee % >/dev/null

Il suffit ensuite d'appeler l'alias de la manière suivante :

:sudow

Saisir des caractères de contrôle

Il peut être nécessaire de saisir ce type de caractères lors de l'utilisation de vim. Pour cela, il faut utiliser la combinaison Ctrl+V qui indique à vim de prendre le caractère qui suit tel quel. Certains caractères peuvent être insérés directement (la tabulation par exemple) ou en utilisant un code de contrôle (voir la liste complète).

Caractère Notation Séquence
Nul ^@ Ctrl+V suivi de Ctrl+2
Retour chariot ^M Ctrl+V suivi de Ctrl+M
Tabulation ^I Ctrl+V suivi de Tab ⇆

Certain caractères peuvent être saisis sans utiliser la combinaison Ctrl+V.

Appliquer une commande sur un ensemble de ligne

Quand on veut appliquer une commande sur plusieurs lignes d'un fichier, il faut utiliser les commandes suivantes :

Voici quelques exemples :

  1. Supprimer les lignes contenant aaa
    :g/aaa/d
  2. Ajouter bbb à partir du deuxième caractère des lignes contenant aaa
    :g/aaa/normal l3ab
  3. Ajouter ^M à partir du deuxième caractère des lignes contenant aaa
    :g/aaa/execute "normal la^M"

Pour plus d'informations, voir ici

Recharger le contenu d'un fichier

Quand on veut recharger le contenu d'un fichier modifié par une action externe, il suffit de lancer la commande :edit (:e en notation courte).
Si on ne veut pas conserver le contenu modifié localement, il suffit de lancer la commande :edit! (:e! en notation courte).

Substitution de texte

Utiliser des regexp

Le fonctionnement des regexp est inversé par rapport à d'autre logiciel. Pour activer certains motifs, il faut utiliser le caractère d'échappement alors que d'habitude, il faut l'utiliser pour les désactiver.

# Pour supprimer ''n'' espaces suivi de ''|'' suivi de ''n'' chiffres
:%s/\s\+|\d\+//

Changer de casse

Le changement de casse ne peut se faire qu'avec l'utilisation de références arrières. Il est possible de :

:%s/Test \(TeSt\) Test/Test \U\1 Test/ # Affiche "Test TEST TEST"
:%s/Test \(TeSt\) Test/Test \U\1\E Test/ # Affiche "Test TEST Test"
:%s/Test \(TeSt\) Test/Test \L\1 Test/ # Affiche "Test test test"
:%s/Test \(TeSt\) Test/Test \L\1\E Test/ # Affiche "Test test Test"
:%s/Test \(TeSt\) Test/Test \u\1 Test/ # Affiche "Test TeSt Test"
:%s/Test \(TeSt\) Test/Test \l\1 Test/ # Affiche "Test teSt Test"

Chaîner des substitutions

Pour cela, il suffit juste d'utiliser | entre chaque commande de substitution. Si une erreur survient, les substitutions suivantes ne seront pas appliquées.

:%s/htm/html/ | %s/JPEG/jpg/ | %s/GIF/gif/

Utiliser une expression

Il est possible d'utiliser une expression comme chaîne de remplacement. Pour cela, la chaîne de remplacement doit commencer par \=.

# Ajouter le numéro de chaque ligne
:%s/^/\=line('.')."\t"/
 
# Dupliquer la référence arrière en la modifiant
:%s/'\(.*\)'/\='"'.submatch(1).'" => "'.substitute(submatch(1),'_',' ', 'g').'",'/g

Copier du texte dans le presse-papier

Voici une solution qui ne nécessite aucun programme supplémentaire :

:%w !xclip -in -selection clipboard

Pour d'autres méthodes, il suffit de faire un tour sur Stack Overflow

Convertir les fins de ligne

:set ff=dos
:set ff=unix
:set ff=mac

Convert DOS line endings to Linux line endings in vim - Stack Overflow

Convertir en HTML

Il est possible de convertir le contenu d'un fichier en HTML en utilisant TOhtml en mode visuel. Il est possible de le faire également en mode CLI de la manière suivante :

# Convertir tout le fichier
vim -e <filename> -c "set nobackup" -c :TOhtml -c wq -c :q
 
# Convertir une partie du fichier (de la ligne 10 à la ligne 20 incluse)
vim -e <filename> -c "set nobackup" -c :10,20TOhtml -c wq -c :q

Avec l'utilisation du thème moria, il est possible de changer la coloration syntaxique de base :

# Avec un arrière plan foncé
vim -e <filename> -c "set nobackup" -c "let moria_style='dark'" -c ":colorscheme moria" -c :TOhtml -c wq -c :q
 
# Avec un arrière plan clair
vim -e <filename> -c "set nobackup" -c "let moria_style='light'" -c ":colorscheme moria" -c :TOhtml -c wq -c :q

Il est intéressant de pouvoir convertir le fichier HTML généré en image pour pouvoir l'inclure dans une documentation. Pour cela, il est possible d'utiliser wkhtmltoimage, firefox en mode headless ou encore Puppeteer.

Exemple

Fichier source

event.py
class Card:
  def __init__(self, event, person):
    self.event=event
    self.person=person
 
  def message(self):
    print(f"Happy {self.event} {self.person}!")
 
card = Card('birthday', 'Charles')
card.message()

Résultat avec le thème sombre

event.py.dark.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>~/event.py.html</title>
<meta name="Generator" content="Vim/8.2">
<meta name="plugin-version" content="vim8.1_v2">
<meta name="syntax" content="python">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=,use_input_for_pc=fallback">
<meta name="colorscheme" content="moria">
<style>
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #c0c0c0; background-color: #000000; }
body { font-family: monospace; color: #c0c0c0; background-color: #000000; }
* { font-size: 1em; }
.LineNr { color: #ffff00; }
.Constant { color: #ff40ff; }
.Identifier { color: #00ffff; font-weight: bold; }
.Statement { color: #ffff00; }
-->
</style>
 
<script>
<!--
 
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var lineNum;
  lineNum = window.location.hash;
  lineNum = lineNum.substr(1); /* strip off '#' */
 
  if (lineNum.indexOf('L') == -1) {
    lineNum = 'L'+lineNum;
  }
  var lineElem = document.getElementById(lineNum);
  /* Always jump to new location even if the line was hidden inside a fold, or
   * we corrected the raw number to a line ID.
   */
  if (lineElem) {
    lineElem.scrollIntoView(true);
  }
  return true;
}
if ('onhashchange' in window) {
  window.onhashchange = JumpToLine;
}
 
-->
</script>
</head>
<body onload='JumpToLine();'>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Statement">class</span> <span class="Identifier">Card</span>:
<span id="L2" class="LineNr"> 2 </span>  <span class="Statement">def</span> <span class="Identifier">__init__</span>(self, event, person):
<span id="L3" class="LineNr"> 3 </span>    self.event=event
<span id="L4" class="LineNr"> 4 </span>    self.person=person
<span id="L5" class="LineNr"> 5 </span>
<span id="L6" class="LineNr"> 6 </span>  <span class="Statement">def</span> <span class="Identifier">message</span>(self):
<span id="L7" class="LineNr"> 7 </span>    <span class="Identifier">print</span>(f<span class="Constant">&quot;</span><span class="Constant">Happy {self.event} {self.person}!</span><span class="Constant">&quot;</span>)
<span id="L8" class="LineNr"> 8 </span>
<span id="L9" class="LineNr"> 9 </span>card = Card(<span class="Constant">'</span><span class="Constant">birthday</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">Charles</span><span class="Constant">'</span>)
<span id="L10" class="LineNr">10 </span>card.message()
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->

event.py.dark.jpg

Résultat avec le thème clair

event.py.light.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>~/event.py.html</title>
<meta name="Generator" content="Vim/8.2">
<meta name="plugin-version" content="vim8.1_v2">
<meta name="syntax" content="python">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=,use_input_for_pc=fallback">
<meta name="colorscheme" content="moria">
<style>
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; }
body { font-family: monospace; color: #000000; background-color: #ffffff; }
* { font-size: 1em; }
.LineNr { color: #af5f00; }
.Constant { color: #c00000; }
.Identifier { color: #008080; }
.Statement { color: #af5f00; }
-->
</style>
 
<script>
<!--
 
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var lineNum;
  lineNum = window.location.hash;
  lineNum = lineNum.substr(1); /* strip off '#' */
 
  if (lineNum.indexOf('L') == -1) {
    lineNum = 'L'+lineNum;
  }
  var lineElem = document.getElementById(lineNum);
  /* Always jump to new location even if the line was hidden inside a fold, or
   * we corrected the raw number to a line ID.
   */
  if (lineElem) {
    lineElem.scrollIntoView(true);
  }
  return true;
}
if ('onhashchange' in window) {
  window.onhashchange = JumpToLine;
}
 
-->
</script>
</head>
<body onload='JumpToLine();'>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Statement">class</span> <span class="Identifier">Card</span>:
<span id="L2" class="LineNr"> 2 </span>  <span class="Statement">def</span> <span class="Identifier">__init__</span>(self, event, person):
<span id="L3" class="LineNr"> 3 </span>    self.event=event
<span id="L4" class="LineNr"> 4 </span>    self.person=person
<span id="L5" class="LineNr"> 5 </span>
<span id="L6" class="LineNr"> 6 </span>  <span class="Statement">def</span> <span class="Identifier">message</span>(self):
<span id="L7" class="LineNr"> 7 </span>    <span class="Identifier">print</span>(f<span class="Constant">&quot;</span><span class="Constant">Happy {self.event} {self.person}!</span><span class="Constant">&quot;</span>)
<span id="L8" class="LineNr"> 8 </span>
<span id="L9" class="LineNr"> 9 </span>card = Card(<span class="Constant">'</span><span class="Constant">birthday</span><span class="Constant">'</span>, <span class="Constant">'</span><span class="Constant">Charles</span><span class="Constant">'</span>)
<span id="L10" class="LineNr">10 </span>card.message()
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->

event.py.light.jpg

1) , 2)
le changement s'effectue jusqu'à la fin de la ligne ou jusqu'au délimiteur (\E ou \e).