😎 VSCode + Neovim Setup: keyboard-centric, powerful, reliable, clean, and aesthetic development environment. Tips and tricks

Nikita Maslov
12 min readJul 5, 2024

--

Here I will share my current development environment setup and the philosophy behind it. I’ll try to keep this article updated with my latest approaches and insights.

Philosophy Definition

Productivity, power, reliability, cleanliness, aesthetics — it’s all about that.

Productivity

When I say “productivity”, I mean being able to edit your code and navigate through your editor blazingly fast. This very approach allows you to complete your tasks in an hour and spend the other seven hours debating the perfect programming language (DreamBerd) with your team lead at the bar. However, if your job involves spending seven hours on research and one hour writing 10 lines of code, this approach might not be your vibe. Anyways, I find it lit to advance efficiently in the coding part of a project and believe it’s natural to optimize your workflow, especially, in the case when you spend the lion’s share of time on implementation.

To edit code and move through an editor blazingly fast, I rely on this approach: everything that can be done using a keyboard should be done using a keyboard. After some training, it turns out that your fingers’ movements on a keyboard are faster than your attempts to wiggle a mouse.

Power

When I say “power”, I mean that your editor is packed with features that assist you throughout the development process. This includes code suggestions, autocompletion, quick fixes, go-to definition, syntax highlighting, community plugins, AI support, and more. All these features are designed to make your development process faster and more enjoyable.

It’s good to understand that fundamental features like code suggestions, autocompletion, quick fixes, and go-to definition are usually implemented by the specific language server. The code editor just communicates with this language server through the Language Server Protocol (LSP) and acts as an LSP client.

Reliability

When I say “reliability”, I mean that there is a large community behind your editor: if something goes wrong, you can expect issues to be fixed quickly; if new tools and approaches emerge, you can expect them to be implemented swiftly by the editor.

Cleanliness

When I say “cleanliness”, I mean that I’m not a big fan of having dozens of icons, buttons, and labels cluttering my workspace, especially if I don’t use or care about them. I prefer seeing only the essentials during the development process, such as the code itself and the current file with its path. If I need to see anything else occasionally, I navigate using shortcuts.

Aesthetics

When I say “aesthetics”, I mean that I’ve dedicated a lot of time to designing user interfaces and typography, so I notice every misalignment and any place that needs an extra 1px margin. Because of this, I find it more enjoyable to use an editor with a well-crafted UI.

Philosophy Implementation

Now that we have defined the philosophy behind the development environment, let’s move on to its implementation. My goal here is not to provide a complete setup, but rather to show you the framework, approaches, and opportunities that you can use as a foundation for building and evolving your personalized development environment.

So our implementation will be based on these four things: ten-fingers touch typing, VSCode, Neovim, and keyboard shortcuts.

Ten-fingers touch typing

The foundation of your coding productivity is your ability to type with all 10 fingers. If your typing speed is slow, it will significantly hinder your ability to code and navigate quickly. To avoid this bottleneck, it’s crucial to become proficient at touch typing. So if you’re not already in the league of touch typists, I highly recommend you join.

The early days of your switch may be challenging as your fingers get used to the new positions and movements. Initially, you will likely type even slower than with your previous approach, and it may drive you nuts. However, if you push through this period, you will undoubtedly see a gradual increase in typing speed, leading to a significant boost in the long term. I recommend finding an online training program that teaches ten-finger typing through specific exercises. Here is the resource I used when I was learning to type fast: https://www.typingstudy.com.

VSCode

According to the Stack Overflow Developer Survey 2023, Visual Studio Code (VSCode) turned out to be the most popular and preferred editor. This indicates that there is a large community supporting it, which usually means that the tool has everything we might need. Many people are working on polishing it, adding features, and creating plugins that enhance its capabilities. Also, VSCode is free, has a slick UI, and is quite lightweight, so it won’t eat up your RAM as heavily as Chrome or JetBrains IDEs do.

Step 1. Install Visual Studio Code

First, head over to the VSCode official website and download the editor for your operating system.

Step 2. Activate Zen Mode, uncheck Centered Layout and Hide Line Numbers options

