XDG Base Directory specification, $XDG_CONFIG_HOME
etc. Great thing - configs
separated from user data and cache, no clutter in home directory. Unfortunately,
many programs still don't respect it, including Vim. But what would be our favourite
text editor if we wouldn't be able to reconfigure it!
TL;DR #
Into shell config (e.g. in ~/.profile
):
export VIMINIT="set nocp | source ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc"
At the top of vimrc:
" XDG support
if empty($MYVIMRC) | let $MYVIMRC = expand('<sfile>:p') | endif
if empty($XDG_CACHE_HOME) | let $XDG_CACHE_HOME = $HOME."/.cache" | endif
if empty($XDG_CONFIG_HOME) | let $XDG_CONFIG_HOME = $HOME."/.config" | endif
if empty($XDG_DATA_HOME) | let $XDG_DATA_HOME = $HOME."/.local/share" | endif
if empty($XDG_STATE_HOME) | let $XDG_STATE_HOME = $HOME."/.local/state" | endif
set runtimepath^=$XDG_CONFIG_HOME/vim
set runtimepath+=$XDG_DATA_HOME/vim
set runtimepath+=$XDG_CONFIG_HOME/vim/after
set packpath^=$XDG_DATA_HOME/vim,$XDG_CONFIG_HOME/vim
set packpath+=$XDG_CONFIG_HOME/vim/after,$XDG_DATA_HOME/vim/after
let g:netrw_home = $XDG_DATA_HOME."/vim"
call mkdir($XDG_DATA_HOME."/vim/spell", 'p', 0700)
set backupdir=$XDG_STATE_HOME/vim/backup | call mkdir(&backupdir, 'p', 0700)
set directory=$XDG_STATE_HOME/vim/swap | call mkdir(&directory, 'p', 0700)
set undodir=$XDG_STATE_HOME/vim/undo | call mkdir(&undodir, 'p', 0700)
set viewdir=$XDG_STATE_HOME/vim/view | call mkdir(&viewdir, 'p', 0700)
if !has('nvim') " Neovim has its own special location
set viminfofile=$XDG_STATE_HOME/vim/viminfo
endif
Step-by-step #
Relocating vimrc #
To begin with, since version 7.3.1178, Vim will search for ~/.vim/vimrc
if
~/.vimrc
is not found. So let's move the file there.
Let's move our ~/.vim
to $XDG_CONFIG_HOME/vim
. Now we need to command Vim
to read config from this new location prior to ~/.vim
. There are three ways
to do it.
Shell alias #
Pretty straightforward method. Shell will just substitute command vim
with the alias body
alias vim='vim -u ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc'
Downside? Works only in shell
VIMINIT
environmental variable #
export VIMINIT="set nocp | source ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc"
Cons? If you wish for Neovim and Vim configurations to still be separated, then:
export VIMINIT="if has("nvim") | so ${XDG_CONFIG_HOME:-$HOME/.config}/nvim/init.vim | else | set nocp | so ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc | endif"
Wrapper script #
Save the following code as vim
in $HOME/.local/bin
*
and make is executable with chmod +x vim
#!/usr/bin/env sh
IFS='
'
for dir in "$(echo "$PATH" | tr ":" "\n" | grep -Fxv "$(dirname $0)")"; do
if [ -x "$dir/vim" ]; then
exec "$dir/vim" -u "${XDG_CONFIG_HOME:-$HOME/.config}"/vim/vimrc "$@"
fi
done
Doesn't affect Neovim and works outside shell, but you need to carry it together with your config
* Remember to add it to the beginning of PATH
environment variable.
It can be also other location of your choice instead of $HOME/.local/bin
Now the code in our vimrc #
First of all, although not mandatory, let's set $MYVIMRC
variable:
if empty($MYVIMRC) | let $MYVIMRC = expand('<sfile>:p') | endif
Let's define fallback locations in case XDG_*
variables are not set.
if empty($XDG_CACHE_HOME) | let $XDG_CACHE_HOME = $HOME."/.cache" | endif
if empty($XDG_CONFIG_HOME) | let $XDG_CONFIG_HOME = $HOME."/.config" | endif
if empty($XDG_DATA_HOME) | let $XDG_DATA_HOME = $HOME."/.local/share" | endif
if empty($XDG_STATE_HOME) | let $XDG_STATE_HOME = $HOME."/.local/state" | endif
Let's add entries to runtimepath
:
set runtimepath^=$XDG_CONFIG_HOME/vim
set runtimepath+=$XDG_DATA_HOME/vim
set runtimepath+=$XDG_CONFIG_HOME/vim/after
$XDG_CONFIG_HOME/vim
and $XDG_CONFIG_HOME/vim/after
are just equivalents of
~/.vim
and ~/.vim/after
, but $XDG_DATA_HOME/vim
is brand new - there we
will keep downloadables (like plugins and spell files), Netrw bookmarks etc.
Let's set directory for Vim8 build-in packages:
set packpath^=$XDG_DATA_HOME/vim
set packpath+=$XDG_DATA_HOME/vim/after
Netrw is just as easy:
let g:netrw_home = $XDG_DATA_HOME."/vim"
What about spellings? Well, this one is more tricky, because it isn't controlled
by any option. Instead it searches for spell
directory in whole runtime path.
If none is found then it falls back to ~/.vim/spell
. So let's create one at
desired location ourselves!
call mkdir($XDG_DATA_HOME."/vim/spell", 'p', 0700)
So far so good. We are left with state (backup, undo, swap, viminfo, view).
Vim doesn't create directories for them (even for defaults), so we will need
to do it ourselves - thankfully VimL has mkdir()
function.
set backupdir=$XDG_STATE_HOME/vim/backup | call mkdir(&backupdir, 'p', 0700)
set directory=$XDG_STATE_HOME/vim/swap | call mkdir(&directory, 'p', 0700)
set undodir=$XDG_STATE_HOME/vim/undo | call mkdir(&undodir, 'p', 0700)
set viewdir=$XDG_STATE_HOME/vim/view | call mkdir(&viewdir, 'p', 0700)
if !has('nvim') " Neovim has its own location which already complies with XDG specification
set viminfofile=$XDG_STATE_HOME/vim/viminfo
endif
Congratulations! Now your Vim is configured with accordance to XDG Base Directory specification.