Show full content
As a longtime Vim user, I’ve been eyeing Neovim for a while. At work, I use VS Code because it supports language servers, which can speak LSP (the Language Server Protocol). As much as I like Vim, working on a large codebase is infeasible without LSP support. I tried to use the LSP packages that have popped up for Vim, but I couldn’t get them working. Neovim has native support for LSPs, so I decided to 1) switch to Neovim and 2) set up LSP support.
Step 1: Razzle DazzleI have a large and complicated .vimrc file, but I wanted to try out
Neovim’s features on Neovim’s terms. So I copied kickstart.nvim’s init.lua
file into my
Neovim (at ~/.config/nvim/init.lua) and launched Neovim.
Wow. Here’s my raw reaction: “holy shit”.
Here’s a closer look at that screenshot:
This looks like a modern terminal application! It reminds me of charm or rich. There’s lots of color, a floating popup window, parallel processes. I was sold.
Step 2: copy over my existing Vim configI deleted the kickstart.nvim code and ported my .vimrc to Neovim.
Neovim understands Vimscript, but its “native” scripting language is Lua. Since Vimscript is a terrible language, and I like learning new things, I pored over the Neovim Lua guide and the “Learn Lua in X minutes” cheatsheet.
There was a lot of fumbling with the various abstractions of Neovim/Lua/Vimscript but
I eventually figured it out and copied over my existing config in Lua. I didn’t
translate the portions that are pithier in Vimscript, like autocommands in
groups. I used vim.cmd to run Vimscript directly.
-- `vim.cmd` accepts arbitrary Vimscript
vim.cmd [[
augroup vimrc
autocmd!
autocmd User Rails nnoremap <Leader>u :Eunittest<Space>
autocmd BufReadCmd set nohlsearch
augroup END
]]
-- Compare to the following equivalent "pure Lua" approach.
augroup = vim.api.nvim_create_augroup("vimrc", { clear = true }),
vim.api.nvim_create_autocmd("User Rails", {
group = augroup,
callback = function(event)
vim.keymap.set("n", "<Leader>u", ":Eunittest<Space>", { noremap = true })
end
end
vim.api.nvim_create_autocmd("BufReadCmd", {
group = augroup,
callback = function(event)
-- The Lua equivalent to `set nohlsearch` in Vimscript
vim.o.hlsearch = false
end
end
You can check out this PR to see where I converted from Vim to a Neovim config.
Step 3: oh yeah, LSPsOnce my vim config was ported over, I set up LSPs. This was confusing because “having an LSP” is actually a lot of different pieces, and people talk about them as if they’re all one thing. But I learned that I can have an LSP working and still not have autocompletion. Here are the individual pieces, and the PR in my dotfiles where I implemented them.
- Having an LSP installed on your computer (e.g.
gem install ruby-lsp)- People use
mason.nvimfor this, a full package manager. I decided to just install each LSP manually until I understood everything better. I still haven’t installedmason.
- People use
- Neovim configuration for that LSP so Neovim can talk to it
- Everyone uses
nvim-lspconfigfor this. - I discovered that I had to explicitly set up each LSP that I wanted to use. I assumed Neovim would automatically detect what’s installed.
- I implemented that in this PR.
- Everyone uses
- Fun mappings for various LSP functions, like a fuzzy finder for all of the
methods in your project
- Neovim’s Lua interface lets me call LSP functions directly (
:lua vim.lsp.buf.references), but it’s not ergonomic. I set up Telescope because it’s the most popular fuzzy finder, and it has a lot of built in pieces for LSPs. - There’s a fun easter egg in Telescope: try
:Telescope planets. - I implemented the nice Telescope mappings in this PR.
- Neovim’s Lua interface lets me call LSP functions directly (
- Autocompletion on <Tab>
Now I have a working LSP with autocompletion! It’s so nice.