After the installation, your VSCode will look something like that:

Default VSCode UI
Default VSCode UI

By default, it’s already pretty clean. But I prefer to make it spotless. To do this, first activate Zen Mode by pressing Cmd+K Z (or by going to ViewAppearance and checking Zen Mode). Now you get that:

VSCode in the default Zen Mode
VSCode in the default Zen Mode

I’m not a centered layout boy, and the lack of line numbers brings too much emptiness and sorrow here. Off we go fixing this. Hit cmd+shift+p to open the command palette and start typing open user settings (json). When you see the corresponding item, hit enter to navigate to it.

You can use ctrl+n and ctrl+p to move through the list of the command palette.

Now we have to set 2 options in the opened settings.json file:

"zenMode.centerLayout": false, 
"zenMode.hideLineNumbers": false

As a result, we have that:

VSCode in the Zen Mode with unchecked “Centered Layout” and “Hide Line Numbers” options
VSCode in the Zen Mode with unchecked “Centered Layout” and “Hide Line Numbers” options

Now it looks pretty neat. You can also toggle the primary side bar on the left with cmd + h:

VSCode in the Zen Mode with unchecked “Centered Layout” and “Hide Line Numbers” options, and the primary side bar visible
VSCode in the Zen Mode with unchecked “Centered Layout” and “Hide Line Numbers” options, and the primary side bar visible

To focus between the Explorer and the Editor, hit cmd+shift+e multiple times.

I’m ok with having the opened files panel at the top all the time, and btw:

You can move through the opened files by hitting these two shortcuts: cmd+shift+] and cmd+shift+[.

If you see any other icons or panels that you find useless to display all the time, try to hide them as well.

Step 3. Find a dark theme of your preference

The main condition for a perfect color theme is that it should be dark, because Black Lives Matter and because a dark palette will save you from light bursts at night that can cause your eyes to become wide and almost closed.

The default VSCode dark theme is almost perfect. The only thing I don’t fancy is this accent color:

I don’t know why, but it reminds me of a morgue or at least a hospital, and it seems to be hinting, “to hell with this job”. Hence, I decided to switch over to the Github Dark Default, which looks like that:

Github Dark Default color theme
Github Dark Default color theme

This theme is even darker and looks like under the bed, and that’s how it should be.

Step 4. Set the JetBrains Mono font for the editor

As a former JetBrains user, I have a platonic relationship with the JetBrains Mono font, which is why I decided to bring it over to VSCode as well. To use this font in your editor, download it from the official website, install it, and set it in your settings.json like that:

"editor.fontFamily": "JetBrains Mono"

I also recommend enabling font ligatures. This will make some symbol combinations look more attractive, like this arrow in the Rust codebase:

Font ligatures demo
Font ligatures demo

To enable ligatures in VSCode, head over to settings.json and add this line:

"editor.fontLigatures": true

Step 5. Install and configure the Starship prompt

The Starship allows you to make your terminal prompt look more informative and appealing, for instance, like mine:

My Starship prompt demo
My Starship prompt demo

Also, the Starship is backed by Rust.

First, go through the installation steps.

By default, the Starship prompt displays a lot of information. However, I found that having only the current git branch and git status is enough for me, so I customized the Starship prompt accordingly.

To modify the prompt, create the following file: ~/.config/starship.toml. If you want to have the Starship prompt set up like mine, define these options:

format = """
$directory\
$git_branch\
$git_status\
$line_break\
$shell\
$character
"""

[directory]
truncation_length = 10
truncate_to_repo = false

Neovim

Neovim is what makes you a Gigachad. It’s a tool that turns you into a Real Hacker from the movies. With Neovim, your development process becomes transcendent, and your editing speed is now unparalleled.

Step 1. Learn core vim keybindings

What most people love about Neovim are its core vim keybindings. With these commands, you can navigate through a codebase, edit, move, rearrange, and highlight code parts using only a keyboard, without needing to touch a mouse. If you’re new to Neovim, I highly recommend finding a tutorial, game, or cheat sheet to teach you these fundamental key combinations. There are many online resources that can guide you, so find one you like and start training. As with touch typing, you may not be fast at the beginning and may forget some keymaps, but over time, you’ll get used to these combinations, and they will become an extension of your hands.

Step 2. Install VSCode Neovim extension

Not vscodevim! But VSCode Neovim extension, install it from the VSCode marketplace, and complete the “Getting Started/Installation” part! The key selling point of this extension is that it uses a fully embedded Neovim instance, not a vim emulation. This means it supports custom init.lua and many plugins. At the same time, the extension preserves VSCode’s native functionality for insert mode and editor commands, making the best use of both worlds. I highly recommend walking through the VSCode Neovim extension docs to familiarize yourself with all its features.

Step 3. Understand why I don’t advocate using ordinary terminal Neovim as your main editor

I made many attempts to create a custom terminal Neovim setup from scratch, but each time I encountered several unpleasant moments: I was either frustrated by the amount of time spent configuring basic features that the editor should rather have out of the box, faced issues with certain plugins or their interoperability that led to non-working functionality or noticeable lags, or found parts of the UI that I didn’t like and couldn’t modify.

All the unpleasant aspects of my attempts to use terminal Neovim as an editor led me to realize that I would rather prefer to use Neovim only as a back end. It’s better for me if the client part is a full-fledged editor that has at least the basic features out of the box, a slick UI, is easy to customize to my own needs without breaking things, and has a large plugin ecosystem where I can get plugin features working just by clicking the ‘install’ button. For now, I find VSCode well suited for this role as the client for Neovim, which is why we’ll proceed with it.

Step 4. Configure Neovim for VSCode

In this step, we’ll create a basic Neovim configuration, where we’ll define some custom basic keymaps along with some bindings that will call VSCode commands from Neovim using the vscode-neovim extension API.

First, head over to ~/.config/nvim (or ~/AppData/Local/nvim, if you’re on Windows) and create the following file structure:

Neovim basic config file structure
Neovim basic config file structure

In the init.lua paste the following code:

if vim.g.vscode then
-- VSCode Neovim
require "user.vscode_keymaps"
else
-- Ordinary Neovim
end

It’s good to keep the VSCode-specific config separate from the ordinary one to have fine-grained control over each environment and avoid messing things up.

Now, let’s move to the vscode_keymaps.lua file and define some basic keymaps. Here are the ones I have in my config:

local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }

