Aller au contenu
Administration Linux medium

Neovim : l'éditeur terminal extensible en Lua

54 min de lecture

logo neovim

Vous maîtrisez Vim mais vous êtes frustré par son langage de configuration archaïque, l’absence de LSP natif et la lenteur de certains plugins ? Neovim reprend tout ce qui fait la force de Vim — modes, motions, text objects — et y ajoute une API Lua moderne, un client LSP intégré, Tree-sitter pour une coloration syntaxique précise, et un terminal asynchrone. Ce guide vous accompagne de l’installation jusqu’à un environnement productif avec autocomplétion, diagnostic, recherche fuzzy et explorateur de fichiers.

  • Installer Neovim sur votre distribution Linux
  • Comprendre la structure de configuration en Lua (init.lua)
  • Configurer les options et raccourcis essentiels
  • Installer des plugins avec le gestionnaire lazy.nvim
  • Activer le LSP pour l’autocomplétion et le diagnostic en temps réel
  • Utiliser Tree-sitter pour une coloration syntaxique intelligente
  • Chercher des fichiers et du texte avec Telescope
  • Naviguer dans les fichiers avec un explorateur intégré

Neovim est un fork de Vim lancé en 2014 avec un objectif clair : moderniser le code source de Vim sans casser la compatibilité. En pratique, si vous connaissez Vim, vous connaissez déjà Neovim — les modes, les raccourcis et la philosophie sont identiques. Ce qui change, c’est tout ce qui se passe sous le capot et dans l’écosystème de plugins.

FonctionnalitéVimNeovim
Langage de configurationVimScript uniquementLua natif (plus rapide, plus lisible)
Client LSPVia plugin (coc.nvim, vim-lsp)Intégré (vim.lsp) — zéro plugin nécessaire
Tree-sitterNonIntégré — coloration syntaxique basée sur l’AST
Terminal intégréBasiqueAsynchrone avec API complète
API externeLimitéeAPI RPC — contrôler Neovim depuis un programme externe
Exécution asynchroneLimitée (Vim 8+)Native — les plugins ne bloquent pas l’éditeur
Valeurs par défautMinimalistesModernes (syntax on, filetype on, incsearch, souris activée)
Presse-papierRequiert +clipboard à la compilationUtilise un provider externe (xclip, wl-copy)
Compatibilité VimLa plupart des plugins Vim fonctionnent dans Neovim
Santé du systèmePas d’équivalent:checkhealth diagnostique la configuration

Pour résumer : Vim est un éditeur puissant avec 30 ans d’héritage. Neovim garde cette puissance et y ajoute une architecture moderne qui rend les plugins plus rapides, la configuration plus lisible et les fonctionnalités d’IDE accessibles nativement.

Le paquet des dépôts officiels est souvent en retard. Pour obtenir la dernière version stable :

Fenêtre de terminal
# Ajout du PPA pour la version stable
sudo add-apt-repository ppa:neovim-ppa/stable
sudo apt update
sudo apt install neovim

Pour la version la plus récente (unstable, pour tester les nouveautés) :

Fenêtre de terminal
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update
sudo apt install neovim

Vérification : confirmez l’installation en affichant la version :

Fenêtre de terminal
nvim --version | head -2

Vous devriez voir quelque chose comme NVIM v0.11.x.

Plusieurs plugins (Neo-tree, lualine, which-key) utilisent des icônes Unicode pour afficher les types de fichiers, les modes et les raccourcis. Ces icônes nécessitent une police Nerd Font — une police monospace enrichie avec des glyphes supplémentaires.

Fenêtre de terminal
# Télécharger et installer FiraCode Nerd Font
mkdir -p ~/.local/share/fonts
cd ~/.local/share/fonts
curl -fLO https://github.com/ryanoasis/nerd-fonts/releases/latest/download/FiraCode.zip
unzip -o FiraCode.zip -d FiraCodeNerdFont
rm FiraCode.zip
fc-cache -fv

Configurez ensuite votre émulateur de terminal pour utiliser la police FiraCode Nerd Font Mono (ou une autre Nerd Font de votre choix).

La configuration de Neovim se trouve dans ~/.config/nvim/. C’est le premier changement par rapport à Vim : au lieu d’un unique ~/.vimrc, Neovim utilise un dossier structuré qui permet d’organiser la configuration en modules.

~/.config/nvim/
├── init.lua # Point d'entrée (équivalent du .vimrc)
├── lua/
│ ├── options.lua # Options de l'éditeur
│ ├── keymaps.lua # Raccourcis personnalisés
│ └── plugins/ # Configuration de chaque plugin
│ ├── colorscheme.lua
│ ├── cmp.lua
│ ├── gitsigns.lua
│ ├── lsp.lua
│ ├── lualine.lua
│ ├── misc.lua
│ ├── neo-tree.lua
│ ├── telescope.lua
│ └── treesitter.lua

