Fransys

Blog technique — Architecture, Cloud & DevOps

BlogServicesContactÀ propos

Suivez-moi

githubGitHublinkedinLinkedinmailMail

© 2026 Fransys • Fransys

Fransys

Catégories

  • Tous les articles
  • Tags
  • productivite10
  • nas10
  • ia8
  • securite7
  • linux6
  • claude-code6
  • auto-hebergement6
  • neovim5
  • docker5
  • editeur4
  • mcp3
  • vpn3
  • reseau3
  • lua2
  • terminal2
neovimluaediteurproductivite

Configurer Neovim from scratch avec Lua et Lazy.nvim

Publié le
9 janvier 2026·9 min de lecture
Avatar François GUERLEZFrançois GUERLEZ

Pourquoi Lua ?

Vimscript, c'était bien pour l'époque. Genre, vraiment bien. Mais Neovim 0.5, sorti en 2021, a changé la donne. Lua est arrivé comme citoyen de première classe, et franchement, là en 2026, personne n'a plus d'excuse pour coller au Vimscript quand on monte une config from scratch.

Les bénéfices ? Ils sautent aux yeux :

  • Performance : Lua passe par LuaJIT et devient du bytecode. Vimscript ? Ça reste de l'interprété, point barre.
  • Modularité : tu structures vraiment ta config comme du vrai code. Des modules, des imports, une arborescence qui a du sens.
  • Écosystème : presque tous les plugins modernes sont écrits en Lua. Vraiment presque tous. Et les APIs sont natives.
  • Lisibilité : si tu touches du JS, du Python, du TypeScript au boulot, Lua c'est intuitif. Pas de courbe d'apprentissage folle.

J'ai comaté sur Neovim en tant qu'éditeur principal pour du web (JS/TS, Python, un peu de Lua) depuis quelques années maintenant. Ma config tourne autour de 1800 lignes, parsemée sur 46 plugins différents (oui, j'aime les extensions). Et celle que j'utilise au quotidien demande même pas 35ms pour démarrer. Voilà comment j'ai organisé le truc.

Structure du projet

L'organisation suit un pattern classique dans l'écosystème Neovim :

~/.config/nvim/
├── init.lua                  # Point d'entrée
├── lua/
│   ├── config/
│   │   ├── options.lua       # Options Vim globales
│   │   ├── keymaps.lua       # Raccourcis clavier
│   │   ├── lazy.lua          # Bootstrap Lazy.nvim
│   │   ├── autocmds.lua      # Autocommandes
│   │   └── icons.lua         # Icônes centralisées
│   └── plugins/
│       ├── ui.lua            # Thème, statusbar, bufferline
│       ├── editor.lua        # Neo-tree, which-key, alpha
│       ├── lsp.lua           # LSP natif + Mason
│       ├── completion.lua    # Autocomplétion
│       ├── treesitter.lua    # Syntax highlighting
│       └── ...

Le init.lua est minimal. Son rôle est de charger les modules dans le bon ordre :

-- init.lua
vim.loader.enable() -- Cache bytecode Lua pour un démarrage plus rapide

require("config.options")
require("config.keymaps")
require("config.lazy")
require("config.autocmds")

Là, première ligne : vim.loader.enable(). Ça active le cache bytecode Lua qui est intégré à Neovim depuis 0.9 (ou presque). Concrètement ? Les fichiers Lua se compilent une fois, une seule, et après ça sort du cache. J'ai mesuré. Ça m'a gagné à peu près 30% sur le temps de démarrage.

Les options essentielles

Le fichier options.lua contient toutes les options globales. Je préfère tout centraliser ici plutôt que de disperser des vim.opt dans différents fichiers :

-- lua/config/options.lua
local opt = vim.opt

-- Désactiver netrw (remplacé par Neo-tree)
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1

-- Leaders
vim.g.mapleader = " "
vim.g.maplocalleader = ","

-- Numéros de ligne
opt.number = true
opt.relativenumber = true

-- Indentation : 2 espaces, pas de tabs
opt.tabstop = 2
opt.shiftwidth = 2
opt.expandtab = true
opt.smartindent = true

-- Recherche intelligente
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true

-- Interface
opt.signcolumn = "yes"
opt.cursorline = true
opt.termguicolors = true
opt.showmode = false

-- Splits : ouverture à droite et en bas
opt.splitright = true
opt.splitbelow = true

-- Presse-papier système
opt.clipboard = "unnamedplus"

-- Undo persistant, pas de swap
opt.undofile = true
opt.swapfile = false

-- Caractères invisibles
opt.list = true
opt.listchars = { tab = "» ", trail = "·", nbsp = "␣" }

-- Réactivité
opt.updatetime = 250
opt.timeoutlen = 300

-- Scrolloff pour garder du contexte
opt.scrolloff = 10

Quelques choix qui méritent une explication :

  • Space comme leader : ouais, la barre d'espace. C'est LA touche la plus accessible quand tes deux mains sont sur le clavier. Couple ça avec which-key et tu as un système de commandes qui est vraiment ergonomique.
  • relativenumber : absolument essentiel pour faire des 5j, 12k sans les compter sur tes doigts comme un débile. Tu vois directement combien de lignes tu dois franchir.
  • 2 espaces : c'est le standard de facto dans le monde JS/TS/Lua. J'ai testé 4 espaces une fois, c'était une catastrophe, trop de bruit visuel.
  • Pas de swap, undo persistant : les swap files, c'est l'Holocène. L'undo persistant entre les sessions ? Ça c'est utile. Genre vraiment.

Bootstrap de Lazy.nvim

Lazy.nvim, c'est LE gestionnaire de plugins maintenant. J'ai utilisé Packer avant, j'ai même touché à vim-plug pendant un brief moment (grosse erreur). Lazy, c'est du sérieux : lazy-loading par défaut, config simple, et ça fait ce qu'on lui demande sans faire de simagrées.

Le truc cool, c'est que ça s'auto-installe au premier lancement :

-- lua/config/lazy.lua
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)