-- remap leader key
keymap("n", "<Space>", "", opts)
vim.g.mapleader = " "
vim.g.maplocalleader = " "

-- yank to system clipboard
keymap({"n", "v"}, "<leader>y", '"+y', opts)

-- paste from system clipboard
keymap({"n", "v"}, "<leader>p", '"+p', opts)

-- better indent handling
keymap("v", "<", "<gv", opts)
keymap("v", ">", ">gv", opts)

-- move text up and down
keymap("v", "J", ":m .+1<CR>==", opts)
keymap("v", "K", ":m .-2<CR>==", opts)
keymap("x", "J", ":move '>+1<CR>gv-gv", opts)
keymap("x", "K", ":move '<-2<CR>gv-gv", opts)

-- paste preserves primal yanked piece
keymap("v", "p", '"_dP', opts)

-- removes highlighting after escaping vim search
keymap("n", "<Esc>", "<Esc>:noh<CR>", opts)

Next, in the same file, let’s add a section with VSCode-specific keymaps that will trigger VSCode actions like toggling the built-in terminal, showing hover, displaying the quick fix list, toggling a breakpoint, etc. Here are the keybindings I currently have:

-- call vscode commands from neovim
keymap({"n", "v"}, "<leader>t", "<cmd>lua require('vscode').action('workbench.action.terminal.toggleTerminal')<CR>")
keymap({"n", "v"}, "<leader>b", "<cmd>lua require('vscode').action('editor.debug.action.toggleBreakpoint')<CR>")
keymap({"n", "v"}, "<leader>d", "<cmd>lua require('vscode').action('editor.action.showHover')<CR>")
keymap({"n", "v"}, "<leader>a", "<cmd>lua require('vscode').action('editor.action.quickFix')<CR>")
keymap({"n", "v"}, "<leader>sp", "<cmd>lua require('vscode').action('workbench.actions.view.problems')<CR>")
keymap({"n", "v"}, "<leader>cn", "<cmd>lua require('vscode').action('notifications.clearAll')<CR>")
keymap({"n", "v"}, "<leader>ff", "<cmd>lua require('vscode').action('workbench.action.quickOpen')<CR>")
keymap({"n", "v"}, "<leader>cp", "<cmd>lua require('vscode').action('workbench.action.showCommands')<CR>")
keymap({"n", "v"}, "<leader>pr", "<cmd>lua require('vscode').action('code-runner.run')<CR>")
keymap({"n", "v"}, "<leader>fd", "<cmd>lua require('vscode').action('editor.action.formatDocument')<CR>")