Créez cette arborescence complète avec les commandes suivantes :

Fenêtre de terminal
# Créer le dossier de configuration et les sous-dossiers
mkdir -p ~/.config/nvim/lua/plugins
# Créer tous les fichiers de la configuration
touch ~/.config/nvim/init.lua
touch ~/.config/nvim/lua/options.lua
touch ~/.config/nvim/lua/keymaps.lua
touch ~/.config/nvim/lua/plugins/{colorscheme,cmp,gitsigns,lsp,lualine,misc,neo-tree,telescope,treesitter}.lua

Vérification : la commande find doit afficher tous les fichiers créés :

Fenêtre de terminal
find ~/.config/nvim -type f -name "*.lua" | sort
Résultat attendu
/home/user/.config/nvim/init.lua
/home/user/.config/nvim/lua/keymaps.lua
/home/user/.config/nvim/lua/options.lua
/home/user/.config/nvim/lua/plugins/cmp.lua
/home/user/.config/nvim/lua/plugins/colorscheme.lua
/home/user/.config/nvim/lua/plugins/gitsigns.lua
/home/user/.config/nvim/lua/plugins/lsp.lua
/home/user/.config/nvim/lua/plugins/lualine.lua
/home/user/.config/nvim/lua/plugins/misc.lua
/home/user/.config/nvim/lua/plugins/neo-tree.lua
/home/user/.config/nvim/lua/plugins/telescope.lua
/home/user/.config/nvim/lua/plugins/treesitter.lua

Les sections suivantes de ce guide détaillent le contenu de chaque fichier, dans l’ordre logique de configuration.

Le fichier init.lua est le point d’entrée — Neovim le charge automatiquement au démarrage. Depuis ce fichier, vous pouvez importer (require) d’autres fichiers Lua pour organiser votre configuration.

Créez le fichier ~/.config/nvim/lua/options.lua pour regrouper toutes les options de l’éditeur. La syntaxe Lua est plus lisible que le VimScript équivalent.

