Vim / Neovim (vimtex)

Pour écrire LaTeX dans Vim ou Neovim, le standard de facto est le plugin vimtex de Karl Yngve Lervåg. Il apporte la compilation, la navigation entre la table des matières et les étiquettes, les mouvements et les objets texte qui fonctionnent sur les environnements et les commandes, la complétion et les sauts bidirectionnels avec votre visionneuse PDF, le tout sans quitter l'éditeur. Cette page explique l'installation et la configuration de vimtex, la complétion et la recherche inverse via SyncTeX.

Qu'est-ce que vimtex

Ni Vim ni Neovim ne composent TeX lui-même ; la compilation proprement dite est effectuée par une distribution que vous installez — TeX Live (ou MiKTeX / MacTeX). vimtex est le pont : un plugin de type de fichier et de syntaxe pour .tex. Lorsqu'il détecte le type de fichier tex, il active automatiquement les commandes de construction, la coloration syntaxique, une fonction de complétion (omnifunc), une vue de table des matières, le passage à la définition pour \ref/\cite et des objets texte pour les environnements, les délimiteurs et les commandes. Son noyau fonctionne sans dépendances externes ; la complétion et les extraits sont associés aux plugins de votre choix.

Il y a trois conditions préalables. Tout d'abord, les commandes TeX doivent être accessibles sur votre PATH — vimtex génère latexmk et ses amis en tant que processus enfants, donc si latexmk --version s'exécute dans un terminal, tout va presque certainement bien. Deuxièmement, utilisez Vim 9.1 ou plus récent, ou Neovim 0.10 ou plus récent, comme l'exige le vimtex actuel. Troisièmement, Vim doit avoir la détection du type de fichier et la syntaxe activées. Votre vimrc/init.vim a besoin de ces deux lignes (la plupart des configurations les ont déjà) :

terminal
filetype plugin indent on
syntax enable

Configuration

Vous installez normalement vimtex avec un gestionnaire de plugins — vim-plug pour Vim, lazy.nvim pour Neovim, sont les choix courants. Une mise en garde essentielle : ne chargez pas vimtex paresseusement. Comme le projet le documente explicitement, le charger une fois le type de fichier détecté interrompt la recherche inverse décrite ci-dessous. La règle générale est lazy = false dans lazy.nvim, une charge explicite dans packer et aucune spécification paresseuse basée sur for dans vim-plug.

Une configuration minimale de Vim (vim-plug) est ci-dessous. Déclarez le plugin, activez le type de fichier/syntaxe et choisissez un spectateur PDF avec g:vimtex_view_method, et il commence à fonctionner. Puisque maplocalleader (le leader local) est le point d'entrée des commandes de vimtex, il est rassurant de le définir explicitement (la valeur par défaut est la barre oblique inverse \).

terminal
call plug#begin()
Plug 'lervag/vimtex'
call plug#end()

filetype plugin indent on
syntax enable

let maplocalleader = ' '          " use Space as <localleader>
let g:vimtex_view_method = 'zathura'   " 'skim' on macOS, 'sumatrapdf' on Windows
let g:vimtex_compiler_method = 'latexmk'

Dans Neovim (lazy.nvim), vous écrivez la même chose dans Lua. La définition des variables dans init les fait prendre effet avant le chargement du corps du plugin. N'oubliez pas lazy = false :

terminal
return {
  "lervag/vimtex",
  lazy = false,   -- do NOT lazy-load: it breaks inverse search
  init = function()
    vim.g.vimtex_view_method = "zathura"   -- "skim" / "sumatrapdf"
    vim.g.vimtex_compiler_method = "latexmk"
  end,
}

Ouvrez un fichier .tex et les commandes saisies sur <localleader>l deviennent disponibles. Les quatre qui méritent d’être mémorisés en premier sont :

ActionMappage par défautCe que ça fait
compile\llDémarrer/arrêter la compilation continue via latexmk ; se reconstruit automatiquement à chaque sauvegarde
view\lvOuvrez le PDF et forward-search (source → PDF) jusqu'au curseur
clean\lcNettoyer les fichiers auxiliaires (.aux, .log, …)
stop\lkArrêtez la compilation en cours (\lK arrête tout)

En pratique : appuyez une fois sur \ll et latexmk reste résident, actualisant le PDF à chaque sauvegarde par la suite. Utilisez \lv pour afficher l'emplacement actuel dans le PDF et \le pour mettre les erreurs dans la liste des correctifs rapides et accéder à la ligne incriminée. Quant à leur saisie : si le leader local est toujours \, vous appuyez sur \ll ; si vous l'avez basculé sur Espace, vous appuyez sur <Space>ll, et ainsi de suite.

