Skip to content
Chris Rawnsley edited this page Dec 5, 2019 · 4 revisions

Lazy-load vim-lsp

When you’re just wanting to make a quick adjustment to a file with Vim you may not appreciate an LSP server spinning up in the background delaying your edit.

Using Vim’s built-in packages system we can demonstrate how it is possible to achieve a lazy-loaded setup. You could then adapt this to your package manager of choice.

To keep things simple, let us assume a blank Vim configuration. First, we set vim-lsp to be optionally started. With Vim’s native package system, we do this by placing them in pack/<namespace>/opt within your .vim directory. Namespace can be anything; Vim doesn’t care what what it is. Let’s call ours “manual” as we are managing it manually.

cd /tmp
curl -L https://github.com/prabirshrestha/async.vim/archive/master.tar.gz \
	-o async.vim-master.tar.gz
curl -L https://github.com/prabirshrestha/vim-lsp/archive/master.tar.gz \
	-o vim-lsp-master.tar.gz
cd ~
mkdir -p .vim/pack/manual/opt
cd .vim/pack/manual/opt
tar xzvf /tmp/async.vim-master.tar.gz
tar xzvf /tmp/vim-lsp-master.tar.gz
mv async.vim-master async.vim
mv vim-lsp-master vim-lsp

(Well, that was quite laboursome! You can see why package managers still exist.)

Next, let’s edit ~/.vim/vimrc:

" Roughly, equivalent to Tim Pope's sensible but included with Vim
runtime! defaults.vim

augroup lsp_setup
	autocmd!
	if executable('typescript-language-server')
		autocmd User lsp_setup call lsp#register_server({
			\ 'name': 'typescript-language-server',
			\ 'cmd': {server_info->[
				\ &shell,
				\ &shellcmdflag,
				\ 'typescript-language-server --stdio',
			\ ]},
			\ 'root_uri':{server_info->lsp#utils#path_to_uri(
				\ lsp#utils#find_nearest_parent_file_directory(
					\ lsp#utils#get_buffer_path(),
					\ ['tsconfig.json', 'package.json']
				\ )
			\ )},
			\ 'whitelist': [
				\ 'javascript',
				\ 'typescript',
				\ 'typescriptreact'
			\ ],
		\ })
	endif
augroup END

" Lazy-load more advanced features
command! IDE
	\   packadd async.vim
	\ | packadd vim-lsp
	\ | source $MYVIMRC
	\ | call lsp#enable()

And that is it! When using Vim just type :IDE to load vim-lsp.

Of course, you may wish to add to the list of packages that are loaded in your version of “IDE” mode. Pay special attention to the source $MYVIMRC line; if your Vim configuration can be reloaded without side-effects you can change things on the fly. Automatic commands combined with groups can help a lot with this.

As an example, this is how you might like to handle folds:

" Regardless of whether they are enabled, always expand folds when loading
" a file. If we run :IDE after enabling, our fold's expanded state is then
" maintained.
set foldlevelstart=99
if get(g:, '__ide_mode_enabled', 0)
	set foldenable foldcolumn=4
else
	set nofoldenable
endif

command! IDE
	\ | packadd async.vim
	\ | packadd vim-lsp
	\ | let g:__ide_mode_enabled = 1
	\ | source $MYVIMRC
	\ | call lsp#enable()

Package managers

dein.vim (TODO)

Would you like to contribute this part of the article?

minpac

After setting up minpac, you can achieve the same setup through just putting this in your .vimrc file:

runtime defaults.vim

augroup lsp_setup
	autocmd!
	if executable('typescript-language-server')
		autocmd User lsp_setup call lsp#register_server({
			\ 'name': 'typescript-language-server',
			\ 'cmd': {server_info->[
				\ &shell,
				\ &shellcmdflag,
				\ 'typescript-language-server --stdio',
			\ ]},
			\ 'root_uri':{server_info->lsp#utils#path_to_uri(
				\ lsp#utils#find_nearest_parent_file_directory(
					\ lsp#utils#get_buffer_path(),
					\ ['tsconfig.json', 'package.json']
				\ )
			\ )},
			\ 'whitelist': [
				\ 'javascript',
				\ 'typescript',
				\ 'typescriptreact'
			\ ],
		\ })
	endif
augroup END

if exists('*minpac#init')
	call minpac#init()
	call minpac#add('k-takata/minpac', {'type': 'opt'})

	call minpac#add('prabirshrestha/async.vim', {'type': 'opt'})
	call minpac#add('prabirshrestha/vim-lsp', {'type': 'opt'})
endif

command! PackUpdate packadd minpac | source $MYVIMRC |
	\ call minpac#update('', {'do': 'call minpac#status()'})
command! PackClean packadd minpac | source $MYVIMRC | call minpac#clean()
command! PackStatus packadd minpac | source $MYVIMRC | call minpac#status()

" Lazy-load more advanced features
command! IDE
	\   packadd async.vim
	\ | packadd vim-lsp
	\ | source $MYVIMRC
	\ | call lsp#enable()

And then run :PackUpdate followed by :IDE.

vim-plug (TODO)

Would you like to contribute this part of the article?

Vundle (TODO)

Would you like to contribute this part of the article?