-- ~/.config/nvim/lua/options.lua
-- === PATH (mise + Mason) ===
-- Les serveurs LSP installés via Mason et les outils mis en place via mise
-- doivent être accessibles dans le PATH de Neovim
vim.env.PATH = vim.fn.expand("~/.local/share/nvim/mason/bin") .. ":" .. vim.env.PATH
-- Ajouter node/python de mise si présents
local mise_shims = vim.fn.expand("~/.local/share/mise/shims")
if vim.fn.isdirectory(mise_shims) == 1 then
vim.env.PATH = mise_shims .. ":" .. vim.env.PATH
end
-- === Apparence ===
vim.opt.number = true -- Numéros de ligne
vim.opt.relativenumber = true -- Numéros relatifs (utile pour 5j, 12k)
vim.opt.cursorline = true -- Surligne la ligne du curseur
vim.opt.signcolumn = "yes" -- Colonne de signes toujours visible (Git, diagnostics)
vim.opt.termguicolors = true -- Active les couleurs 24 bits (true color)
vim.opt.showmode = false -- Cache le mode (le plugin lualine l'affichera)
vim.opt.colorcolumn = "80" -- Ligne verticale à 80 caractères
-- === Indentation ===
vim.opt.tabstop = 4 -- Une tabulation vaut 4 espaces à l'écran
vim.opt.shiftwidth = 4 -- L'indentation automatique décale de 4 espaces
vim.opt.expandtab = true -- Insère des espaces au lieu de tabulations
vim.opt.smartindent = true -- Indentation intelligente après {, if, etc.
-- === Recherche ===
vim.opt.ignorecase = true -- Recherche insensible à la casse
vim.opt.smartcase = true -- SAUF si vous tapez une majuscule
vim.opt.hlsearch = true -- Surligne toutes les occurrences
vim.opt.incsearch = true -- Résultats en temps réel
-- === Comportement ===
vim.opt.mouse = "a" -- Souris activée partout
vim.opt.clipboard = "unnamedplus" -- Presse-papier système partagé
vim.opt.scrolloff = 8 -- Garde 8 lignes au-dessus/en-dessous du curseur
vim.opt.undofile = true -- Persistent undo (historique sauvegardé sur disque)
vim.opt.swapfile = false -- Pas de fichier swap (moins de messages au démarrage)
vim.opt.updatetime = 250 -- Délai réduit (meilleure réactivité Git/diagnostics)
vim.opt.splitright = true -- Les splits verticaux s'ouvrent à droite
vim.opt.splitbelow = true -- Les splits horizontaux s'ouvrent en bas
-- === Wrapping ===
vim.opt.wrap = false -- Pas de retour à la ligne automatique
vim.opt.linebreak = true -- Si wrap activé, coupe aux mots (pas au milieu)

Chaque option vim.opt.X = valeur correspond au set X=valeur de VimScript. La différence : en Lua, les booléens sont true/false (pas set X / set noX), et les strings utilisent des guillemets.

Vérification : ouvrez Neovim et vérifiez que les options sont bien appliquées :

" Vérifier une option booléenne (doit afficher "number")
:set number?
" Vérifier une valeur numérique (doit afficher 4)
:lua print(vim.opt.tabstop:get())
" Voir toutes les options modifiées par rapport aux défauts
:set

Créez le fichier ~/.config/nvim/lua/keymaps.lua pour vos raccourcis personnalisés. La touche Leader est la base de tous les raccourcis personnalisés — elle sert de préfixe pour éviter les conflits avec les commandes Vim natives.

-- ~/.config/nvim/lua/keymaps.lua
-- Définir la touche Leader (Espace)
vim.g.mapleader = " "
vim.g.maplocalleader = " "
-- Raccourci helper
local map = vim.keymap.set
-- === Fichiers ===
map("n", "<leader>w", "<cmd>w<cr>", { desc = "Sauvegarder" })
map("n", "<leader>q", "<cmd>q<cr>", { desc = "Quitter" })
map("n", "<leader>x", "<cmd>x<cr>", { desc = "Sauvegarder et quitter" })
-- === Navigation entre splits ===
map("n", "<C-h>", "<C-w>h", { desc = "Aller au split gauche" })
map("n", "<C-j>", "<C-w>j", { desc = "Aller au split bas" })
map("n", "<C-k>", "<C-w>k", { desc = "Aller au split haut" })
map("n", "<C-l>", "<C-w>l", { desc = "Aller au split droit" })
-- === Redimensionner les splits ===
map("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "Agrandir split horizontal" })
map("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "Réduire split horizontal" })
map("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "Réduire split vertical" })
map("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "Agrandir split vertical" })
-- === Buffers ===
map("n", "<S-l>", "<cmd>bnext<cr>", { desc = "Buffer suivant" })
map("n", "<S-h>", "<cmd>bprevious<cr>", { desc = "Buffer précédent" })
map("n", "<leader>bd", "<cmd>bdelete<cr>", { desc = "Fermer le buffer" })
-- === Confort ===
map("n", "<leader>h", "<cmd>nohlsearch<cr>", { desc = "Effacer le surlignage recherche" })
map("n", "<Esc>", "<cmd>nohlsearch<cr>", { desc = "Effacer le surlignage" })
map("v", "J", ":m '>+1<cr>gv=gv", { desc = "Déplacer la sélection vers le bas" })
map("v", "K", ":m '<-2<cr>gv=gv", { desc = "Déplacer la sélection vers le haut" })
map("n", "J", "mzJ`z", { desc = "Joindre les lignes sans déplacer le curseur" })
-- === Terminal ===
map("n", "<leader>t", "<cmd>terminal<cr>", { desc = "Ouvrir un terminal" })
map("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Quitter le mode terminal" })

La syntaxe vim.keymap.set(mode, touche, action, options) est l’équivalent Lua de nnoremap / vnoremap en VimScript. Le champ desc est important : il permet aux plugins comme which-key d’afficher une description pour chaque raccourci.

Vérification : vérifiez que vos raccourcis sont bien enregistrés :

" Lister tous les raccourcis du mode normal commençant par Leader
:nmap <leader>
" Chercher un raccourci précis
:verbose nmap <leader>w
" Lister TOUS les raccourcis (long, mais exhaustif)
:map

La commande :verbose nmap affiche en plus où le raccourci a été défini (fichier et numéro de ligne) — très utile pour comprendre les conflits.

Le fichier d’entrée importe les modules que vous venez de créer et prépare le terrain pour les plugins :

-- ~/.config/nvim/init.lua
-- Charger les options et raccourcis
require("options")
require("keymaps")
-- Le gestionnaire de plugins sera chargé ici (section suivante)

require("options") cherche le fichier lua/options.lua dans le dossier de configuration. C’est le mécanisme d’import standard de Lua.

Vérification : à ce stade (avant les plugins), lancez Neovim pour vérifier que la base fonctionne :

Fenêtre de terminal
# Lancer Neovim
nvim

Vous devriez voir les numéros de ligne, la ligne curseur surlignée et la colonne à 80 caractères. Si une erreur apparaît, la ligne fautive est indiquée dans le message — corrigez-la avant de continuer.

" Vérifier l'état de santé complet de Neovim
:checkhealth

:checkhealth analyse toute l’installation et affiche un rapport détaillé. Chaque section montre OK, WARNING ou ERROR. Concentrez-vous sur les ERROR — les WARNING sont souvent des fonctionnalités optionnelles.

lazy.nvim est le gestionnaire de plugins le plus populaire pour Neovim. Il remplace vim-plug et packer.nvim avec une approche plus rapide et plus moderne : chargement paresseux (les plugins ne se chargent que quand vous en avez besoin), interface graphique, verrouillage des versions et mises à jour simplifiées.

Ajoutez ce bloc au début de votre init.lua, avant les require :

-- ~/.config/nvim/init.lua
-- Bootstrap lazy.nvim (installation automatique au premier lancement)
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- Charger les options et raccourcis
require("options")
require("keymaps")
-- Charger les plugins
require("lazy").setup("plugins")

La dernière ligne require("lazy").setup("plugins") indique à lazy.nvim de charger tous les fichiers Lua du dossier lua/plugins/. Chaque fichier dans ce dossier définit un ou plusieurs plugins.

Vérification : au premier lancement, lazy.nvim se clone automatiquement depuis GitHub. Vous devriez voir des messages de clonage dans le terminal :

Fenêtre de terminal
# Lancez Neovim
nvim

Si le bootstrap fonctionne, la commande :Lazy doit ouvrir l’interface du gestionnaire. Si vous voyez une erreur module 'lazy' not found, vérifiez que git est installé (git --version) et que le chemin lazypath est correct.

Ouvrez l’interface du gestionnaire avec la commande :

:Lazy

Interface de lazy.nvim montrant la liste des plugins installés et leur statut

Depuis cette interface, vous pouvez :

ToucheAction
IInstaller les plugins manquants
UMettre à jour tous les plugins
SSynchroniser (installer + mettre à jour + nettoyer)
XSupprimer les plugins non déclarés
PVoir les performances de chargement
qFermer l’interface

Voici les plugins qui transforment Neovim en environnement de travail complet. Chacun est configuré dans un fichier séparé dans lua/plugins/.

Créez lua/plugins/colorscheme.lua :

-- ~/.config/nvim/lua/plugins/colorscheme.lua
return {
"ellisonleao/gruvbox.nvim",
priority = 1000, -- Charger en premier (avant les autres plugins)
config = function()
require("gruvbox").setup({
contrast = "hard", -- "hard", "soft" ou "" (défaut)
})
vim.cmd.colorscheme("gruvbox")
end,
}

Neovim avec le thème Gruvbox sur un fichier Python — coloration riche avec tons chauds

Le thème Gruvbox en version Neovim exploite les couleurs 24 bits (true color) pour un rendu plus fidèle que la version Vim 256 couleurs.

Vérification : après redémarrage, le thème doit s’appliquer immédiatement. Si les couleurs semblent incorrectes (pas de fond sombre, couleurs plates) :

" Vérifier que le thème est bien actif (doit afficher "gruvbox")
:colorscheme
" Vérifier que true color est actif (doit afficher "termguicolors")
:set termguicolors?
" Lister tous les thèmes disponibles
:Telescope colorscheme

Créez lua/plugins/lualine.lua :

-- ~/.config/nvim/lua/plugins/lualine.lua
return {
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
require("lualine").setup({
options = {
theme = "gruvbox",
section_separators = { left = "", right = "" },
component_separators = { left = "", right = "" },
},
sections = {
lualine_a = { "mode" },
lualine_b = { "branch", "diff", "diagnostics" },
lualine_c = { "filename" },
lualine_x = { "encoding", "fileformat", "filetype" },
lualine_y = { "progress" },
lualine_z = { "location" },
},
})
end,
}

Lualine remplace lightline (Vim) avec des fonctionnalités supplémentaires : affichage de la branche Git, compteur de diagnostics LSP et indicateur de diff — le tout sans configuration manuelle.

Telescope est la fonctionnalité qui justifie à elle seule le passage à Neovim pour beaucoup d’utilisateurs. C’est un chercheur universel : fichiers, texte, buffers, historique Git, diagnostics LSP — tout est accessible en tapant quelques lettres.

Créez lua/plugins/telescope.lua :

-- ~/.config/nvim/lua/plugins/telescope.lua
return {
"nvim-telescope/telescope.nvim",
version = "*",
dependencies = {
"nvim-lua/plenary.nvim",
{ "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
},
config = function()
local telescope = require("telescope")
telescope.setup({
defaults = {
path_display = { "truncate" },
sorting_strategy = "ascending",
layout_config = {
horizontal = { prompt_position = "top" },
},
},
})
telescope.load_extension("fzf")
-- Raccourcis Telescope
local map = vim.keymap.set
map("n", "<leader>ff", "<cmd>Telescope find_files<cr>", { desc = "Chercher un fichier" })
map("n", "<leader>fg", "<cmd>Telescope live_grep<cr>", { desc = "Chercher du texte" })
map("n", "<leader>fb", "<cmd>Telescope buffers<cr>", { desc = "Lister les buffers" })
map("n", "<leader>fh", "<cmd>Telescope help_tags<cr>", { desc = "Chercher dans l'aide" })
map("n", "<leader>fo", "<cmd>Telescope oldfiles<cr>", { desc = "Fichiers récents" })
map("n", "<leader>fd", "<cmd>Telescope diagnostics<cr>", { desc = "Diagnostics LSP" })
end,
}

Telescope affichant la recherche fuzzy de fichiers dans un projet

RaccourciCe qu’il fait
Espace ffChercher un fichier par nom (fuzzy)
Espace fgChercher du texte dans tout le projet (live grep)
Espace fbNaviguer dans les buffers ouverts
Espace fhChercher dans l’aide Neovim
Espace foFichiers récemment ouverts
Espace fdListe des erreurs et warnings LSP

Vérification : testez chaque commande Telescope pour confirmer que tout fonctionne :

" Doit ouvrir le chercheur de fichiers (nécessite fd)
:Telescope find_files
" Doit ouvrir la recherche de texte (nécessite ripgrep)
:Telescope live_grep
" Si une erreur apparaît, vérifier les dépendances :
" - fd --version
" - rg --version
" Si fzf-native échoue, vérifier que make est installé :
" - make --version

Tree-sitter est un analyseur syntaxique incrémental intégré à Neovim. Au lieu de colorier le code avec des expressions régulières (comme Vim), il construit un arbre syntaxique (AST) du fichier. Le résultat : une coloration plus précise, du pliage de code intelligent et une meilleure compréhension de la structure du fichier.

Créez lua/plugins/treesitter.lua :

-- ~/.config/nvim/lua/plugins/treesitter.lua
-- API nvim-treesitter rewrite (branche main, Neovim ≥ 0.11)
return {
"nvim-treesitter/nvim-treesitter",
lazy = false,
build = ":TSUpdate",
config = function()
require("nvim-treesitter").setup({})
-- Installer les parsers (asynchrone, no-op si déjà installés)
require("nvim-treesitter").install({
"bash", "c", "css", "dockerfile", "go", "hcl",
"html", "javascript", "json", "lua", "markdown",
"python", "rust", "terraform", "toml", "typescript",
"vim", "vimdoc", "yaml",
})
-- Activer la coloration Tree-sitter pour ces filetypes
vim.api.nvim_create_autocmd("FileType", {
pattern = {
"bash", "sh", "c", "css", "dockerfile", "go", "hcl",
"html", "javascript", "json", "lua", "markdown",
"python", "rust", "terraform", "toml", "typescript",
"vim", "yaml",
},
callback = function()
pcall(vim.treesitter.start)
end,
})
-- Activer le pliage de code basé sur Tree-sitter
vim.api.nvim_create_autocmd("FileType", {
pattern = {
"bash", "sh", "c", "go", "javascript", "json", "lua",
"python", "rust", "typescript", "yaml",
},
callback = function()
vim.wo[0][0].foldmethod = "expr"
vim.wo[0][0].foldexpr = "v:lua.vim.treesitter.foldexpr()"
vim.wo[0][0].foldenable = false -- Ne pas plier par défaut
end,
})
end,
}

La nouvelle API nvim-treesitter (branche main) fonctionne différemment de l’ancienne. L’installation des parsers se fait via require("nvim-treesitter").install({...}) — l’appel est asynchrone et ne refait rien si le parser est déjà compilé. La coloration syntaxique s’active avec vim.treesitter.start() dans un autocmd FileType, ce qui permet un contrôle fin par langage.

Le pliage de code (folding) utilise vim.treesitter.foldexpr() au lieu des expressions régulières. L’option foldenable = false évite que tous les blocs soient repliés à l’ouverture du fichier — vous pouvez plier manuellement avec za (basculer) ou zM (tout plier).

Vérification : ouvrez un fichier dans un des langages configurés et vérifiez que la coloration Tree-sitter est active :

" Ouvrir un fichier Python, Lua, YAML, etc.
:edit test.py
" Vérifier que Tree-sitter est actif pour ce buffer
" (doit afficher une liste avec le parser actif)
:lua print(vim.inspect(vim.treesitter.get_parser():lang()))
" Lister tous les parsers installés
:lua print(vim.inspect(require('nvim-treesitter').get_installed()))
" Si un parser manque, l'installer
:lua require('nvim-treesitter').install({ 'terraform' })

LSP : autocomplétion et diagnostic en temps réel

Section intitulée « LSP : autocomplétion et diagnostic en temps réel »

Le LSP (Language Server Protocol) est la fonctionnalité qui transforme Neovim en véritable IDE. Un serveur de langage analyse votre code en arrière-plan et fournit l’autocomplétion, le diagnostic d’erreurs, la navigation vers les définitions, le renommage de symboles et bien plus.

La configuration LSP nécessite deux éléments :

  1. mason.nvim — installe et gère les serveurs de langage
  2. nvim-cmp — affiche l’autocomplétion dans l’éditeur

Le plugin nvim-lspconfig reste utile en complément : il fournit les configurations par défaut de chaque serveur (commande de lancement, détection de la racine du projet, types de fichiers). Ces fichiers sont chargés automatiquement dans le runtimepath — pas besoin d’appeler require('lspconfig').

Depuis Neovim 0.11, la configuration des serveurs LSP utilise l’API native vim.lsp.config et vim.lsp.enable au lieu de l’ancien require('lspconfig').server.setup().

Créez lua/plugins/lsp.lua :

-- ~/.config/nvim/lua/plugins/lsp.lua
-- API vim.lsp.config / vim.lsp.enable (Neovim ≥ 0.11)
return {
{
"williamboman/mason.nvim",
config = function()
require("mason").setup()
end,
},
{
"neovim/nvim-lspconfig",
dependencies = { "williamboman/mason.nvim" },
config = function()
-- Capabilities enrichies avec nvim-cmp (si installé)
local capabilities = vim.lsp.protocol.make_client_capabilities()
local ok, cmp_lsp = pcall(require, "cmp_nvim_lsp")
if ok then
capabilities = cmp_lsp.default_capabilities(capabilities)
end
-- Raccourcis LSP activés à l'attachement d'un serveur
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(ev)
local map = function(keys, func, desc)
vim.keymap.set("n", keys, func, { buffer = ev.buf, desc = desc })
end
map("gd", vim.lsp.buf.definition, "Aller à la définition")
map("gD", vim.lsp.buf.declaration, "Aller à la déclaration")
map("gr", vim.lsp.buf.references, "Voir les références")
map("gi", vim.lsp.buf.implementation, "Aller à l'implémentation")
map("K", vim.lsp.buf.hover, "Documentation au survol")
map("<leader>rn", vim.lsp.buf.rename, "Renommer le symbole")
map("<leader>ca", vim.lsp.buf.code_action, "Actions de code")
map("<leader>e", vim.diagnostic.open_float, "Détails du diagnostic")
map("[d", vim.diagnostic.goto_prev, "Diagnostic précédent")
map("]d", vim.diagnostic.goto_next, "Diagnostic suivant")
end,
})
-- Configuration par défaut (appliquée à tous les serveurs)
vim.lsp.config("*", {
capabilities = capabilities,
})
-- Configuration spécifique pour lua_ls (éviter les warnings Neovim)
vim.lsp.config("lua_ls", {
settings = {
Lua = {
diagnostics = { globals = { "vim" } },
workspace = { library = vim.api.nvim_get_runtime_file("", true) },
},
},
})
-- Activer tous les serveurs installés via Mason
vim.lsp.enable({
"lua_ls", "pyright", "bashls", "yamlls",
"dockerls", "terraformls", "jsonls",
})
end,
},
}

Pour installer les serveurs de langage, ouvrez l’interface Mason avec :Mason puis installez-les manuellement, ou lancez directement :

:MasonInstall pyright lua-language-server bash-language-server yaml-language-server dockerfile-language-server terraform-ls json-lsp

Les changements clés par rapport à l’ancienne API :

  • vim.lsp.config("*", {...}) remplace le passage de capabilities à chaque serveur — la configuration "*" s’applique à tous.
  • vim.lsp.config("lua_ls", {...}) remplace lspconfig.lua_ls.setup({...}) pour les configurations spécifiques.
  • vim.lsp.enable({...}) remplace la boucle for server in servers.
  • LspAttach autocmd remplace le callback on_attach — c’est l’approche recommandée depuis Neovim 0.11.

Créez lua/plugins/cmp.lua :

-- ~/.config/nvim/lua/plugins/cmp.lua
return {
"hrsh7th/nvim-cmp",
dependencies = {
"hrsh7th/cmp-nvim-lsp", -- Source LSP
"hrsh7th/cmp-buffer", -- Source buffer courant
"hrsh7th/cmp-path", -- Source chemins de fichiers
"L3MON4D3/LuaSnip", -- Moteur de snippets
"saadparwaiz1/cmp_luasnip", -- Source snippets pour cmp
"rafamadriz/friendly-snippets", -- Collection de snippets
},
config = function()
local cmp = require("cmp")
local luasnip = require("luasnip")
-- Charger les snippets de friendly-snippets
require("luasnip.loaders.from_vscode").lazy_load()
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<C-b>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { "i", "s" }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" }, -- Suggestions du LSP en priorité
{ name = "luasnip" }, -- Snippets
{ name = "buffer" }, -- Mots du buffer courant
{ name = "path" }, -- Chemins de fichiers
}),
})
end,
}