Le compilateur par défaut est latexmk et vimtex transmet pour vous des options telles que -verbose -file-line-error -synctex=1 -interaction=nonstopmode. En particulier, -synctex=1 est activé par défaut, de sorte que les données de synchronisation nécessaires à la recherche directe et inverse ci-dessous sont émises sans aucune configuration supplémentaire. Pour utiliser Tectonic à la place, définissez g:vimtex_compiler_method = "tectonic" ; latexrun et arara sont également disponibles.

Pour le japonais, l'approche la plus propre est de laisser .latexmkrc choisir le moteur. Le backend latexmk de vimtex lit $pdf_mode à partir de .latexmkrc pour décider du chemin de traitement (1 = pdfLaTeX directement, 3 = construire un DVI puis convertir avec dvipdfmx, 4 = LuaLaTeX). Notez que les indicateurs de moteur comme -pdf/-lualatex ne doivent pas être ajoutés au options de vimtex ; précisez-les dans .latexmkrc ou via g:vimtex_compiler_latexmk_engines. Voici une configuration upLaTeX + dvipdfmx — la combinaison classique pour les articles japonais en sciences :

latex
$latex = 'uplatex -synctex=1 -interaction=nonstopmode -file-line-error %O %S';
$bibtex = 'upbibtex %O %B';
$biber = 'biber --bblencoding=utf8 -u -U --output_safechars %O %S';
$makeindex = 'upmendex %O -o %D %S';
$dvipdf = 'dvipdfmx %O -o %D %S';
$pdf_mode = 3;
$max_repeat = 5;

Les points clés : attribuez uplatex à $latex et dvipdfmx à $dvipdf, puis configurez $pdf_mode = 3 pour choisir le chemin « construire un DVI, puis le convertir en PDF avec dvipdfmx ». Passer -synctex=1 à $latex transporte également les données SyncTeX vers le PDF même via DVI. Si vous tapez du japonais avec LuaLaTeX, vous n'avez pas du tout besoin d'un .latexmkrc - demandez simplement à g:vimtex_compiler_latexmk_engines de sélectionner lualatex ou d'écrire $pdf_mode = 4 (en supposant que luatexja/ltjsclasses).

Achèvement

vimtex propose des candidats contextuels via la fonction de complétion standard de Vim (omnifunc). Dans un tampon tex, il définit automatiquement omnifunc=vimtex#complete#omnifunc, donc tant que g:vimtex_complete_enabled (1 par défaut) est activé, il est prêt à être utilisé. Les principales choses qu'il accomplit :

  • \cite{...} — lit les fichiers .bib et \bibitems pour compléter les clés de citation.
  • \ref{...} / \eqref{...} — rassemble les \label dans le document pour compléter les références.
  • Commandes et environnements : noms d'environnement \commands et \begin{...} en fonction des packages que vous chargez.
  • Noms de fichiers : chemins d'accès aux figures, \input/\include, \includepdf, etc.
  • Noms de glossaire et de package : entrées glossaries et noms de package basés sur les fichiers .sty/.cls disponibles.