An argument we pass to the action function is the VSCode’s Command ID. To retrieve the ID of a command, navigate to Keyboard Shortcuts by pressing cmd+k+s, search for the command by name, then right-click on the found command and choose “Copy Command ID”:

Retrieving the VSCode’s Command ID
Retrieving the VSCode’s Command ID

With everything defined, once you restart VSCode, your custom keymaps should begin to work.

Step 5. Explore code navigation keybindings

In the corresponding section of the VSCode Neovim extension docs, you can find a list with all predefined keybindings for code navigation. Here, I will highlight the ones that I find the most significant and frequently used:

  • gd — go to the definition;
  • ctrl + o — get back from the definition;
  • space + d — show the hover with details on the item where the cursor currently is (from our custom vscode_keymaps.lua);
  • shift + k — if the hover isn’t shown, it shows it. If the hover is already shown, it focuses on it, and then you can use vim motions like j, k, gg, G to scroll through it;
  • space + a — show the quick fix list (from our custom vscode_keymaps.lua). You can also use ctrl + n and ctrl + p to move through the list and hit enter to choose the action to perform.

Step 6. Investigate explorer navigation and file manipulation keybindings

Once you focused on the explorer by hitting cmd + shift + e, you can walk through it, expand and collapse folders, and select, create, rename, delete, copy, and move files and folders using specific keybindings as well.

In the explorer navigation section of the VSCode Neovim extension docs, you can find all predefined keymaps for moving through the VSCode explorer. And in the file manipulation section, you can find all bindings for performing actions on files and folders within the explorer. Here, I will highlight the most useful ones:

  • j and k — focus down and up between files and folders;
  • h and l — collapse folders and select folders and files;
  • enter — select folders and files;
  • gg — focus on the first item of the explorer;
  • G — focus on the last item of the explorer;
  • a — create a new file;
  • A — create a new folder;
  • r — rename a file/folder;
  • d — delete a file/folder;
  • y — copy a file/folder;
  • x — cut a file/folder;
  • p — paste a file/folder.

You can also use a to create a folder, just terminate your input with /. Additionally, you can create nested structures by hitting a and entering input like that: new-folder/new-nested-folder/new-file.hs.

Keyboard shortcuts

Let’s keep it as one of the most significant takes.

Step 1 and the only 1. Make your world around your keyboard

5. If you need to navigate to a certain place in your workspace or perform some actions, don’t be quick to grab a mouse. Spend some time googling ways to achieve the desired result using keyboard combinations. As I mentioned previously, once you get used to the keybindings, you’ll accomplish tasks significantly faster than with a mouse.

And the final tip for today:

When defining your custom keymaps, don’t use random symbols. Instead, incorporate meaningful semantics to make it easier for you to remember the shortcuts. For instance, if you want to assign a keybinding to the “go to definition” action, don’t make it pm; make it gd, where g stands for “go” and d stands for “definition”.

If you want to support my work in creating educational materials in the field of software engineering, I would highly appreciate your donation: https://bit.ly/donate-nikmas.

If you want to see more of my content on software engineering topics and keep up with the latest updates, subscribe to my Telegram channel: https://t.me/nikmas_group.

And here is my Telegram channel for programming memes: https://t.me/nikmas_group_humor.

--

--