Migrating to Neovim from VScode

Sun May 12 2024

This is a step I have trying for years, ending up depressed at VScode. I have been putting the pieces together, and now, I think I am ready to fly around files and lines of code, as a Neovim Ninja.

Of course I am using vim extension in VScode, but it is not enough for me. There are a lot of functionalities I have no access to, or have limitations.

But this will be no easy task, these are the requirements for a good code editor in my opinion. If Neovim can do everything I do with VScode, I know things will only get better in the future, while I find more amazing flexibility and functionality.

There are a lot things in VScode that I cannot live without. I will find a similar/better approach in Neovim one by one. These are my top priorities:

  1. Autocomplete
  2. Go to definition and references
  3. Search for matching words
  4. Search a file by name
  5. Terminal
  6. File explorer
  7. Git differences and conflict resolving
  8. Toggle latest files
  9. Rename variables globally
  10. Format file on save
  11. Update imports when renaming a file
  12. See inferred type and type error

Having all these functionalities, I do not think I need to open VScode anymore, while enjoying the Neovim benefits:

My plugins are install in /home/ro/.config/nvim/lua/plugins.lua. You can find them here

Autocomplete

This includes auto-importing components, accessing inner properties of an object, knowing what is variables are inside a destructured object, auto-closing tags, and recommending already used words.

For this I used coc.vim plugin from here

Go to definition and references

This is the most important feature for me. I used to surf the project, allowing me to better understand what is happening. This is specially useful when the project is giant (millions lines of code).

Again, coc.vim does the trick. I use a coc.lua file with the keybindings, check it here.

With these keybindings, I can use \ gd and \ gr to go to definition and reference respectively.

Search for matching words

Many times in a large repository, you need to find an expression or words near the place you will code. This helps to quickly find the place where you need to be. For this, you can use command/control + shift + f in VScode, I definitively used it all the time instead of searching in the file explorer.

Thankfully, there is an amazing fzf fuzzy finder plugin to help us achieve this same thing, faster and with extra functionalities. It feels more powerful that the one in VScode, using the whole screen.

I used this keybinding \fc:

map("n", "<leader>fc", ":Rg<cr>") --search word everywhere

Search a file by name

Many times we know the path of the file we want to open and we want to access it as quickly as possible. Of course, we could open a new terminal and go the file manually, but we should have a keybinding to make it smoother. Again, fzf library comes to the rescue.

In our remaps.lua file

map("n", "mm", ":Files<cr>") --search file by name in the whole system

And in our plugins.lua file

function search_word_all()
    local input_string = vim.fn.input("Search For > ")
        if (input_string == '') then
          return
        end
        builtin.grep_string({
          search = input_string,
    })
end
vim.keymap.set('n', '<leader>fa', search_word_all, {})

Format file on save

I installed Prettier using :CocInstall coc-prettier in vim’s EXECUTE mode. Then I added a keybinding to format and save the file when I use zz in COMMAND mode.

map("n", "zz", ":Prettier<cr> <ESC>:update<cr>")

You can use formatters different than Prettier, depending on your programming language target. Or assign a different keybinding to formatting file only.

map("n", "ff", ":Prettier<cr>")

Git differences and conflict resolving

For this, I am planning to use this program named lazygit. You need to install it depending your OS, it is a breeze. Then I can easily open it from Neovim using terminal explained in this step. . I can open a floating terminal with lazygit using this remap \g:

-- TERMINAL LAZYGIT
local Terminal  = require('toggleterm.terminal').Terminal
local lazygit = Terminal:new({
  cmd = "lazygit",
  dir = "git_dir",
  direction = "float",
  float_opts = {
    border = "double",
  },
  -- function to run on opening the terminal
  on_open = function(term)
    vim.cmd("startinsert!")
    vim.api.nvim_buf_set_keymap(term.bufnr, "n", "q", "<cmd>close<CR>", {noremap = true, silent = true})
  end,
  -- function to run on closing the terminal
  on_close = function(term)
    vim.cmd("startinsert!")
  end,
})

function _lazygit_toggle()
  lazygit:toggle()
end

vim.api.nvim_set_keymap("n", "<leader>g", "<cmd>lua _lazygit_toggle()<CR>", {noremap = true, silent = true})

File explorer