Autocomplétion LSP dans Neovim avec menu déroulant et documentation

Les raccourcis LSP les plus importants à retenir :

RaccourciAction
gdAller à la définition de la fonction/variable sous le curseur
grVoir les références (tous les endroits qui utilisent ce symbole)
KDocumentation au survol (signature, description)
Espace rnRenommer le symbole partout dans le projet
Espace caActions de code (correction rapide, import manquant)
Espace eDétails du diagnostic (message d’erreur complet)
[d / ]dNaviguer entre les diagnostics (erreurs, warnings)
Tab / Shift+TabNaviguer dans le menu d’autocomplétion
EntréeAccepter la suggestion
Ctrl+EspaceDéclencher manuellement l’autocomplétion

Vérification LSP complète : ouvrez un fichier du langage concerné et vérifiez que le serveur s’attache :

" Ouvrir un fichier Python (ou Lua, YAML, etc.)
:edit test.py
" Vérifier les serveurs LSP actifs (doit lister le serveur du langage)
:LspInfo
" Vérifier que Mason a bien installé les serveurs
:Mason
" Les serveurs installés apparaissent avec une coche verte
" Tester la connexion LSP (doit afficher les clients connectés)
:lua print(vim.inspect(vim.lsp.get_clients()))
" Si le serveur ne démarre pas, vérifier le journal LSP
:LspLog

