2023-12-29
Vim is a great terminal text editor.
Much ink has been spilled about how to be productive in vim. I recommend reading https://pragprog.com/titles/dnvim2/practical-vim-second-edition/
Vim configuration can be endless, but to start somewhere, I’ll cover how I track my vim configuration in git, and how I track plugins using my vimrc and built-in plugin management.
Run vim --version
, and you’ll see, after all the vim features, the many vimrc files:
$ vim --version
VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Dec 04 2023 12:42:16)
Included patches: 1-1672, 1729, 1747, 2107, 1840, 1846-1848, 1857-1858, 1873, 1969, 1992, 2010, 2068, 2106, 2108-2112, 2121
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Huge version without GUI. Features included (+) or not (-):
+acl +file_in_path +mouse_urxvt -tag_any_white
[...]
+extra_search +mouse_sgr +tag_binary
-farsi -mouse_sysmouse -tag_old_static
system vimrc file: "/etc/vim/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
...
I recommend using ~/.vim/vimrc
, so that you can make the whole .vim
directory a git repository.
$ mkdir ~/.vim
$ cd ~/.vim
.vim $ echo '# vim config' > README.md
.vim $ git init
.vim $ git add .
.vim $ git commit -m 'Initial commit'
# and you're all set to start configuring vim!
.vim $ vim vimrc
Perhaps you’ll be a stoic vim user with a minimal vimrc. I do recommend learning how to do most things in vim without plugins; especially since I use vim on remote machines which don’t have my config, it’s useful to know how vim works out-of-the-box. And it is already quite powerful! But if you’re like me, eventually you’ll start adding plugins to your vim config.
To manage plugins, I tried several solutions, and Plug is in fact quite nice, but I ended up creating my own solution for 3 reasons:
bootstrapping: 3rd-party package managers need to be bootstrapped. For Plug’s case, either you run their curl command manually or add their automatic installation to your .vimrc; however either way depends on a gist being reachable over the network which is a bit unwieldy
package installation: in order to use your packages, you must run :PlugInstall
.
To the credit of Plug
there is an autocmd
in the link above that ensures plugins
are installed in their automatic installation code I linked above, but since that runs
on VimEnter
, just reloading your vimrc will not install plugins;
you’ll have to manually install packages or restart vim.
vimrc organization: to me it’s an anti-pattern to have all packages jammed between a plug#begin
and a plug#end
; I think it’s better to install a package and then have any relevant configuration.
These calls seem a bit magical anyways.
Luckily there is a solid alternative! Since vim version 8 (released in 2016), vim has built-in package management.
You can read about it with :help package
but I’ll give you my guide here.
There are 2 places you can put plugins:
~/.vim/pack/vendor/opt/
where packages are not enabled by default, and~/.vim/pack/vendor/start/
where packages are loaded automatically.For a while I was just putting packages directly in /start/
as follows:
$ git clone https://github.com/DataWraith/auto_mkdir ~/.vim/pack/vendor/start/auto_mkdir
This will work in that it will load the package. However this has a couple downsides:
The fact that you ran this command is not tracked by default in git,
and since plugins like this are their own git repositories,
if you added and committed the pack
directory you’d be dealing with submodules.
If you are just trying out a module, you have to remove its repository to disable it.
Using /opt/
, it doesn’t load a package until you call packadd <package>
in your vimrc
,
so it takes care of the second concern. I used this for a bit, manually cloning repositories
whenever I needed to set up a new development environment, but I wanted to track the url of
the plugins as well, without submodules. So I added pack/
to my .gitignore
, and wrote the
following package loading code:
function! EnsurePackage(url)
let name = split(a:url, '/')[-1]
let target = $HOME . '/.vim/pack/vendor/opt/' . name
if !isdirectory(target)
silent execute '!git clone ' . a:url . ' ' . target
endif
execute 'packadd! ' . name
endfunction
command! -nargs=1 Package :call EnsurePackage(<q-args>)
which I can use it as follows:
Package https://github.com/bkad/CamelCaseMotion
And it will clone the plugin repository if it does not exist, and enable it.
Long story short, if you want to manage plugins like me,
put the function! EnsurePackage
and command! -nargs=1 Package
lines
verbatim in your vimrc (making them their own package would have the bootstrapping problem)
then add Package
commands anywhere after that.
You can then configure your packages right there next to these Package
calls.
Package https://github.com/tpope/vim-surround
vmap s S
This guide is a work in progress; eventually I’d like to cover tips and tricks and the plugins I use; for now, feel free to browse my personal configuration.