I started using NerdTree, but then I read that for Neovim, NvimTree is more convenient since it is written in Lua. I gave it a try and I totally felt in love. It is faster than NerdTree and the keybindings are awesome.

You can find it here . This how it looks like and the default keybindings:

NvimTree photoNvimTree photo

Terminal

Being able to quickly toggle terminals while coding is a fundamental functionality in my opinion. I want to be able to create multiple terminals for different tasks, for example, running dev servers, executing tests and writing git commands. I do not want them to be open all the time, but to have rapid access to them when needed.

I found this amazing plugin to achieve just that. I use tt to toggle terminal, and {number}tt to create a new one. I do not like that I have to use Ctrl\ Ctrl n to exit insert mode in the terminal and be able to toggle it close, but I it is possible to remap it with:

map("t", "jk", "<C-\\><C-n>") -- exit terminal mode

I used this for a while, but then decided that it was better to learn/use tmux. I was a very easy transition and now I can control Neovim and more window/pane from the terminal itself. So, instead of letting Neovim control terminals, I let my terminal control Neovim + new windows/panes.

Terminal plugin

Toggle latest files

This is probably my favorite advantage of using Neovim, and the one that made me try the full migration. In VScode I use Ctrl Tab to show the latest files I worked on. It does the job but sometimes I found it buggy, not adding files that I visited recently. This is very important for me when working in a large repository, I do not want to search the file again in the file explorer.

So I use this plugin in Neovim, and completely love it. It opens telescope with all the files you worked on recently. So I can access them as fast as thunder.

I also learned recently that you can toggle the last file you worked on with Ctrl ^, and I remapped it to Ctrl s since I use it all the time now.

Additionally, I am trying to use Ctrl o and Ctrl i more, so I can go to recent lines of code across different files I am working on. But this is not very good when jumping around a lot in the same file, because it navigates to your previous locations.

This navigation between recent places makes the Neovim experience to be captivating in my opinion.

Currently I am trying the plugin Harpoon of the famous Primeagen youtuber, it promise a lot to be the thing I am looking for; an easy way to toggle the latest files I am working when doing a specific task at my job.

Rename variables globally

This is a very convenient functionality when you want to refactor your code and give more context to your variables names. In VScode I use it all the time, specially when I know the variable is used in many places along the project and I do not want to change manually each one. For Neovim, I found amazing plugin .

You need to install it and add this key mapping to you configuration:

vim.keymap.set("n", "<leader>rn", function()
  return ":IncRename " .. vim.fn.expand("<cword>")
end, { expr = true })

Then, you can use \rn over the selected variable. It works as a charm.

See inferred type and type error

After installing coc.vim I could see type errors when making one. To see the inferred type, you just need to use Shift k over the target variable and that is it.

In VScode, I also have a plugin that shows me an ‘easy’ type error explanation. Can I have something similar in Neovim?

Update imports when renaming a file

I am having troubles with this one. I do not do this often, but I do not want to open VScode when I need to rename a file and update the imported places. I tried many approaches to solve this but nothing was working, what made try some other people configuration. Then, I used this amazing Tayuka san’s dotfiles . There, all my problems were solved, and I had so many awesome new features. But, I felt it was too fancy for me, too many effects and unwanted functionalities. Besides that, Tayuka san opened a new door for me “I could try many people configuration and find a good match for me!!!”

Conclusions after 2 weeks trying to make my Nvim configuration better than VScode

The process was more fun and more tedious than I expected. But I feel so much productive, fast and ergonomic than before. I have so much power in my hands now!!

I am learning a lot about lua and Neovim. Also, I found so many new functionalities that I did not know were so useful. You can check the plugins I have installed and you will see that now I expect more from my editor than I did when starting this post.

After realising that there was a lazy plugging installer and that I could use another’s people configuration so easily, I researched online and found josean-dev’s wonderful configuration. This solved basically all my listed problems, then I found that I needed a few more things, as inline git blame, spell checker for English and Spanish,

These post let me understand that a nvim configuration is something dynamic, and that rather than having one configuration, I will be learning and tweaking it constantly.

This is my current configuration, but as I said before, it will evolve with time definitively.

My configuration

I plan to write a new post after a month working with Neovim as my day to day text editor. I am much in a hype right now!!