Si :LspInfo montre 0 clients attached, le serveur de langage n’est probablement pas installé via Mason (vérifiez avec :Mason) ou le PATH de Neovim ne contient pas les binaires (vérifiez la section PATH dans options.lua).

Créez lua/plugins/neo-tree.lua :

-- ~/.config/nvim/lua/plugins/neo-tree.lua
return {
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
},
config = function()
require("neo-tree").setup({
filesystem = {
follow_current_file = { enabled = true },
filtered_items = {
hide_dotfiles = false,
hide_gitignored = false,
},
},
window = {
width = 35,
},
})
vim.keymap.set("n", "<leader>n", "<cmd>Neotree toggle<cr>",
{ desc = "Ouvrir/fermer l'explorateur" })
end,
}

Neo-tree affichant l'arborescence du projet avec icônes et indicateurs Git

Neo-tree remplace NERDTree (Vim) avec un affichage plus riche : icônes par type de fichier, indicateurs Git intégrés et navigation fluide. Appuyez sur Espace n pour l’ouvrir ou le fermer.

Vérification : appuyez sur Espace n — l’explorateur doit s’ouvrir à gauche avec l’arborescence du répertoire courant. Si les icônes ne s’affichent pas, vérifiez que vous utilisez une Nerd Font (voir la section d’installation plus haut).