En clair Vim, appuyez sur Ctrl-X Ctrl-O (le déclencheur d'omni-complétion) en mode insertion et les candidats apparaissent. Tapez \cite{ puis Ctrl-X Ctrl-O, par exemple, et vos clés de citation sont répertoriées. Cependant, appuyer dessus à chaque fois est fastidieux, donc dans la pratique, les gens connectent l'omnifunc à un moteur de complétion qui affiche automatiquement des suggestions au fur et à mesure que vous tapez.

Pour une configuration Neovim moderne, nvim-cmp est le choix habituel. Ajoutez directement sa source omni et les candidats du flux omnifunc de vimtex :

terminal
local cmp = require("cmp")
cmp.setup({
  sources = cmp.config.sources({
    { name = "omni" },   -- pulls vimtex completion via omnifunc
  }),
})

Si vous préférez coc.nvim (qui fonctionne à la fois dans Vim et Neovim), installez l'extension coc-omni et incluez le type de fichier tex parmi ses sources omni. Sur les anciennes configurations deoplete, associez-le à deoplete-vimtex. Dans tous les cas, la division du travail est la même : vimtex produit les candidats, et le moteur de complétion décide quand et comment les présenter.

SyncTeX enregistre la correspondance entre les lignes source et les positions dans le PDF. Il permet la recherche avant — passer de votre position d'édition au PDF — et la recherche inverse — passer d'un endroit du PDF à la ligne source. vimtex gère la recherche avant pour vous, il vous suffit donc d'appuyer sur \lv. La recherche inverse est la partie la plus délicate : elle nécessite que le visualiseur PDF rappelle Vim. L'élément clé est la commande :VimtexInverseSearch fournie par vimtex.

Voici le mécanisme. À l'aide de SyncTeX, le visualiseur détermine à quelle ligne source et à quel fichier correspond un clic, puis exécute une commande shell pour appeler l'éditeur avec ce numéro de ligne et ce fichier comme arguments. Dans cette commande, vous appelez VimtexInverseSearch <line> <file>, et vimtex#view#inverse_search localise votre Vim/Neovim en cours d'exécution et ouvre le spot. vimtex gère plusieurs instances et noms de serveurs pour vous, vous n'avez donc généralement pas besoin de transmettre vous-même un --servername. Les noms d'espace réservé diffèrent selon le visualiseur : la ligne et le fichier sont %{line}/%{input} dans zathura, %line/%file dans Skim et %l/%f dans SumatraPDF.

Linux — zathura. L'association la plus testée au combat avec vimtex. Avec g:vimtex_view_method = "zathura", vous obtenez une recherche directe via \lv et, dans la plupart des cas, une recherche inverse sans pratiquement aucune configuration : vimtex lance zathura avec -x et lui transmet la commande d'éditeur qui appelle VimtexInverseSearch pour vous (sur les systèmes sans xdotool, utilisez zathura_simple). Dans zathura, Ctrl-click se déplace vers la ligne source correspondante.

Si vous souhaitez le configurer vous-même, ou synchroniser également la colonne, mettez-le directement dans zathurarc. les espaces réservés de zathura sont %{line} et %{input} (remarque : pas %l/%f) ; avec une version prenant en charge les colonnes, vous pouvez également utiliser %{column} :

terminal
set synctex true
set synctex-editor-command "nvim --headless -c 'VimtexInverseSearch %{line} %{input}'"

macOS — Skim. Définissez g:vimtex_view_method = "skim". Du côté de Skim, ouvrez Préférences → Sync, définissez le préréglage sur « Personnalisé » et enregistrez une commande et des arguments. %line et %file sont remplacés par Skim avec le numéro de ligne et le fichier :

terminal
Command:   nvim
Arguments: --headless -c "VimtexInverseSearch %line '%file'"

Désormais, Cmd-Shift-click dans Skim effectue une recherche inverse : Skim lance Neovim en arrière-plan et VimtexInverseSearch relaie le spot vers votre instance existante.

Windows — SumatraPDF. Définissez g:vimtex_view_method = "sumatrapdf". Dans SumatraPDF, sous Settings → Options → « Définir la ligne de commande de recherche inverse », enregistrez une commande comme celle-ci (%l et %f sont le numéro de ligne et le fichier) :

terminal
cmd /c start /min "" nvim --headless -c "VimtexInverseSearch %l '%f'"

Dans SumatraPDF, un double-clic déclenche une recherche inverse. Pour gVim simple, remplacez la partie nvim --headless par vim -v --not-a-term -T dumb (gVim et Vim sur Windows démarrent automatiquement un serveur).

Une dernière mise en garde. Vim exécuté dans un terminal (Linux/macOS) ne démarre pas de serveur par défaut, donc les utilisateurs de Vim doivent ajouter ce qui suit à vimrc pour être accessible par le rappel de recherche inverse (Neovim n'a besoin de rien de tout cela) :

terminal
if empty(v:servername) && exists('*remote_startserver')
  call remote_startserver('VIM')
endif

Sur chaque OS et visualiseur, la condition préalable est que le document ait été compilé avec -synctex=1 — mais comme indiqué, cela fait déjà partie des options latexmk par défaut de vimtex, vous devez donc rarement y penser.

La boucle d'édition vimtex

vimtex n'est pas un outil qu'il faut maîtriser avant d'écrire. Premier verrouillage en quatre mouvements : démarrez la compilation continue avec \ll, enregistrez, passez au PDF avec \lv et inspectez uniquement les erreurs avec \le. Lorsque vous ajoutez des équations ou des figures, insérez \ref{...} jusqu'à la complétion de l'étiquette et décidez comment le fichier racine est détecté avant de diviser les chapitres. Si cette boucle d'édition vimtex est réglée en premier, les moteurs de complétion et les extraits de code peuvent être ajoutés ultérieurement sans perturber la ligne d'écriture principale.

Avant de passer à un document multi-fichiers, placez le fichier avec \documentclass au centre du projet et confirmez que la compilation à partir d'un fichier enfant crée toujours le même PDF. Si \ll d'un chapitre produit une cible différente, corrigez la détection de racine et .latexmkrc avant d'ajouter d'autres extraits de code ou couches de complétion.