DEV Community

Oinak
Oinak

Posted on

Neovim config from scratch (Part II)

This is a continuation from Neovim config from scratch (Part I).

There I covered:

  • Nuke from orbit (starting from a clean slate)
  • Create the config folder
  • Plugin manager
  • Fuzzy finder
  • Colorscheme
  • Treesitter
  • Additional plugins
  • Set options
  • Mappings

I you came here loking for any of those, please visit the link.

Language Support

I used to base my language support on CTags. But due to neovim's native support of LSP I am trying that too.

CTags

Requirements:
You need to have a CTags implementation like universal-ctags installed on your system (on every system where you use vim).

  • For Linux distros it is commonly available as a package, see: debian, ubuntu
  • For OSX it is available via homebrew

Configs

Tell nvim where to find your tag file, the default is tags

-- (Exuberant/Universal) Ctags
vim.opt.tags = '.tags'
Enter fullscreen mode Exit fullscreen mode

Key mapping to refresh your tags

function RTags()
  vim.cmd [[!ctags -f .tags --languages=ruby --exclude=.git -R .]]
end

vim.keymap.set("n", "rT", RTags)
Enter fullscreen mode Exit fullscreen mode

You can automate this via githooks, if you work usually on the same repo(s).

On top of this you can use vim's default mappings for tags operations:

*g] go to definition *

Example, you type g] while having your cursor on the word initialize on line 41, and you see this list. <number>+<enter> takes you to each result.

nvim window showing several results for solution tag

C-] (control+']') will jump to the first result without showing the list

You can run :help tags to learn about all of them.

However, if you are using telescope, you can add this to your .config/nvim/lua/after/plugin/telescope.lua (or equivalent) file:

local builtin = require('telescope.builtin')
-- ...
vim.keymap.set('n', 'gt', builtin.tags,            { desc = '[G]o to C[T]ags (telescope)', noremap = true })
Enter fullscreen mode Exit fullscreen mode

And then if you press gt and then method or class name like initialize here, you would see something like:

telescope window searching for initialize tag.

LSP

Go to LSP-Zero page, Istalling section and copy the packer block.

Paste it under the last use block, into your .config/nvim/lua/core/plugins.lua file that we created in Part I.

Save :w, source :so % and run :PackerSync.

Then you can create an .config/nvim/after/plugin/lsp.lua to add your custom config for LSP.

Mine is

vim.opt.signcolumn = 'yes' -- Reserve space for diagnostic icons

local lsp = require('lsp-zero')

lsp.preset('recommended')

lsp.ensure_installed({
  'html',
  'cssls',
  'tsserver',
  'solargraph',
  'eslint',
  'sumneko_lua',
})

-- keymaps to add only on buffers with LSP support (overriding grep/tags based defaults)
lsp.on_attach(function(client, bufnr)
  vim.keymap.set("n", "gd", function() vim.lsp.buf.definition() end,     { desc = '[G]o to [d]efinition',buffer = bufnr, remap = false }))
  vim.keymap.set("n", "gD", function() vim.lsp.buf.declaration() end,    { desc = '[G]o to [D]eclaration',buffer = bufnr, remap = false }))
  vim.keymap.set("n", "gr", function() vim.lsp.buf.references() end,     { desc = '[G]o to [R]eferences (with LSP)', buffer = bufnr, remap = false })
  vim.keymap.set("n", "gi", function() vim.lsp.buf.implementation() end, { desc = '[G]o to [I]mplementation (with LSP)', buffer = bufnr, remap = false })
  vim.keymap.set("n", "K",  function() vim.lsp.buf.hover() end,          { desc = '[K] Hover info', buffer = bufnr, remap = false })
  vim.keymap.set("n", "R",  function() vim.lsp.buf.rename() end,         { desc = '[R]ename symbol (with LSP)', buffer = bufnr, remap = false })
end)

  -- Set up lspconfig.
  local capabilities = require('cmp_nvim_lsp').default_capabilities()
  -- Replace <YOUR_LSP_SERVER> with each lsp server you've enabled.
  require('lspconfig')['solargraph'].setup  { capabilities = capabilities }
  require('lspconfig')['html'].setup        { capabilities = capabilities }
  require('lspconfig')['cssls'].setup       { capabilities = capabilities }
  require('lspconfig')['tsserver'].setup    { capabilities = capabilities }
  require('lspconfig')['eslint'].setup      { capabilities = capabilities }
  require('lspconfig')['sumneko_lua'].setup { capabilities = capabilities }

lsp.setup()
Enter fullscreen mode Exit fullscreen mode

Basically it selects which language servers are installed by default, sets custom keybinding only when LSP is acive (via the on_attach hook) and then sets up the servers.

LSP will auto-install your selected servers with mason, and propose you additional servers when you open a file of a new type.

You can look at what servers are installed with :Mason.

LSP diagnostics

I have finally chose to use trouble to see and jump to LSP diagnostic output in a non obstrusive way (I tried floating windows and inline messages but they were not for me)

Image description

Just the default installation as suggested by the Readme page works for me.

Ruby/Rails/Tests language support

I mainly develop in ruby so here are some plugins i have find very useful to add:

  • vim-ruby language support
  • vim-rails framework support with enhanced file navigation gf and custom :Emodel, :Eview etc commands, :Rails to run rails/rake commands without leavinf your editor.
  • vim-test run your test with a simple mapping. Works with rSpec and Minitest (and dozens other languages)
-- make test commands execute using dispatch.vim
vim.g['test#strategy'] = "neovim"

vim.keymap.set("n", "<leader>tn", vim.cmd.TestNearest, { desc = '[T]est [N]earest' })
vim.keymap.set("n", "<leader>tf", vim.cmd.TestFile, { desc = '[T]est [F]ile' })
vim.keymap.set("n", "<leader>ts", vim.cmd.TestSuite, { desc = '[T]est [S]uite' })
vim.keymap.set("n", "<leader>tl", vim.cmd.TestLast, { desc = '[T]est [L]ast' })
vim.keymap.set("n", "<leader>tv", vim.cmd.TestVisit, { desc = '[T]est [V]isit' })
Enter fullscreen mode Exit fullscreen mode

vim-test plugin usage demo calling tests from the editor

  • splitjoin to alternate between abbreviated and expansive syntaxes for hashes, arrays, method calls...
  • vim-commentary comment code comfortably with motions and visual selections alike.
  • vim-surround act on surrounding characters (think quotes, braces, parentheses...)

  • vim-textobj-ruby use r as a ruby motion (like w for word) meaning "ruby block"

Afterword

That's about it for my current configuration, I hope it was useful or at least interesting for you.

Please let me know if there is anything else you are struggling with. I might have com upon it after writing this piece.

Top comments (0)