Créez lua/plugins/gitsigns.lua :

-- ~/.config/nvim/lua/plugins/gitsigns.lua
return {
"lewis6991/gitsigns.nvim",
config = function()
require("gitsigns").setup({
signs = {
add = { text = "" },
change = { text = "" },
delete = { text = "_" },
topdelete = { text = "" },
changedelete = { text = "~" },
},
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local map = function(mode, l, r, desc)
vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc })
end
map("n", "]c", gs.next_hunk, "Hunk Git suivant")
map("n", "[c", gs.prev_hunk, "Hunk Git précédent")
map("n", "<leader>gp", gs.preview_hunk, "Prévisualiser le changement")
map("n", "<leader>gb", gs.blame_line, "Git blame de la ligne")
map("n", "<leader>gr", gs.reset_hunk, "Annuler le changement")
end,
})
end,
}

Marqueurs Git dans la gouttière de Neovim avec gitsigns

MarqueurSignification
vertLigne ajoutée
bleuLigne modifiée
_ rougeLigne supprimée

Créez lua/plugins/misc.lua pour les plugins utilitaires :

-- ~/.config/nvim/lua/plugins/misc.lua
return {
-- Commenter/décommenter avec gcc (comme vim-commentary)
{
"numToStr/Comment.nvim",
config = function()
require("Comment").setup()
end,
},
-- Fermeture automatique des parenthèses et guillemets
{
"windwp/nvim-autopairs",
event = "InsertEnter",
config = function()
require("nvim-autopairs").setup()
end,
},
-- Entourer du texte (comme vim-surround, en Lua)
{
"kylechui/nvim-surround",
event = "VeryLazy",
config = function()
require("nvim-surround").setup()
end,
},
-- Guides d'indentation visuels
{
"lukas-reineke/indent-blankline.nvim",
main = "ibl",
config = function()
require("ibl").setup()
end,
},
-- Which-key : affiche les raccourcis disponibles
{
"folke/which-key.nvim",
event = "VeryLazy",
config = function()
require("which-key").setup()
end,
},
}

