10 More VS Code Vim Tricks to Code Faster ⚡

10 More VS Code Vim Tricks to Code Faster ⚡

Around a year ago, I published the article “10 VS Code Vim Tricks to Boost Your Productivity ⚡”, which I shared various tips for the VSCodeVim extension. Turns out that the article was a hit, so allow me to share a few more VS Code Vim tips that I have up my sleeves 😆.

Prerequisites:

You’ve installed the VSCodeVim extension
Basic understanding of Vim keybindings. This guide is NOT for total beginners!

Table of Contents

(Previous 10 Tips)

Navigation

#1 – Tabs Management
#2 – Splits Management
#3 – Multi-Cursor
#4 – Quick Search

Vim Features

#5 – Emulated Plugins
#6 – Macros

Git

#7 – Peek Diff
#8 – Revert Hunk or Selected Lines
#9 – Jump to Previous/Next Changes
#10 – Open File on Remote

(Full Settings: settings.json | keybindings.json)

Navigation

#1 – Tabs Management

I prefix all my custom keybindings for managing editor tabs with the Shift key so that it’s easy to remember. For tab navigation:

Shift + h – Focus the left tab

Shift + l – Focus the right tab

Shift + q – Close current tab

Notice how intuitive they are, since h and l keys in Vim means left and right, and q means “quit”.

To define the custom keybindings, open settings.json by pressing “Ctrl+Shift+P” and search for “Preferences: Open User Settings (JSON)”. Then, add the following item:

{
“vim.normalModeKeyBindings”: [
{
“before”: [“H”], // Focus previous tab at the left
“commands”: [“workbench.action.previousEditor”]
},
{
“before”: [“L”], // Focus next tab at the right
“commands”: [“workbench.action.nextEditor”]
},
{
“before”: [“Q”], // Close current tab
“after”: [“<C-w>”, “q”]
}
]
}

As for reorganizing the order of tabs:

Shift + LeftArrow – Move tab leftwards

Shift + RightArrow – Move tab rightwards

Setting up this keybinding is a bit tricky. VS Code has default keybindings where “Shift + LeftArrow” will select one character at the cursor’s left side (similar for “Shift + RightArrow”).

Actually we don’t need that since Vim’s Visual Mode can achieve the same thing via vh and vl keybindings. Thus, we need to disable VS Code’s default keybindings for Shift + Left/Right.

Open keybindings.json via “Ctrl + Shift + P” → “Preferences: Open Keyboard Shortcuts (JSON)” and append the following items:

[
{
“key”: “shift+left”,
“command”: “-cursorColumnSelectLeft”,
“when”: “editorColumnSelection && textInputFocus”
},
{
“key”: “shift+left”,
“command”: “-cursorLeftSelect”,
“when”: “textInputFocus && vim.mode != ‘Visual'”
},
{
“key”: “shift+left”,
“command”: “workbench.action.moveEditorLeftInGroup”,
“when”: “vim.mode == ‘Normal'”
},
{
“key”: “shift+right”,
“command”: “-cursorColumnSelectRight”,
“when”: “editorColumnSelection && textInputFocus”
},
{
“key”: “shift+right”,
“command”: “-cursorRightSelect”,
“when”: “textInputFocus && vim.mode != ‘Visual'”
},
{
“key”: “shift+right”,
“command”: “workbench.action.moveEditorRightInGroup”,
“when”: “vim.mode == ‘Normal'”
}
]

(🔼 Table of Contents)

#2 – Splits Management

I prefix all splits-related keybindings with Ctrl key, similar to Tip #1 where I prefix all tabs-related keybindings with Shift key.

To create splits easily, I’ve defined 2 custom keybindings:

| (Shift + ) – Split tab vertically

_ – Split tab horizontally

I picked these two symbols because it looks like the split direction (| is a vertical stroke, _ is a horizontal stroke).

{
“vim.normalModeKeyBindings”: [
{
“before”: [“|”], // Split tab vertically
“after”: [“<C-w>”, “v”]
},
{
“before”: [“_”], // Split tab horizontally
“after”: [“<C-w>”, “s”]
}
]
}

(💡 <C-w> is a Vim keybinding syntax that means Ctrl + w)

The Shift + q keybinding we saw from Tip #1 can also close a split if it only has one tab 👇

