Combining LSPs and Telescope to find code references
Plus: Debugging failed LSP installations
Hello! And welcome! To Nat’s Neovim Newsletter, the newsletter where we all get better at Neovim, so we don’t have to use IntelliJ or VSCode. (Which are fine editors! But I am a weirdo.)
This week I added the ability to find references to functions across my codebase to my Neovim config.
Prerequisites
You’ll need to set up telescope and which-key for the following code snippet to work. You’ll also need at least one language server configured. I recommend using lsp-config and install the language server itself with a package manager.
If you don’t have it already, go ahead and install the Lua language server, so you can use it for writing your configuration.
I recommend using the Lazy plugin manager for Neovim.
I’ve included an example Neovim configuration at the bottom of this post.
Configuring “Goto References”
vim.api.nvim_create_autocmd({"LspAttach"}, {
callback = function()
wk.register({
g = {
name = "Goto"
d = { vim.lsp.buf.definition, "Go to definition" },
r = { require("telescope.builtin").lsp_references,
"Open a telescope window with references" },
},
}, { buffer = 0 })
end
})Now when I hit gr I see something like this.
Complete Example Config
To run that code snippet successfully the rest of your `init.lua` will need to look something like this:
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
local plugins = {
{ 'neovim/nvim-lspconfig' },
{
"folke/which-key.nvim",
event = "VeryLazy",
init = function()
vim.o.timeout = true
vim.o.timeoutlen = 300
end,
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
}
},
{
'nvim-telescope/telescope.nvim',
tag = '0.1.2',
dependencies = { 'nvim-lua/plenary.nvim' }
}
}
require("lazy").setup(plugins)
--- lspconfig
local lspconfig = require 'lspconfig'
local language_servers = { 'lua_ls' }
for _, ls in ipairs(language_servers) do
require('lspconfig')[ls].setup({
settings = {
Lua = {
diagnostics = { globals = { 'vim' } }
}
}
})
end
local wk = require("which-key")
You can also refer to my working example configuration on Github.
Whoops all my LSPs are gone
While I was doing this I discovered that I wasn’t actually configuring my language servers without noticing. To avoid being like me, you can check that your language servers are actually installed with the handy :LspInfo command. You should see something like this:
There are a variety of ways to configure your language servers. Right now I like this:
local language_servers = { 'lua_ls', 'elmls', 'gopls' }
for _, ls in ipairs(language_servers) do
require('lspconfig')[ls].setup({
capabilities = capabilities,
settings = {
Lua = {
diagnostics = { globals = { 'vim' } }
}
}
-- you can add other fields for setting up lsp server in this table
})
end
Next week I’ll probably write about what currently goes into that “capabilities” field in my configuration, and why I started using code folding.



