Last time I showed you how to setup vim with a basic config which you can extend to make vim exactly how you like it.
In this article, we'll setup LSP support, Autocomplete, and Syntax Highlighting.
Before You Start
It's important to know what plugin is taking care of what responsibility so you can customize things to your own taste later. I'll explain each functionality and how it's achieved in an abstract way in this section.
To summarize, there are 3 independent concepts you should know about:
LSP is different from Syntax Highlighting is different from Autocomplete!
And to achieve the functionality we need, we'll use the following plugins:
- lsp-zero (and its dependencies)
- mason
- nvim-lspconfig
- nvim-cmp
- treesitter
Language Server Protocol
LSP stands for language server protocol. Here's what the LSP does:
- Autocomplete options (but not the menu itself)
- Diagnostics
- Code actions (refactor, extract function, etc.)
- Import management
- Other (depends on language & specific LSP)
Syntax Highlighting
Syntax highlighting is how you get all the pretty colors in your code.
Autocomplete
Gives you completion options based on where your cursor currently is and what you're typing with the help of your LSP.
With that out of the way, let's get to setting everything up.
Setting Up Syntax Highlighting
Install nvim-treesitter
. I'll do it with Packer (refer to 1st article):
-- packer.lua
return require("packer").startup(
function(use)
-- ... other plugins ...
use("nvim-treesitter/nvim-treesitter", {run = ":TSUpdate"})
end
)
Then run :so
followed by :PackerSync
to install it.
Next, create a configuration for it using whatever method you like. I did it by creating a file under ~/.config/nvim/after/plugin/treesitter.lua
require "nvim-treesitter.configs".setup {
-- A list of parser names, or "all" (customize according to taste)
ensure_installed = {"javascript", "typescript", "rust", "lua", "vim", "vimdoc", "query"},
-- Install parsers synchronously (only applied to `ensure_installed`)
sync_install = false,
-- Automatically install missing parsers when entering buffer
auto_install = true,
highlight = {
enable = true,
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
-- Using this option may slow down your editor, and you may see some duplicate highlights.
-- Instead of true it can also be a list of languages
additional_vim_regex_highlighting = false
}
}
Above is my own personal configuration. You can mess around with yours to make it do whatever you like. Check the docs for more info.
With that, you're done! Now this plugin will automatically install whatever's necessary to highlight your code without you needing to do a thing!
LSP Zero (Autocomplete & Language Support)
Add the following to your packer file:
use {
"VonHeikemen/lsp-zero.nvim",
branch = "v2.x",
requires = {
-- LSP Support
{"neovim/nvim-lspconfig"}, -- Required
{
-- Optional
"williamboman/mason.nvim",
run = function()
pcall(vim.cmd, "MasonUpdate")
end
},
{"williamboman/mason-lspconfig.nvim"}, -- Optional
-- Autocompletion
{"hrsh7th/nvim-cmp"}, -- Required
{"hrsh7th/cmp-nvim-lsp"}, -- Required
{"L3MON4D3/LuaSnip"} -- Required
}
}
Then run :so
followed by :PackerSync
to install all the added plugins.
If all goes well, you should be ready to setup your config.
I set mine up under ~/.config/nvim/after/lsp.lua
as the following:
local lsp = require("lsp-zero")
lsp.preset("recommended")
-- navigating completions in the autocomplete popup
local cmp = require("cmp")
local cmp_select = {behavior = cmp.SelectBehavior.Select}
local cmp_mappings =
lsp.defaults.cmp_mappings(
{
-- prev item in menu
["<C-p>"] = cmp.mapping.select_prev_item(cmp_select),
-- next item in menu
["<C-n>"] = cmp.mapping.select_next_item(cmp_select),
-- confirm current selection
["<C-y>"] = cmp.mapping.confirm({select = true}),
-- misc
["<C-Space>"] = cmp.mapping.complete()
}
)
-- assigning previously defined mappings
lsp.setup_nvim_cmp(
{
mappings = cmp_mappings
}
)
-- shortcuts for making use of LSPs
lsp.on_attach(
function(client, bufnr)
local opts = {buffer = bufnr, remap = false}
-- go to definition of symbol under cursor
vim.keymap.set(
"n",
"gd",
function()
vim.lsp.buf.definition()
end,
opts
)
-- shows info about current symbol as if you hovered on it
-- with the cursor (really handy!)
vim.keymap.set(
"n",
"K",
function()
vim.lsp.buf.hover()
end,
opts
)
-- lookup a workspace symbol
vim.keymap.set(
"n",
"<leader>vws",
function()
vim.lsp.buf.workspace_symbol()
end,
opts
)
-- show diagnostic in a floating dialog (like when you hover on a
-- a line with a red squiggly under it)
vim.keymap.set(
"n",
"<leader>vd",
function()
vim.diagnostic.open_float()
end,
opts
)
-- go to next diagnostic
vim.keymap.set(
"n",
"[d",
function()
vim.diagnostic.goto_next()
end,
opts
)
-- go to prev diagnostic
vim.keymap.set(
"n",
"]d",
function()
vim.diagnostic.goto_prev()
end,
opts
)
-- show code actions (refactor, inline function, etc..)
vim.keymap.set(
"n",
"<leader>vca",
function()
vim.lsp.buf.code_action()
end,
opts
)
-- show references to symbol under cursor
vim.keymap.set(
"n",
"<leader>vrr",
function()
vim.lsp.buf.references()
end,
opts
)
-- rename current symbol (works across files too!)
vim.keymap.set(
"n",
"<leader>vrn",
function()
vim.lsp.buf.rename()
end,
opts
)
-- show help for current function when in insert mode (helps to see
-- params of current function for example)
vim.keymap.set(
"i",
"<C-h>",
function()
vim.lsp.buf.signature_help()
end,
opts
)
end
)
-- setup lua language server (with support for nvim)
require("lspconfig").lua_ls.setup(lsp.nvim_lua_ls())
lsp.setup()
The above configuration sets up everything you need for a base you can expand on. I've added a lot of annotations to make it easier to know what does what.
Whenever you add an LSP, autocomplete and everything else will "just work" requiring only minimal configuration most of the time.
For most of your needs, you should consult the lspconfig server configurations page.
Let's add the html and emmet LSPs as a demo.
Step 1: Install it with LspInstall
. To do this, simply run the command :LspInstall
from a file with the .html
extension.
We'll do the same to install support for emmet
Let's do a quick check to see if that worked. Exit your current vim session and open it again so the LSPs are loaded.
Here's a demo of emmet with autocomplete:
And here is what the html lsp gives us:
Step 2: configure LSPs with lspconfig (if necessary)
For the emmet and html LSPs, this isn't necessary (thanks to lsp-zero). You can still do it if you want to customize things to your needs. Refer to the server configurations page in that case.
You can see an example at the bottom of this file in my own neovim config.
What actually happened here though? Let's break it down:
- You ran the
:LspInstall
command which looked up what LSPs are associated with the file you have open - You installed the html and emmet lsps suggested by LspInstall, which in turn installed them using Mason (it's the popup that shows after you select which lsp to install)
If you want to see what LSPs you have installed, you can run the :Mason
command.
You can use some basic shortcuts to manage your LSPs from this menu, like i
to install an available LSP, X
to uninstall one, and /
to search for one. You can exit this menu using q
.
Conclusion
We setup syntax highlighting with Nvim-Treesitter, and language support, including autocomplete and diagnostics, using lsp-zero, mason, and nvim-cmp.
Here's my own nvim config if you're interested (yes, I will shamelessly link to this every time 🌚):
Top comments (0)