O12 - Neovim : Vim modernisé, configuré en Lua

Objectif

Installer une version récente de Neovim, comprendre ce qu’il ajoute à Vim, puis construire pas à pas une config init.lua avec thème, recherche de fichiers, explorateur, et LSP (erreurs soulignées, autocomplétion, renommage) pour Python et Bash.

Prérequis

Les touches sont exactement celles de Vim : modes, i, Échap, :wq, dd, yy, :%s… → apprends d’abord O10 - Vim. Cette fiche ne couvre que ce que Neovim ajoute.


1. Neovim, c’est quoi ?

Neovim (nvim) est un fork de Vim lancé en 2014 : même éditeur modal, mais repensé pour être facile à étendre.

VimNeovim
Touches, modes, :%sidentiquesidentiques
Fichier de config~/.vimrc (Vimscript)~/.config/nvim/init.lua (Lua) ou init.vim
Réglages par défauttrès « années 90 »modernes (coloration, souris, recherche surlignée…)
LSP (erreurs, complétion, « aller à la définition »)via pluginsintégré
Gestionnaire de pluginsaucunintégré depuis la 0.12 (vim.pack)
Terminal intégrébasique:terminal complet
Présent sur les serveursvi presque partoutrarement → sur un serveur, c’est O10 - Vim ou O11 - Nano
flowchart LR
  T["Toi"] --> N["Neovim (nvim)"]
  N --> C["~/.config/nvim/init.lua<br/>ta config en Lua"]
  C --> P["vim.pack<br/>gestionnaire de plugins intégré"]
  P --> PL["Plugins<br/>thème, recherche, Mason..."]
  PL -->|"Mason installe"| S["Serveurs de langage<br/>pyright, bashls, lua_ls"]
  N <-->|"protocole LSP"| S

Le LSP en une phrase

Un serveur de langage (Language Server) est un petit programme qui « comprend » un langage. Neovim lui envoie ton fichier ; il répond avec les erreurs, les complétions, la définition d’une fonction… C’est exactement ce que fait VS Code (O02 - VS Code) en coulisses.


2. Installer une version récente

La version apt de Pop!_OS est trop vieille

Vérifié sur ton poste : apt fournit Neovim 0.9.5 (2023). La version stable actuelle est la 0.12.5 (août 2026). Le gestionnaire de plugins vim.pack (0.12) et la config LSP simplifiée vim.lsp.enable (0.11) n’existent pas en 0.9 → la config de cette fiche planterait.

2.1 Avec le script du vault (recommandé)

Il gère Pop!_OS et Arch, installe les outils utiles (ripgrep, presse-papiers…) et sert aussi à mettre à jour.

cd "$HOME/obsidian/truc non trier/scripts/linux"
./installer_neovim.sh

Lecture du script : installer_neovim.sh.

2.2 À la main sur Pop!_OS (ce que fait le script)

# 1. Télécharger l'archive officielle de la dernière version stable
cd /tmp
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.tar.gz
 
# 2. L'extraire dans /opt (dossier des logiciels installés "à la main")
sudo rm -rf /opt/nvim-linux-x86_64
sudo tar -C /opt -xzf nvim-linux-x86_64.tar.gz
 
# 3. Créer un raccourci dans /usr/local/bin (prioritaire sur /usr/bin dans le PATH)
sudo ln -sf /opt/nvim-linux-x86_64/bin/nvim /usr/local/bin/nvim
hash -r                                   # le shell oublie l'ancien chemin de nvim
 
# 4. Faire pointer "vi" et "vim" vers ce Neovim (sinon ils lancent la 0.9.5)
for nom in vi vim; do
  sudo update-alternatives --install /usr/bin/$nom $nom /usr/local/bin/nvim 110
  sudo update-alternatives --set $nom /usr/local/bin/nvim
done
 
# 5. Vérifier
nvim --version | head -1                  # NVIM v0.12.x
readlink -f "$(which vim)"                # /opt/nvim-linux-x86_64/bin/nvim

2.3 Sur Arch

sudo pacman -S neovim ripgrep wl-clipboard   # les dépôts Arch sont à jour

2.4 Outils dont la config a besoin

OutilPourquoiSur ton Pop!_OS
gitvim.pack télécharge les plugins avec Git✅
curl, unzip, tar, gzipMason télécharge les serveurs LSP✅
npm (Node.js)pyright et bash-language-server sont des paquets npm✅
ripgrep (rg)recherche de texte dans tout un projet❌ → le script l’installe
wl-clipboard (Wayland) / xclip (X11)copier-coller avec le reste du bureau✅
une Nerd Fonticônes (facultatif)JetBrainsMono NF sur Arch uniquement

