DEV Community

Cover image for VSCode as a Vim editor
Antoine Lehurt
Antoine Lehurt

Posted on • Originally published at kewah.com on

VSCode as a Vim editor

Photo by @goshua13 on Unsplash

In 2013 I started to use Vim as my primary editor, the journey hasn’t been without frustration, but in general, I really enjoyed using it. It took me sometimes, but I found a setup that worked well for me from auto completion to code navigation. What I love the most is Vim motions, I would not trade that feature for something else.

So, if everything was fine why did you start using VSCode?

I got mainly interested by VSCode for its debugging and refactoring features. I got used to debugging JavaScript or CSS in the browser’s dev tools, but I never found the right spot for debugging Node apps. With VSCode it is possible to debug directly in the editor, to add breakpoints or investigate the stack trace.

But, as usual, the first thing I do when I start to use a new code editor to install the Vim plugin.

VSCode Vim plugin

In a nutshell, VSCodeVim is really good. It is by far the best Vim integration I have tried outside Vim (or NeoVim) itself. It’s fast, includes plugins I love (easymotion, sneak, surround), and supports all motions and most shortcuts I used to use.

To get there I had to tweak the settings to be able to remap commands, but the great thing with this plugin is that we can remap loads of it!

For instance, I use jk to switch between insert and normal mode.

{
  "vim.insertModeKeyBindings": [
    {
      "before": ["j", "k"],
      "after": ["<Esc>"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

You need to define that in User Settings. (Search forPreferences: Open User Settings. in the command palette (⇧⌘P).)

It is pretty straightforward, you define what mapping you want to use inbefore and what output you want to get into after.

I rely a lot on EasyMotion to move around (jump to a different line or a character) but I found the default setting quite annoying: I have a double press the leader key, instead of once in Vim, and then the action (for instance j to go to a line below). But, it is possible to remap it!

{
  "vim.normalModeKeyBindingsNonRecursive": [
    {
      "before": ["<leader>", "j"],
      "after": ["<leader>", "<leader>", "j"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

You can remap not only key bindings but also execute commands. For instance to toggle a bookmark using ma:

{
  "vim.normalModeKeyBindingsNonRecursive": [
    {
      "before": ["m", "a"],
      "after": [],
      "commands": [
        {
          "command": "bookmarks.toggle",
          "args": []
        }
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

I have been able to remap bindings to match my Vim memory muscles. I felt at home when starting to use VSCode.

You can find my VSCodeVim settings on this Gist.

Refactoring

VSCode has made some refactoring tasks easier than what I used to in Vim. One of my favourites is renaming a variable by pressing f2. All occurence will be updated in the project. The same happens when you rename a file or move it to another folder, its path is updated where it is used.

We can also transform arrow function with implicit return using cmd+.:

const add = (a, b) => a + b;
Enter fullscreen mode Exit fullscreen mode

Put the curson on (, then press cmd+. ->add braces to arrow function. It will convert it to:

const add = (a, b) => {
  return a + b;
};
Enter fullscreen mode Exit fullscreen mode

Super convenient when you need to debug a function.
It can also be used for disabling a ESLint rules for the current line.

In general, I find it more comfortable to refactor in VSCode, the multiple cursors works better than on Vim, and I can still use visual block mode when I need it.

Debugging

So far, I have only used the “attach to process” debug mode. When you run node (or nodemon) with the —inspect flag you can attach the process in VSCode to debug the application.

In launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "dev:server inspect",
      "port": 5858,
      "restart": true,
      "protocol": "inspector"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

It’s an excellent way of debugging Node.js apps, so you don’t need to open a Chrome dev tools to add breakpoints and put debugger statement in your code.

Navigation

After some tuning, navigating in VSCode looks familiar to Vim:

  • Search a file using the fuzzy finder à la CtrlP.
  • Use the command palette to run commands when I don’t think it is necessary to memorise a key binding.
  • Jump between windows using ctrl + hjkl. (More about it in “What I miss from Vim” section.)
  • Go to definition using gf. (In Vim I used Ternjs to have this feature, “60% of the time, it works every time”.)
  • Use the code outline to jump between symbols in a file using cmd+shift+o. I’m in love with this feature.
  • Switch between tabs using gt (next tab) or gT (previous tab). ctrl + tab comes handy when I have too many files open, which happen more often to me because of the poor window management support on VSCode.
  • Jump to the next occurrence of the variable under the cursor using *.
  • Jump to the next changeusing <leader>n (next change) or <leader>p (previous change).
  • And of course, my beloved Vim motions.

Language support

The VSCode community is active, so I haven’t encountered a language that wasn’t supported: JavaScript (+JSX), TypeScript, Sass, Elm, Elixir/Phoenix, or Haskell.

Auto completion is right most of the time, except for CSS or Sass files where it struggles to suggest class names defined in a template file. It also has some issues to autocomplete snippets. If I type too fast, I will need to close and reopen the suggestion box to be able to run a snippet.

What I miss from Vim

Obviously, everything is not perfect. The main thing I miss from Vim is the window management, in VSCode the current support is really basic.

In Vim, it is possible to open several files under the same tab, so it is straight forward to create different spaces with related files and terminal open.For instance, you can open a tab containing all files related to a component.

| TAB A | TAB B
|       |-------------------------------------------------------------
Module.js     | Module.test.js     | Terminal that runs
              |                    | Module.test.js
              |--------------------|
              | Module.style.scss  |
              |                    |
Enter fullscreen mode Exit fullscreen mode

In VSCode, tabs are all independent, so even if I can split the screen in two, I can’t switch tabs to change both files at the same time. So, I need to jump back and forth between the files to switch the tabs accordingly. Annoying.

| TAB Module.js | TAB Module.test.js | TAB Terminal
-------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

It creates some frustration when I try to jump quickly between files and terminals since I need to remember where are the related files are and keep things in sync manually.

What’s next?

I will keep using VSCode and haven’t planned to go back to my previous setup iTerm + NeoVim. It has (almost) everything I’m looking for: it is fast, it has good language, and auto completion support, a built-in terminal, and I can still use Vim in it. A nice thing is that most of my colleagues use it as well, so we can share settings in a project or do remote pair programming in VSCode directly, which is fantastic.

Top comments (4)

Collapse
 
ducaale profile image
Mohamed Dahir

comma operator could also be used to debug arrow functions

const add = (a, b) => (console.log('adding together', a, b), a + b)
Collapse
 
c24w profile image
Chris Watson

Never thought of that. I've always done

const add = (a, b) => console.log('adding together', a, b) || a + b
Collapse
 
ducaale profile image
Mohamed Dahir

Ok, that is even better 😀

Thread Thread
 
c24w profile image
Chris Watson • Edited

¯\_(ツ)_/¯ not much in it!