Le plugin which-key mérite une attention particulière : quand vous appuyez sur Espace (la touche Leader) et que vous attendez une seconde, un panneau apparaît avec tous les raccourcis disponibles et leur description. C’est un aide-mémoire intégré qui rend la configuration explorable.

Which-key affichant les raccourcis Leader disponibles dans Neovim

Vérification finale : après avoir créé tous les fichiers, lancez Neovim et exécutez ces commandes pour valider l’ensemble de la configuration :

" 1. Vérifiez que tous les plugins sont installés (aucun en rouge)
:Lazy
" 2. Vérifiez la santé complète de l'installation
:checkhealth
" 3. Vérifiez que les serveurs LSP sont installés
:Mason
" 4. Vérifiez que Telescope fonctionne
:Telescope find_files
" 5. Vérifiez que Tree-sitter a compilé les parsers
:lua print(#require('nvim-treesitter').get_installed() .. ' parsers installés')
" 6. Ouvrez un fichier Python et vérifiez le LSP
:edit test.py
:LspInfo

Si toutes ces commandes fonctionnent sans erreur, votre configuration est opérationnelle.

Voici l’arborescence finale et le init.lua complet :

~/.config/nvim/
├── init.lua
└── lua/
├── options.lua
├── keymaps.lua
└── plugins/
├── colorscheme.lua
├── lualine.lua
├── telescope.lua
├── treesitter.lua
├── lsp.lua
├── cmp.lua
├── neo-tree.lua
├── gitsigns.lua
└── misc.lua

En plus des commandes Vim que vous connaissez déjà, Neovim ajoute des commandes propres :

CommandeCe qu’elle fait
:checkhealthDiagnostic complet de l’installation (providers, plugins, LSP)
:LazyOuvrir le gestionnaire de plugins (installer, mettre à jour, supprimer)
:MasonOuvrir le gestionnaire de serveurs LSP
:TSInstallInfoVoir les parsers Tree-sitter installés
:LspInfoAfficher les serveurs LSP actifs pour le fichier courant
:TelescopeOuvrir Telescope (recherche fuzzy)
:Neotree toggleOuvrir/fermer l’explorateur de fichiers
:lua vim.print(vim.lsp.get_clients())Lister les clients LSP connectés

Si vous avez une configuration Vim existante, la migration vers Neovim peut se faire progressivement.

Créez un init.vim minimal qui utilise votre configuration Vim :

" ~/.config/nvim/init.vim
source ~/.vimrc

À ce stade, Neovim fonctionne exactement comme votre Vim configuré. Les plugins vim-plug continuent de fonctionner.

Gardez votre init.vim et ajoutez des fichiers Lua au fur et à mesure. Dans init.vim, vous pouvez charger du Lua :

" ~/.config/nvim/init.vim
source ~/.vimrc
lua require('options') " Charge lua/options.lua

Quand vous êtes à l’aise, remplacez init.vim par init.lua et migrez les plugins vers lazy.nvim.

SymptômeCause probableSolution
Pas de couleurs true colorTerminal ne supporte pas termguicolorsVérifier que $TERM contient 256color ou truecolor
Erreur au lancement de lazy.nvimGit non installésudo apt install git
Telescope :Telescope live_grep échoueripgrep manquantsudo apt install ripgrep
LSP ne démarre pasServeur non installéOuvrir :Mason et installer le serveur
checkhealth affiche “provider not found”Provider Python/Node manquantpip install pynvim et/ou npm install -g neovim
Le presse-papier ne fonctionne pasOutil clipboard manquantInstaller xclip (X11) ou wl-clipboard (Wayland)
Les icônes sont des carrésPolice Nerd Font manquante ou non configurée dans le terminalInstaller une Nerd Font et la configurer dans votre terminal. Sur WSL, la police doit être installée côté Windows
”No C compiler found” à l’installation Tree-sitterCompilateur C manquantsudo apt install build-essential
Plugin non chargéErreur dans la spec lazy.nvimOuvrir :Lazy et vérifier les erreurs en rouge
Lenteur au démarrageTrop de plugins chargés au démarrageUtiliser le chargement paresseux (event, cmd, ft dans lazy.nvim)
  • Neovim reprend 100 % des commandes Vim (modes, motions, text objects) — tout ce que vous savez faire dans Vim fonctionne dans Neovim.
  • La configuration en Lua est plus lisible, plus rapide et mieux structurée que le VimScript (fichiers modulaires dans lua/).
  • Le LSP natif fournit l’autocomplétion, le diagnostic, la navigation vers les définitions et le renommage — des fonctionnalités d’IDE sans quitter le terminal.
  • Tree-sitter offre une coloration syntaxique basée sur l’analyse du code (pas des regex), plus précise et plus fiable.
  • Telescope remplace fzf.vim avec une interface plus riche et plus de sources (fichiers, texte, buffers, diagnostics, aide).
  • lazy.nvim gère les plugins avec chargement paresseux, verrouillage des versions et interface graphique.
  • La commande :checkhealth est votre premier réflexe en cas de problème — elle diagnostique toute la configuration.
  • La migration depuis Vim est progressive : commencez par source ~/.vimrc, puis migrez vers Lua au fur et à mesure.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn