3. Vim’s ftplugin system
This is part three in a seven-part series explaining how to use the Vim or Neovim text editors to efficiently write LaTeX documents.
This article covers Vim’s ftplugin system, which allows you to create customizations that apply only to LaTeX files (or any other file type).
Understanding this article will give you a clearer mental model of how the VimTeX plugin works.
Contents of this article
The basics of file-specific Vim plugins
What is a plugin?
Officially, as defined in :help plugin, a plugin is the name for a Vimscript file that is loaded when you start Vim.
If you have ever created a vimrc or init.vim file, which are just simple Vimscript files, you have technically written a Vim plugin.
Just like your vimrc, a plugin’s purpose is to extend Vim’s default functionality to meet your personal needs.
A package, as defined in :help packages, is a set of Vimscript files.
To be pedantic, what most people (myself included) refer to in everyday usage as a Vim plugin is technically a package.
That’s irrelevant; the point is that plugins and packages are just Vimscript files used to extend Vim’s default functionality, and, if you have ever written a vimrc or init.vim, it is within your means to write more advanced plugins, too.
Runtimepath: where Vim looks for files to load
Vim’s runtimepath is a list of directories, both in your home directory and system-wide, that Vim searches for files to load at runtime, i.e. when opening Vim.
Below is a list of some directories on Vim’s default runtimepath, taken from :help runtimepath—you will probably recognize some of them from your own Vim setup.
| Directory or File | Description |
|---|---|
filetype.vim |
Used to set a file’s Vim filetype |
autoload/ |
Scripts loaded dynamically using Vim’s autoload feature |
colors/ |
Vim colorscheme files conventionally go here |
compiler/ |
Contains files related to compilation and make functionality |
doc/ |
Contains documentation and help files |
ftplugin/ |
Filetype-specific configurations go here |
indent/ |
Contains scripts related to indentation |
pack/ |
Vim’s default location for third-party plugins |
spell/ |
Files related to spell-checking |
syntax/ |
Contains scripts related to syntax highlighting |
You can view your current runtimepath with :echo &runtimepath.
If you want a plugin to load automatically when you open Vim, you must place the plugin in an appropriate location in your runtimepath.
For the purposes of this series, the most important directory in your runtimepath is the ftplugin/ directory in your Vim config folder, i.e. the directory ~/.vim/ftplugin/ on Vim and ~/.config/nvim/ftplugin/ on Neovim.
Here’s why it is so important: ftplugin/ is the correct directory to place LaTeX-specific configuration (or in general any configuration that you wish to apply only to a single file type), and this entire series is all about LaTeX-specific configuration.
Vim’s filetype plugin system
Say you’ve written some customizations that you want to apply only to LaTeX files, and not to any other file types. To keep your LaTeX customizations specific to only LaTeX files, you should use Vim’s filetype plugin system.
Filetype plugin basic recipe
Say you want to write a plugin that applies only to LaTeX files. Here’s what to do:
-
Add the following lines to your
vimrc(these settings are enabled by default on Neovim—see:help nvim-defaults—but it can’t hurt to place them in yourinit.vim, too):filetype on " enable filetype detection filetype plugin on " load file-specific plugins filetype indent on " load file-specific indentationThese lines enable filetype detection and filetype-specific plugins and indentation. To get an overview of your current filetype status, use the
:filetypecommand; you want an output that reads:" With Vim's filetype-specific functionality enabled, the output looks like this filetype detection:ON plugin:ON indent:ONSee
:help filetypefor more information on filetype plugins. -
Create the file structure
~/.vim/ftplugin/tex.vim. Your LaTeX-specific mappings and functions will go in~/.vim/ftplugin/tex.vim. That’s it! Assuming you followed step 1, anything intex.vimwill be loaded only when editing files with thetexfiletype (i.e. LaTeX and related files), and will not interfere with your other filetype plugins.Optional tip: You can also split up your
texcustomizations among multiple files (instead of having a single, clutteredtex.vimfile). To do this, create the file structure~/.vim/ftplugin/tex/*.vim. Any Vimscript files inside~/.vim/ftplugin/tex/will then load automatically when editing files with thetexfiletype. As a concrete example, you might design yourftplugindirectory like this:# Two ways to have LaTeX-specific configuration; # note the dedicated `tex` folder in the second example ftplugin/ ftplugin/ ├── tex.vim ├── markdown.vim ├── markdown.vim ├── python.vim └── python.vim └── tex ├── vimtex.vim └── main.vimThe first example uses a single
tex.vimfile insideftplugin. In the second example, thetex-specific configuration is divided into two files—vimtex.vimmight store configuration related to the VimTeX plugin andmain.texwould store general settings for thetexfiletype.
The following sections explain how loading filetype plugins works under the hood.
Automatic filetype detection
-
Vim keeps track of a file’s type using the
filetypeoption. You can view Vim’s opinion of a file’sfiletypeusing the commands:set filetype?or:echo &filetype. -
Once you set
:filetype onin yourvimrc(enabled by default on Neovim), Vim automatically detects common filetypes (LaTeX included) based on the file’s extension using a Vimscript file calledfiletype.vimthat ships with Vim. You can viewfiletype.vim’s source code at the path$VIMRUNTIME/filetype.vim(first use:echo $VIMRUNTIMEin Vim to determine$VIMRUNTIME).
Manual filetype detection
If Vim’s default filetype detection using filetype.vim fails (this only happens for exotic filetypes), you can also manually configure Vim to detect the target filetype.
Note that manual detection of exotic filetypes is not needed for this tutorial (Vim detects LaTeX files without any configuration on your part), so feel free to skip ahead.
But if you’re curious, here’s an example using LilyPond files, which by convention have the extension .ly.
(LilyPond is a free and open-source text-based system for elegantly typesetting musical notation; as an analogy, LilyPond is for music what LaTeX is for math.)
Here’s what to do for manual filetype detection:
-
Identify the extension(s) you expect for the target filetype, e.g.
.lyfor LilyPond. -
Make up some reasonable value that Vim’s
filetypevariable should take for the target filetype. This can match the extension, but doesn’t have to. For LilyPond files I usefiletype=lilypond. -
Create the file
~/.vim/ftdetect/lilypond.vim(the file name, in this caselilypond.vim, can technically be anything ending in.vim, but by convention should match the value offiletype). Inside the file add the single lineautocmd BufNewFile,BufRead *.ly set filetype=lilypondOf course replace
.lywith your target extension andlilypondwith the value offiletypeyou chose in step 2.
How Vim loads filetype plugins
The relevant documentation lives at :help filetype and :help ftplugin, but is rather long.
For our purposes:
-
When you open a file with Vim, assuming you have set
:filetype on, Vim tries to determine the file’s type by cross-checking the file’s extension against a set of extensions found in$VIMRUNTIME/filetype.vim. Generally this method works out of the box (filetype.vimis over 2300 lines and covers the majority of common files).If the file’s type is not detected from extension, Vim attempts to guess the file type based on file contents using
$VIMRUNTIME/scripts.vim(reference::help filetype). If both$VIMRUNTIME/filetype.vimand$VIMRUNTIME/scripts.vimfail, Vim checks the contents offtdetectdirectories in yourruntimepath, as described in the section Manual filetype detection a few paragraphs above. -
If Vim successfully detects a file’s type, it sets the value of the
filetypeoption to indicate the file type. Often, but not always, the value offiletypematches the file’s conventional extension; for LaTeX this value isfiletype=tex. You can check the current value offiletypewithecho &filetypeor:set filetype?. -
After the
filetypeoption is set, Vim checks the contents of your~/.vim/ftplugindirectory, if you have one. If Vim finds either…-
a file
ftplugin/{filetype}.vim(e.g.filetype/tex.vimforfiletype=tex), then Vim loads the contents of{filetype}.vim, or -
a directory
ftplugin/{filetype}(e.g.ftplugin/texfor thefiletype=tex), then Vim loads all.vimfiles inside the{filetype}directory.
-
As a best practice, keep filetype-specific settings in either in a dedicated {filetype}.vim file at ftplugin/{filetype}.vim,
or split up among multiple files in ftplugin/{filetype}/*.vim.
Think of the ftplugin files as a vimrc for one file type only,
and keep your actual vimrc for global settings you want to apply to all file types.
The original writing, images, and animations in this series are licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.