To navigate around splits, I don’t like Vim’s <C-w> h/j/k/l keybindings because I have to press Ctrl + w every time. To reduce the number of keystrokes, I use Ctrl + h/j/k/l instead:

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<C-h>”], // Focus split window at left
“commands”: [“workbench.action.focusLeftGroup”]
},
{
“before”: [“<C-j>”], // Focus split window at right
“commands”: [“workbench.action.focusBelowGroup”]
},
{
“before”: [“<C-k>”], // Focus split window at above
“commands”: [“workbench.action.focusAboveGroup”]
},
{
“before”: [“<C-l>”], // Focus split window at below
“commands”: [“workbench.action.focusRightGroup”]
}
]
}

⚠️ For Windows/Linux users, the Ctrl + k keybinding may not work properly. You may see this message at the bottom bar:

(Ctrl + K) was pressed. Waiting for second key of chord…

This is because VS Code has a lot of default keyboard shortcuts that starts with Ctrl + k (e.g. Ctrl+K Ctrl+S to open keyboard shortcuts). As a fallback, you can use Vim’s original keybinding of Ctrl+w k.

(🔼 Table of Contents)

#3 – Multi-Cursor

VS Code’s multi-cursor editing is also supported in VS Code Vim.

Below are the built-in VS Code keybindings to enter multi-cursor mode:

MacOS – Cmd + d

Windows/Linux – Ctrl + d

Unfortunately for Windows/Linux users, pressing Ctrl + d will instead scroll down the file, because it clashes with Vim’s keybinding of <C-d> for scrolling down a file. As a workaround, I remapped Ctrl + d to Alt + d to enter multi-cursor mode. To do that, append these to keybindings.json:

[
{
“key”: “ctrl+d”,
“command”: “-editor.action.addSelectionToNextFindMatch”,
“when”: “editorFocus”
},
{
“key”: “alt+d”,
“command”: “editor.action.addSelectionToNextFindMatch”,
“when”: “editorFocus”
}
]

Alternative to Cmd/Alt + d, VS Code Vim also has a built-in keybinding of gb to enter multi-cursor mode. Here’s a demo in MacOS for both the Cmd + d and gb keybindings:

VS Code Vim treats multi-cursor mode as a variant of Visual Mode, so you need to use Visual Mode keybindings to perform multi-cursor actions, such as:

Shift + i – Move to beginning of selection and enter Insert Mode

Shift + a – Move to end of selection and enter Insert Mode

s or c – Delete word and enter Insert Mode

For example, I need to press Shift + a in order to start typing at the end of the word (unlike in Normal Mode where I only need to type a):

#4 – Quick Search

To quickly search text from files, I’ve created the <leader>f keybinding:

💡 <leader> stands for Leader Key, which is commonly used as a prefix for user-defined shortcuts. By default it’s the backslash key (), but we commonly map it to Space key (see vim.leader option below)

{
“vim.leader”: “<space>”,
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “f”], // Search text
“commands”: [“workbench.action.findInFiles”]
}
]
}

I also created a keybinding of <leader>s to search all symbols in a workspace. This will save you a lot of time from locating the definition of a symbol.

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “s”], // Search symbol
“commands”: [“workbench.action.showAllSymbols”]
}
]
}

For example, I want to directly jump to a React component called SaveButton. To do that, I launch the symbol search via <leader>s and enter the component name:

💡 Tip: If you place your cursor under a word (e.g. SaveButton) and press <leader>s, VS Code will automatically fill that word in the search bar 👇

(🔼 Table of Contents)

Vim Features

#5 – Emulated Plugins

VS Code Vim emulates quite a number of Vim plugins. While I’m not going to walkthrough every plugin here (see docs for the full list), I want to highlight a plugin called vim-surround.

This plugin will save you tons of time when working with surrounding characters like paranthesis, brackets, quotes, and XML tags. Here’s a quick cheatsheet:

Surround Command
Description

y s <motion> <desired>
Add desired surround around text defined by 

d s <existing>
Delete existing surround

c s <existing> <desired>
Change existing surround to desired

S <desired>
Surround when in visual modes (surrounds full selection)

For a full guide, please refer to vim-surround’s GitHub README.

Examples:

ysw) – Add () surround around a word

ds] – Delete the [] that surrounds the cursor

cs)] – Changes the () surrounding to []

S} – Surrounds the selected text with {} block

(🔼 Table of Contents)

#6 – Macros

Macro is a powerful feature in Vim that lets you record a series of commands and replay them. It’s useful to perform similar code changes for many times.