require("lazy").setup("plugins", {
  defaults = { lazy = true },
  install = { colorscheme = { "catppuccin" } },
  checker = { enabled = true, notify = false },
  change_detection = { notify = false },
  ui = { border = "rounded" },
})

Le require("lazy").setup("plugins") charge automatiquement tous les fichiers du dossier lua/plugins/. Chaque fichier retourne une table (ou une liste de tables) décrivant les plugins et leur configuration. Le lazy-loading par défaut signifie que les plugins ne sont chargés que quand on en a besoin : au lancement d'une commande, à l'ouverture d'un type de fichier, ou sur un événement.

Le thème : Catppuccin Mocha

J'ai testé trop de thèmes, franchement. Gruvbox ? Trop chaud au bout de 8h. Tokyo Night ? Sympa mais inconsistant. One Dark ? Moyen. Et puis j'ai découvert Catppuccin en variante Mocha.

C'était l'illumination. Les couleurs reposent vraiment les yeux, le contraste est propre, et (là c'est le détail important) il y a des intégrations pour tous les plugins. Tous. Même les obscurs. Voilà :

{
  "catppuccin/nvim",
  name = "catppuccin",
  priority = 1000,
  lazy = false,
  opts = {
    flavour = "mocha",
    integrations = {
      cmp = true,
      gitsigns = true,
      neotree = true,
      treesitter = true,
      telescope = { enabled = true },
      which_key = true,
      native_lsp = {
        enabled = true,
        underlines = {
          errors = { "undercurl" },
          warnings = { "undercurl" },
        },
      },
    },
  },
  config = function(_, opts)
    require("catppuccin").setup(opts)
    vim.cmd.colorscheme("catppuccin")
  end,
}

Le priority = 1000 et lazy = false garantissent que le thème est chargé en tout premier, avant les autres plugins qui en dépendent pour leurs couleurs.

L'interface complète

Lualine : la barre de statut

Lualine. Avant, c'était la statusline default de Vim - basique, sans âme. Lualine la remplace avec du vrai contenu : ta branche Git, les diffs, les erreurs LSP, le type de fichier actuel, ta position dans le fichier. Tout ça en une ligne qui regarde bien. Je le setup avec Catppuccin et des séparateurs arrondis :

{
  "nvim-lualine/lualine.nvim",
  event = "VeryLazy",
  opts = {
    options = {
      theme = "catppuccin",
      component_separators = { left = "", right = "" },
      section_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" },
    },
  },
}

Bufferline : les onglets de buffers

Bufferline - tes buffers ouverts, affichés comme des onglets en haut. C'est simple, ça paraît bête, mais une fois que tu l'as, tu le gardes. Icône pour fermer au survol, compteur d'erreurs par buffer, navigation aux touches. Voilà :

{
  "akinsho/bufferline.nvim",
  event = "VeryLazy",
  opts = {
    options = {
      diagnostics = "nvim_lsp",
      close_icon = "",
      buffer_close_icon = "󰅖",
      modified_icon = "●",
      offsets = {
        { filetype = "neo-tree", text = "File Explorer", highlight = "Directory" },
      },
    },
  },
}

Neo-tree : l'explorateur de fichiers

Neo-tree remplace l'ancien netrw avec une interface moderne. Je le toggle avec <leader>n et il affiche le statut Git directement dans l'arborescence :

{
  "nvim-neo-tree/neo-tree.nvim",
  cmd = "Neotree",
  keys = {
    { "<leader>n", "<cmd>Neotree toggle<cr>", desc = "Toggle file explorer" },
  },
  opts = {
    filesystem = {
      follow_current_file = { enabled = true },
      use_libuv_file_watcher = true,
    },
    window = {
      width = 35,
      mappings = { ["<space>"] = "none" },
    },
    default_component_configs = {
      git_status = {
        symbols = {
          added = "✚",
          modified = "",
          deleted = "✖",
          renamed = "󰁕",
          untracked = "",
        },
      },
    },
  },
}

Alpha : le dashboard d'accueil

Au lancement de Neovim sans argument, Alpha affiche un dashboard avec un logo ASCII et des raccourcis vers les actions fréquentes : fichiers récents, nouveau fichier, recherche, configuration, etc.

{
  "goolord/alpha-nvim",
  event = "VimEnter",
  config = function()
    local alpha = require("alpha")
    local dashboard = require("alpha.themes.dashboard")

    dashboard.section.header.val = {
      "                                                     ",
      "  ███╗   ██╗███████╗ ██████╗ ██╗   ██╗██╗███╗   ███╗",
      "  ████╗  ██║██╔════╝██╔═══██╗██║   ██║██║████╗ ████║",
      "  ██╔██╗ ██║█████╗  ██║   ██║██║   ██║██║██╔████╔██║",
      "  ██║╚██╗██║██╔══╝  ██║   ██║╚██╗ ██╔╝██║██║╚██╔╝██║",
      "  ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║",
      "  ╚═╝  ╚═══╝╚══════╝ ╚═════╝   ╚═══╝  ╚═╝╚═╝     ╚═╝",
    }

    dashboard.section.buttons.val = {
      dashboard.button("r", "  Fichiers récents", "<cmd>Telescope oldfiles<cr>"),
      dashboard.button("n", "  Nouveau fichier", "<cmd>ene<cr>"),
      dashboard.button("f", "󰈞  Chercher un fichier", "<cmd>Telescope find_files<cr>"),
      dashboard.button("g", "  Grep dans les fichiers", "<cmd>Telescope live_grep<cr>"),
      dashboard.button("c", "  Configuration", "<cmd>e $MYVIMRC<cr>"),
      dashboard.button("l", "󰒲  Lazy", "<cmd>Lazy<cr>"),
      dashboard.button("q", "  Quitter", "<cmd>qa<cr>"),
    }

    alpha.setup(dashboard.config)
  end,
}

Which-key : le guide des raccourcis

Which-key change tout sur la découvrabilité des keybindings. Tu appuies sur Space, tu attends une demi-seconde, et boom - un popup avec tous tes raccourcis, bien organisés. C'est comme avoir un cheat sheet permanent collé à ton éditeur, mais qui ne prend zéro place à l'écran.

Temps de démarrage

Donc. 46 plugins. Lazy-loading bien configuré. Ça démarre en 35ms. C'est plus vite qu'un terminal qui affiche son prompt. Je me trompe pas parce que j'ai lancé :Lazy profile environ cinquante fois pour vérifier. Spoiler : c'est vrai.

VS Code ? Entre 2 et 5 secondes. Je vais pas faire un jugement moral sur VS Code, c'est légitime. Mais quand tu ouvres/fermes ton éditeur des dizaines de fois par jour (et tu le fais), cette différence c'est un game changer.

Conclusion

Monter une configuration Neovim de zéro, ça demande du temps. Ouais. C'est un investissement réel, pas du BS. Mais une fois que t'as la structure en place - les dossiers, le init.lua, les modules config/ - chaque ajout devient trivial. Faut juste créer un fichier Lua dans plugins/, ajouter une table, et voilà.

Au final, tu te retrouves avec un éditeur hyper-spécialisé pour ta façon de travailler. Pas de features inutiles qui traînent. Ça démarre instantanément. Et tu comprends chaque couche parce que tu l'as écrite (ou du moins, tu as copié-collé la démo et tu l'as compris après). Lua et Lazy.nvim rendent le truc vraiment accessible, même si tu as jamais vraiment maîtrisé Vimscript.

Article précédent

← Installer Debian sur un NAS en mode 100% automatique

Article suivant

Sécuriser SSH avec des algorithmes post-quantiques→
← Retour au blog

Sommaire

  • Pourquoi Lua ?
  • Structure du projet
  • Les options essentielles
  • Bootstrap de Lazy.nvim
  • Le thème : Catppuccin Mocha
  • L'interface complète
  • Lualine : la barre de statut
  • Bufferline : les onglets de buffers
  • Neo-tree : l'explorateur de fichiers
  • Alpha : le dashboard d'accueil
  • Which-key : le guide des raccourcis
  • Temps de démarrage
  • Conclusion