Vim is a customizable and fast editor. The ability to adapt Vim to your needs makes it a very powerful tool.
Vim is for power-users and tinkerers. It uses less resources than modern alternatives like VS Code. You can use it without a mouse. That’s why you can edit text at “the speed of thought”.
The editor’s basic functionality already covers a lot of ground.
You can see it in action in this Youtube video:
Still, sometimes you want to enhance your experience with a plugin.
vim-packager is a minimal package manager for Vim 8 and NeoVim. It’s written in pure VimScript and thus needs no external dependencies.
vim-packager uses Vim’s native jobs and pack features. It sports an informative window when you use it:
image from the vim-packager GitHub ReadmeHow Does Package Management Work in Vim?
What are packages? What exactly are plugins?
Let’s define some vocabulary:
I’ve been using the word “plugin” to mean “a big ol’ hunk of Vimscript that does a bunch of related stuff”. Vim has a more specific meaning of “plugin”, which is “a file in
~/.vim/plugin/
”.
The folder ~/.vim/plugin
loads all plugins every time you start the Vim editor.
Vim also has a directory ~/.vim/autoload
. Vim delays the loading of a plugin located in that folder.
Unfortunately, adding a plugin that consists of more than one file requires you to manually add the code to Vim’s runtime path
. That’s cumbersome.
In newer versions of Vim, the authors added a native package feature (see :h packages
) which makes plugin management easier. It also supports lazy-loading.
You can find a guide here or here.
Updating plugins is still a hassle because you have to update each plugin yourself (or write your own script).
vim-packager
Kristijan Husak’s vim-packager adds a convenience wrapper around the native package management. It offers some additional features that make package management frictionless.
Find the installation instructions on GitHub and clone the repository to your computer.
For example, for NeoVim on Mac/Linux:
git clone https://github.com/kristijanhusak/vim-packager ~/.config/nvim/pack/packager/opt/vim-packager
Create your configuration (~/.vimrc
, ~./config/nvim/init.vim
or similar) according to the GitHub instructions:
" Only for Vim, NeoVim sets nocompatible automatically
if &compatible
set nocompatible
endif
" Load packager only when you need it
function! PackagerInit() abort
packadd vim-packager
call packager#init()
call packager#add('kristijanhusak/vim-packager', { 'type': 'opt' })
call packager#add('junegunn/fzf', { 'do': './install --all && ln -s $(pwd) ~/.fzf'})
call packager#add('junegunn/fzf.vim')
call packager#add('vimwiki/vimwiki', { 'type': 'opt' })
call packager#add('autozimu/LanguageClient-neovim', { 'do': 'bash install.sh' })
call packager#add('morhetz/gruvbox')
call packager#local('~/my_vim_plugins/my_awesome_plugin')
"Provide full URL; useful if you want to clone from somewhere else than Github.
call packager#add('https://my.other.public.git/tpope/vim-fugitive.git')
"Provide SSH-based URL; useful if you have write access to a repository and wish to push to it
call packager#add('git@github.com:mygithubid/myrepo.git')
"Loaded only for specific filetypes on demand. Requires autocommands below.
call packager#add('kristijanhusak/vim-js-file-import', { 'do': 'npm install', 'type': 'opt' })
call packager#add('fatih/vim-go', { 'do': ':GoInstallBinaries', 'type': 'opt' })
call packager#add('neoclide/coc.nvim', { 'do': function('InstallCoc') })
call packager#add('sonph/onehalf', {'rtp': 'vim/'})
endfunction
function! InstallCoc(plugin) abort
exe '!cd '.a:plugin.dir.' && yarn install'
call coc#add_extension('coc-eslint', 'coc-tsserver', 'coc-pyls')
endfunction
command! PackagerInstall call PackagerInit() | call packager#install()
command! -bang PackagerUpdate call PackagerInit() | call packager#update({ 'force_hooks': '<bang>' })
command! PackagerClean call PackagerInit() | call packager#clean()
command! PackagerStatus call PackagerInit() | call packager#status()
"Load plugins only for specific filetype
"Note that this should not be done for plugins that handle their loading using ftplugin file.
"More info in :help pack-add
augroup packager_filetype
autocmd!
autocmd FileType javascript packadd vim-js-file-import
autocmd FileType go packadd vim-go
augroup END
"Lazy load plugins with a mapping
nnoremap <silent><Leader>ww :unmap <Leader>ww<BAR>packadd vimwiki<BAR>VimwikiIndex<CR>
Now you can run the Vim command :PackagerInstall
.
Updating all packages is as easy as running the :PackagerUpdate
command.
Sweet!
Tips & Tricks
If you want to load several plugins conditionally or load plugins for several filetypes, you can chain the commands like this:
" Load plugins only for specific filetype
augroup packager_filetype
autocmd!
autocmd FileType dart packadd awesome-flutter-snippets | packadd vim-lsc-dart
autocmd FileType html,eelixir packadd emmet-vim
end
This works for plugins that you installed with { 'type': 'opt' }
. Otherwise the plugins are installed into the start
folder and loaded automatically every time.
Further Reading
- vim-packager by Kristjan Husak
- Exploring Vim Plugins: A Methodology to Become 1% Better Every Week by Jaime Gonzalez Garcia
- How to Do 90% of What Plugins Do (With Just Vim) by Maxin Cardamom
- Vim: So long Pathogen, hello native package loading by George Ornbo
- Managing plugins in Vim: The basics by Manas Thakur
- Practical Vim: Edit Text at the Speed of Thought by Drew Neil
- Learn Vimscript the Hard Way by Steve Losh