3. Premiers pas

nvim fichier.py          # ouvrir un fichier
nvim .                   # ouvrir le dossier courant (explorateur intégré)
nvim --clean             # démarrer SANS ta config (dépannage)
CommandeEffet
:Tutortutoriel interactif (l’équivalent de vimtutor)
:checkhealthdiagnostic complet : ce qui marche, ce qui manque
:help sujetl’aide (ex. :help vim.pack) - Ctrl+] suit un lien, Ctrl+o revient
:terminalouvrir un terminal dans Neovim
:restartredémarrer Neovim (après une modif de config) - nouveau en 0.12
:messagesrevoir les messages/erreurs passés
:e $MYVIMRCouvrir ta config

Ce qui marche déjà sans config (et pas dans Vim)

ToucheEffet
gcc / gc (visuel)commenter / décommenter la ligne / la sélection (# en Python et Bash, -- en Lua)
]d / [derreur (diagnostic) suivante / précédente
Ctrl+w dafficher le détail de l’erreur sous le curseur
Ycopier jusqu’à la fin de la ligne (comme D coupe)
Kdocumentation du mot sous le curseur (avec LSP)

4. Où sont les fichiers ?

RôleCheminContenu
Config~/.config/nvim/init.lua, nvim-pack-lock.json (versions des plugins)
Données~/.local/share/nvim/plugins (site/pack/core/opt/), serveurs Mason (mason/)
État~/.local/state/nvim/historique d’annulation, fichiers d’échange, journaux (lsp.log, nvim-pack.log)
Cache~/.cache/nvim/fichiers temporaires

init.lua ou init.vim, pas les deux

Si les deux existent, Neovim affiche une erreur E5422: Conflicting configs. Si tu as créé init.vim (astuce de O10, partie 7.2), supprime-le quand tu passes à init.lua. Et à partir de là, ~/.vimrc n’est plus lu du tout : ses réglages sont repris dans la partie 6.


5. Le Lua minimum pour lire une config

LuaSens
-- textecommentaire
vim.opt.number = truerégler une option (= :set number)
vim.g.mapleader = " "variable globale de Neovim
local raccourci = vim.keymap.setranger quelque chose dans une variable locale
{ "a", "b" }une table (liste)
{ desc = "Enregistrer" }une table avec des clés (comme un dictionnaire Python)
require("module").setup()charger un plugin et l’activer
function() ... endune fonction (comme def en Python)
"a" .. "b"concaténer des textes (= "a" + "b" en Python)

Les raccourcis : vim.keymap.set(mode, touches, action, options)

  • mode : "n" Normal, "i" Insertion, "v" Visuel, "t" Terminal
  • <leader> : la touche leader, ici Espace → <leader>w = Espace puis w
  • <cmd>write<cr> : exécuter :write puis Entrée

6. Construire sa config init.lua

mkdir -p ~/.config/nvim
nvim ~/.config/nvim/init.lua

Config testée

Cette config complète a été testée sur ton Pop!_OS avec Neovim 0.12.5 : les 5 plugins s’installent, le thème se charge, pyright est installé par Mason et détecte bien une erreur dans un fichier Python.

Copie-la en entier (ou section par section, en relançant nvim à chaque étape pour comprendre ce que chacune apporte) :

-- =====================================================================
-- ~/.config/nvim/init.lua — config Neovim de la fiche O12 (Neovim 0.12+)
-- =====================================================================
 
-- ---------- 1. Options -----------------------------------------------
vim.g.mapleader = " "                 -- touche "leader" = Espace (à définir AVANT les raccourcis)
vim.g.maplocalleader = " "
 
local option = vim.opt
option.number = true                  -- numéros de ligne
option.relativenumber = true          -- numéros relatifs (pratique pour 5j, 3dd...)
option.mouse = "a"                    -- souris partout
option.clipboard = "unnamedplus"      -- y / p utilisent le presse-papiers du système
option.ignorecase = true              -- recherche insensible à la casse...
option.smartcase = true               -- ...sauf si on tape une majuscule
option.tabstop = 4                    -- une tabulation = 4 colonnes
option.shiftwidth = 4                 -- >> et << décalent de 4
option.expandtab = true               -- Tab insère des espaces (Python, YAML)
option.smartindent = true             -- indentation automatique "intelligente"
option.cursorline = true              -- surligne la ligne du curseur
option.termguicolors = true           -- vraies couleurs (nécessaire pour les thèmes)
option.signcolumn = "yes"             -- colonne à gauche pour les erreurs (le texte ne bouge plus)
option.undofile = true                -- garder l'historique d'annulation après fermeture
option.scrolloff = 8                  -- garder 8 lignes visibles autour du curseur
option.splitright = true              -- :vsplit ouvre à droite
option.splitbelow = true              -- :split ouvre en bas
option.wrap = false                   -- pas de retour à la ligne visuel
option.completeopt = { "menuone", "noselect", "popup" }  -- comportement du menu d'autocomplétion
 
-- ---------- 2. Raccourcis --------------------------------------------
local raccourci = vim.keymap.set
raccourci("n", "<leader>w", "<cmd>write<cr>", { desc = "Enregistrer" })
raccourci("n", "<leader>q", "<cmd>quit<cr>", { desc = "Quitter la fenêtre" })
raccourci("n", "<Esc>", "<cmd>nohlsearch<cr>", { desc = "Effacer le surlignage" })
raccourci("n", "<C-h>", "<C-w>h", { desc = "Fenêtre de gauche" })
raccourci("n", "<C-j>", "<C-w>j", { desc = "Fenêtre du bas" })
raccourci("n", "<C-k>", "<C-w>k", { desc = "Fenêtre du haut" })
raccourci("n", "<C-l>", "<C-w>l", { desc = "Fenêtre de droite" })
raccourci("n", "<leader>t", "<cmd>botright split | resize 12 | terminal<cr>", { desc = "Terminal en bas" })
raccourci("t", "<Esc><Esc>", <C-\><C-n>, { desc = "Sortir du mode terminal" })
raccourci("v", "<", "<gv", { desc = "Désindenter (garde la sélection)" })
raccourci("v", ">", ">gv", { desc = "Indenter (garde la sélection)" })
 
-- ---------- 3. Plugins (gestionnaire intégré : vim.pack) --------------
local function github(depot)
  return "https://github.com/" .. depot
end
 
vim.pack.add({
  { src = github("catppuccin/nvim"), name = "catppuccin" }, -- thème (le dépôt s'appelle "nvim", on le renomme)
  github("folke/which-key.nvim"),       -- affiche les raccourcis disponibles
  github("nvim-mini/mini.nvim"),        -- boîte à outils : recherche, explorateur, barre d'état...
  github("neovim/nvim-lspconfig"),      -- configurations prêtes pour les serveurs LSP
  github("mason-org/mason.nvim"),       -- installe les serveurs LSP
})
 
-- Thème sombre
require("catppuccin").setup({ flavour = "mocha" })
vim.cmd.colorscheme("catppuccin")
 
-- Aide-mémoire des raccourcis : appuie sur Espace et attends une seconde
require("which-key").setup()
 
-- Modules de mini.nvim
require("mini.statusline").setup()    -- barre d'état en bas (mode, fichier, position)
require("mini.pairs").setup()         -- ferme automatiquement ( [ { " '
require("mini.pick").setup()          -- recherche floue de fichiers / de texte
require("mini.files").setup()         -- explorateur de fichiers
 
raccourci("n", "<leader>ff", "<cmd>Pick files<cr>", { desc = "Chercher un fichier" })
raccourci("n", "<leader>fg", "<cmd>Pick grep_live<cr>", { desc = "Chercher du texte" })
raccourci("n", "<leader>fb", "<cmd>Pick buffers<cr>", { desc = "Fichiers ouverts" })
raccourci("n", "<leader>fh", "<cmd>Pick help<cr>", { desc = "Chercher dans l'aide" })
raccourci("n", "<leader>e", function() require("mini.files").open() end, { desc = "Explorateur de fichiers" })
 
-- ---------- 4. LSP : erreurs, complétion, renommage --------------------
require("mason").setup()              -- :Mason pour installer les serveurs
 
-- lua_ls : déclarer "vim" comme connu (sinon il souligne tout init.lua)
vim.lsp.config("lua_ls", {
  settings = { Lua = { diagnostics = { globals = { "vim" } } } },
})
vim.lsp.enable({ "pyright", "bashls", "lua_ls" })
 
vim.diagnostic.config({ virtual_text = true }) -- affiche l'erreur au bout de la ligne
 
-- Autocomplétion automatique quand un serveur LSP s'attache au fichier
vim.api.nvim_create_autocmd("LspAttach", {
  callback = function(evenement)
    local client = vim.lsp.get_client_by_id(evenement.data.client_id)
    if client and client:supports_method("textDocument/completion") then
      vim.lsp.completion.enable(true, client.id, evenement.buf, { autotrigger = true })
    end
  end,
})
 
raccourci("n", "gd", vim.lsp.buf.definition, { desc = "Aller à la définition" })
raccourci("n", "<leader>cf", function() vim.lsp.buf.format() end, { desc = "Formater le fichier" })
raccourci("n", "<leader>cd", vim.diagnostic.open_float, { desc = "Détail de l'erreur sous le curseur" })

6.1 Premier lancement

  1. nvim → Neovim affiche la liste des 5 plugins à installer et demande confirmation → accepte.
  2. Les plugins se téléchargent (quelques secondes), puis le thème apparaît.
  3. Installe les serveurs de langage (une seule fois) :
    :MasonInstall pyright bash-language-server lua-language-server shellcheck
  4. :restart, puis ouvre un fichier .py : les erreurs apparaissent en bout de ligne.

shellcheck vérifie tes scripts Bash

bash-language-server l’utilise automatiquement s’il est installé : guillemets oubliés, variables non définies… Parfait pour les scripts du TP déploiement et de L07 - Scripting Bash.


7. Gérer les plugins avec vim.pack

flowchart LR
  A["Ajouter une ligne<br/>dans vim.pack.add"] --> R[":restart"]
  R --> I["Installation auto<br/>(confirmation)"]
  I --> U[":lua vim.pack.update()"]
  U --> V{"Relire les changements"}
  V -->|":w"| OK["Mises à jour appliquées"]
  V -->|":q"| NO["Annulé"]
Je veux…Comment
ajouter un pluginajouter github("auteur/depot") dans vim.pack.add({...}), puis :restart
mettre à jour tous les plugins:lua vim.pack.update() → un onglet liste les changements → :w pour valider, :q pour annuler
supprimer un plugin1. l’enlever de vim.pack.add · 2. :restart · 3. :lua vim.pack.del({ "nom" })
voir les plugins installés:lua vim.pack.update(nil, { offline = true }) (sans rien télécharger)
figer les versionsle fichier ~/.config/nvim/nvim-pack-lock.json les enregistre : ne pas le modifier à la main

Et lazy.nvim ?

Avant la 0.12, il fallait un gestionnaire externe (le plus connu : lazy.nvim). Beaucoup de tutos et de configs toutes faites l’utilisent encore ; vim.pack est intégré et suffit largement pour débuter.


8. Les outils de la config au quotidien

8.1 Trouver un fichier ou du texte (mini.pick)

RaccourciEffet
Espace f fchercher un fichier par son nom (tape quelques lettres, pas besoin du nom exact)
Espace f gchercher du texte dans tout le projet (nécessite ripgrep)
Espace f bbasculer entre les fichiers déjà ouverts
Espace f hchercher dans l’aide

Dans la fenêtre de recherche : Ctrl+n / Ctrl+p (ou flèches) pour descendre/monter, Entrée pour ouvrir, Échap pour fermer.

8.2 Explorer les fichiers (mini.files) - Espace e

ToucheEffet
l / hentrer dans un dossier (ou ouvrir un fichier) / remonter
qfermer
éditer la liste comme du texteo puis un nom = créer · dd = supprimer · renommer en modifiant le nom
=appliquer les changements (une confirmation est demandée)

8.3 Fenêtres et terminal

RaccourciEffet
:vs fichier / :sp fichierouvrir à droite / en bas
Ctrl+h/j/k/lchanger de fenêtre (gauche/bas/haut/droite)
Espace tterminal en bas de l’écran
Échap Échapsortir du mode terminal (pour faire défiler, copier…) puis i pour y retaper

8.4 which-key

Appuie sur Espace et attends : une fenêtre liste tous les raccourcis qui commencent par Espace, avec leur description (desc). Pas besoin de tout retenir.


9. Le LSP au quotidien

RaccourciEffet
Kdocumentation de la fonction / variable sous le curseur (K deux fois pour entrer dedans)
gdaller à la définition (Ctrl+o pour revenir)
grrlister toutes les utilisations
grnrenommer partout (variable, fonction)
graactions proposées (ex. ajouter un import manquant)
]d / [derreur suivante / précédente
Espace c ddétail de l’erreur
Espace c fformater le fichier (si le serveur sait le faire)
Ctrl+s (mode insertion)aide sur les paramètres de la fonction en cours

Autocomplétion (mode insertion) : le menu s’ouvre tout seul → Ctrl+n / Ctrl+p pour choisir, Ctrl+y pour valider, Ctrl+e pour fermer. Pour la déclencher à la main : Ctrl+x Ctrl+o.

CommandeEffet
:checkhealth vim.lspquel serveur est actif sur ce fichier, lesquels sont configurés
:lsp restartredémarrer le serveur (s’il s’est perdu)
:Masonfenêtre de Mason : i installer, u mettre à jour, X désinstaller, g? aide

Projet Python avec environnement virtuel (ex. ton bot Discord)

Active le venv avant de lancer Neovim, pour que pyright trouve les bibliothèques installées :

cd ~/discord-bot
source .venv/bin/activate      # adapte au nom de ton dossier venv
nvim bot.py

Sinon pyright souligne les import discord comme introuvables. Voir O09 - Python (venv et pip).


10. Bonnes pratiques

Utiliser ta config pour éditer un fichier système

SUDO_EDITOR=nvim sudoedit /etc/hosts     # édite une copie avec TON nvim et TA config

sudo nvim lancerait Neovim en root sans ta config (et avec des plugins qui tourneraient en root).

En faire ton éditeur par défaut (git commit, crontab -e, visudo…) : voir 8. Choisir son éditeur par défaut et remplacer nano par nvim.

Synchroniser la config entre Pop!_OS et Arch : mets ~/.config/nvim/ (avec nvim-pack-lock.json) dans un dépôt Git (O04 - Git et GitHub). Sur l’autre système : git clone dans ~/.config/nvim, lance nvim → les mêmes versions des plugins s’installent.

Tester une autre config sans casser la tienne (ex. une config toute faite comme kickstart.nvim) :

NVIM_APPNAME=nvim-test nvim      # utilise ~/.config/nvim-test au lieu de ~/.config/nvim

11. Exercices

Exo 1. Installe Neovim 0.12 et vérifie que vim lance bien la nouvelle version.

Exo 2. Crée init.lua avec seulement la section 1 (options). Vérifie dans Neovim que les numéros de ligne relatifs sont actifs.

Exo 3. Ajoute un raccourci Espace s qui enregistre et affiche le message « Sauvegardé ! ».

Exo 4. Dans un fichier Python, renomme une variable utilisée à 3 endroits, en une seule action.

Exo 5. Mets à jour tes plugins en relisant les changements avant de valider.


12. Erreurs fréquentes / dépannage

ProblèmeCauseSolution
E5113 ... E474: Invalid argument ou attempt to index field 'pack' (a nil value) au démarrageNeovim trop ancien (testé : la 0.9.5 d’apt plante dès les options)nvim --version → installer la 0.12 (partie 2)
E5422: Conflicting configsinit.lua et init.vim présentssupprimer ~/.config/nvim/init.vim
E492: Not an editor command: Pickplugin non installé ou setup() non appelé:messages pour voir l’erreur, vérifier la section 3
Spawning language server ... failed / rien n’est soulignéserveur pas installé:Mason ou :MasonInstall pyright ; vérifier avec :checkhealth vim.lsp
Mason n’arrive pas à installer pyrightnpm absentsudo apt install npm (ou nodejs) · sudo pacman -S npm
import discord souligné en rougevenv non activépartie 9 (activer le venv avant nvim)
Espace f g ne trouve rienripgrep absentsudo apt install ripgrep
Le copier-coller avec le bureau ne marche paspas d’outil presse-papiers:checkhealth (partie clipboard) → wl-clipboard (Wayland) ou xclip
dd écrase ce que j’avais copié dans le navigateurclipboard=unnamedplus : tout passe par le presse-papiers systèmenormal ; enlever cette option si ça gêne
Carrés à la place des icônespas de Nerd Font dans le terminalinstaller une Nerd Font (ex. JetBrainsMono NF) et la choisir dans le terminal
La config plante au démarrageerreur de syntaxe Luanvim --clean ~/.config/nvim/init.lua, corriger, puis relancer nvim
Le texte du terminal ne défile pastu es en mode terminalÉchap Échap puis défiler, i pour revenir

13. Antisèche

Je veux…Touche / commande
tout ce qui vient de VimO10 - Vim
voir mes raccourcisEspace puis attendre
enregistrer / quitterEspace w / Espace q
chercher un fichier / du texteEspace f f / Espace f g
explorateurEspace e
terminalEspace t (sortir : Échap Échap)
commenter une lignegcc
définition / doc / renommergd / K / grn
erreur suivante]d
valider une complétionCtrl+y
diagnostic général:checkhealth
mettre à jour les plugins:lua vim.pack.update() puis :w
redémarrer Neovim:restart

Voir aussi