For example, let’s say I have a JavaScript object and I want to turn each value from a string to an array of strings. It’d be very tedious to manually edit line-by-line:

const data = {
item1: one, // -> item1: [“one”]
item2: two, // -> item2: [“two”]

}

Here’s the anatomy of macros:

Record a macro: q<register><commands>q.

Begin a macro recording with q followed by <register> (i.e. a single letter, which is like the name of a save slot). For example, qa means I record a macro to a slot named a.

<commands> is the series of Vim keybindings you wish to perform.
End the recording by pressing q.

To play a macro: @<register>.

<register> is the single letter that you just recorded your macro to. For example, @a will play the commands that I’ve previously recorded via qa<commands>q.
You can play the macro multiple times. For example, 4@a plays the macro 4 times.

Back to our example. We basically want to repeat the action of adding a [] bracket around the string value. Let’s record our macro:

Place our cursor at start of the object key name.

qa – Begin recording the macro to slot a.

f” – Move the cursor to the first double quote.

yst,] – A vim-surround keybinding that we saw from Tip #5. It means adding a [] bracket for the text from the current cursor’s position (first double quote) till the first comma (i.e. t,).

j0w – Places the cursor in an appropriate location before the macro ends. We move one line down with j, then move to beginning of first word with 0w.

💡 The cursor’s end position matters because it affects the repeatability of the macro.

q – Stops the macro recording.

To confirm the macro works, let’s replay it once via @a. Note how the cursor perfectly lands at the start of next line (item3), so that we can replay the macro consecutively via 4@a (i.e. play 4 times):

(🔼 Table of Contents)

Git

All my custom Git keybindings are prefixed with <leader>g, where g stands for git. I highly recommend grouping related keybindings with the same prefix so that it’s easier to remember 👍.

#7 – Peek Diff

If your cursor is located inside a Git hunk, I can press <leader>gp to peek the diff changes (gp = git peek).

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “p”], // Peek Git diff for the changed line
“commands”: [“editor.action.dirtydiff.next”]
}
]
}

(🔼 Table of Contents)

#8 – Revert Hunk or Selected Lines

To revert a Git hunk (i.e. discard unstaged changes) in Normal Mode:

Place my cursor inside the Git hunk
Press <leader>gr (gr = git revert)

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “r”], // Revert hunk
“commands”: [“git.revertSelectedRanges”]
}
]
}

To discard multiple hunks at the same time, I’ve also defined the same keybinding for Visual Mode:

{
“vim.visualModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “r”], // Revert hunk
“commands”: [“git.revertSelectedRanges”]
}
]
}

Then, I can first select multiple hunks in Visual Mode, then use <leader>gr to revert them:

(🔼 Table of Contents)

#9 – Jump to Previous/Next Changes

Sometimes I have many Git changes across a long file. To quickly jump between changes:

<leader>gj – Jump to next Git change (j = down)

<leader>gk – Jump to previous Git change (k = up)

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “j”], // Jump to next Git change
“commands”: [“workbench.action.editor.nextChange”]
},
{
“before”: [“<leader>”, “g”, “k”], // Jump to previous Git change
“commands”: [“workbench.action.editor.previousChange”]
}
]
}

(🔼 Table of Contents)

#10 – Open File on Remote

If your Git repo has a remote upstream (e.g. GitHub, GitLab), you can easily get a sharable URL to the file you’re currently opening.

Prerequisite: Install GitLens extension

Add these keybindings to settings.json

{
“vim.normalModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “g”], // Open file in GitHub
“commands”: [“gitlens.openFileOnRemote”]
}
],
“vim.visualModeKeyBindings”: [
{
“before”: [“<leader>”, “g”, “g”], // Open file in GitHub
“commands”: [“gitlens.openFileOnRemote”]
}
]
}

Move your cursor on a line you wish to open on remote, or enter Visual Mode to select multiple lines
Press <leader>gg (mnemonic: last g stands for GitHub)

To jump to a specific line on remote, use the keybinding in Normal Mode 👇

To select multiple lines on remote, use Visual Mode 👇

(🔼 Table of Contents)

For the full settings code, they can be found below 👇

settings.json
keybindings.json

(I used .jsonc instead of .json in the Gists. Otherwise, the syntax highlighting will add an ugly red background to all comments since theoretically comments are not allowed in JSON 😢)

Thanks for reading. Don’t forget to like and share this post if you found it useful, cheers! 🙌

My GitHub
Personal website

Please follow and like us:
Pin Share