August 2020 by Kristian Lumme

Efficient Editing in Visual Studio Code

Moving through code efficiently, without getting slowed down by your editor, is a good skill for any programmer to have. While your productivity may not be limited by your typing speed, being able to translate the thoughts in your head into code on the screen quickly will reduce mental friction and make for a more enjoyable experience.

In this article, we’ll take a look at editing, selecting and navigating through your code in the Visual Studio Code editor.

Be sure to check out part 2 — where we look at support for projects, tasks and tooling — as well.

This is not quite an introductory article. While I don’t think there’s much in the way of prerequisite knowledge needed in order to get something out of this article, my aim is not to go over the basics of a code editor or to list every keyboard shortcut. Instead, I’ll try to describe which features I find most useful in my day-to-day work, and in what context. That way, I hope you may get something out of this article even if you’re quite familiar with Visual Studio Code (VS Code from now on). With that said, let’s get started!

The shortcuts listed here will be for macOS — naturally, they have Windows counterparts, and the keyboard shortcut preferences (⌘ + K ⌘ + S on Mac) will show what they are.

There are a couple of things worth mentioning about the keyboard shortcut preferences: first, not only can you search for a command like “add cursor below” to find out what shortcut that command is bound to, you can also search for a key binding. So, for example, searching for “ctrl shift cmd right” shows me that that keyboard shortcut is bound to “Expand Selection”. The search is clever and recognizes both “cmd” and “command”, “ctrl” and “control”, and “option” and “alt” (though not “opt”). Second, I personally switch between keyboard layouts often: I use my native layout for everyday tasks, but for programming, I switch to an American layout. As soon as you switch layouts, the keyboard shortcut settings will switch to showing you the key combination that will trigger a particular command in that layout.

Efficient Editing

There’s a classic set of text editing keyboard shortcuts that are available in many places. These include shortcuts like ⌃ + P and ⌃ + N for going to the previous or the next line, and ⌃ + A and ⌃ + E for going to the start or end of the current line. The shortcuts go back all the way to Emacs, are provided in many command-line applications using the Readline library, and work in many operating system text fields like search forms and address bars.

I find some of these quite useful in VS Code. While VS Code is no Vim (though there’s an extension for that), these shortcuts let you keep your fingers close to the home row instead of moving over to the arrow keys. ⌃ + P and ⌃ + N are particularly useful for navigating through search results and code completions. You can look up some shortcuts here, and find out for yourself which ones apply in VS Code and which ones are useful to you.

Of course, VS Code adds some editing shortcuts of its own, for moving and duplicating lines, joining the current line with the next one, and so on. When it comes to these shortcuts, at first, trying to remember which shortcut to use or looking it up will slow you down. However, I find that if a shortcut is truly useful, it quickly becomes second nature, and you start using it without thinking about it.

A particular one worth mentioning: as you move around in a file, or between files, doing edits in different places, ⌃ + - will move the cursor back to the previous place you edited, while ⌃ + ⇧ + - moves it to the next.

Snappy Selections

VS Code has shortcuts for expanding or shrinking your selection “intelligently” (⌘ + ⇧ + ⌃ + → and ⌘ + ⇧ + ⌃ + ←). I find these useful occasionally… but often, I find it expands the selection in bigger steps than I’d like. In HTML, there are some alternatives using Emmet, which we’ll get to later.

You can’t mention editing and selecting in VS Code without going into multi-cursor support. In short, VS Code allows for multiple insertion points and selections, which comes in handy in many cases. Select a string and then hit ⌘ + d to select the next occurrence of that string, or hit ⌘ + d without a selection to select the current word and then again to select the next one and so on. If, in this case, you find yourself wanting to skip an occurrence of the word, press ⌘ + d to select it and then ⌘ + k ⌘ + d to skip that word and select the next one. This is a good one to get into muscle memory.

Another useful multi-cursor shortcut: when you’ve selected several lines, you can press ⌥ + ⇧ + i (that's the letter "i") to add cursors to the ends of all the currently selected lines. By moving the cursor by word, to the beginning and the end of the line and so on in this mode, you can quickly accomplish “batch” operations on a block of similarly structured lines of code.

If you have an elaborate selection going, only to accidentally unselect everything, ⌘ + u will undo the last cursor operation and bring back your selection.

Emmet Essentials

Emmet is a project aimed at improving HTML and CSS workflow. It provides dynamic snippets and smart actions that can accomplish a lot in HTML or CSS. It is an independent project, implemented in many editors, including VS Code. The VS Code integration goes quite deep. To begin with, Emmet in VS Code works seamlessly with multiple cursors. The auto-completion list will suggest completions for Emmet abbreviations, and can even show a preview of the result of the expansion.

(Speaking about auto-completion and previews, VS Code itself has a nice touch when it comes to CSS selectors: hover over one to see a popup showing an example of an element structure matching that selector, as well as the specificity of the selector in question.)

CSS selector and specificity preview.


The party trick of Emmet is expanding CSS selector-like abbreviations into complex HTML structures. You can type something like this:

body>section*3>h1+p.description

… then hit Tab or Enter to expand the snippet into an HTML hierarchy:


This lets you author new HTML very quickly. I don’t find myself using this very much in my day-to-day work — turns out that it’s just not that often that I write deep HTML hierarchies from scratch. However, I do use the abbreviations a lot for inserting simple elements — .content to insert <div class="content"></div>, for example. In addition, Emmet has a couple of actions that come in handy when combined with these abbreviations. These are “Wrap with Abbreviation” and “Wrap Individual Lines With Abbreviations”.

The first one lets you wrap some text in one or more HTML elements. Let’s say you have your cursor somewhere on a line with an <a> element. You want this <a> element to be inside a <p> element with a class of description, itself inside an <aside> element. Run the “Wrap with Abbreviation” action through the command palette or a custom keyboard shortcut, type the abbreviation aside>p.description, press Enter, and Emmet will wrap your element in the correct structure:

<aside>
    <p class="description">
        <a href="https://example.com/">More info here.</a>
    </p>
</aside>

“Wrap Individual Lines with Abbreviation” works similarly but it lets you wrap each individual line in a block of text with an abbreviation, using * to mark the element that is going to repeat for each line. An example makes this clearer: say you have some lines of text like this:

Home
Services
About
Contact

You want to mark these up as links inside a list. Just select the lines of text, run the action “wrap individual lines with abbreviation”, and give the abbreviation ul>li*>a:


You can do a lot more with abbreviations, including providing attributes for elements in the abbreviation or using a filter in an example like the one above to remove any previous textual list markers.

To quickly generate placeholder text, Emmet includes a Lorem Ipsum generator with options! lorem expands to a 30-word-long random block of text. lorem100 expands into 100 words. These work inside repeated elements too: p*4>lorem generates four paragraphs of placeholder text.

Emmet provides some abbreviations when it comes to CSS as well. These abbreviations include not only the CSS property but also the value. You can type things like m10, p2e or bc#3, expanding respectively to margin: 10px, padding: 2em and background-color: #333333. The Emmet auto-completion and expansion preview also works in CSS.

Finally, Emmet has some actions that let you select and navigate your HTML and CSS more quickly. The “Balance Outward” and “Balance Inward” actions expand and shrink your selection in HTML, and for me does a more useful job than the built-in VS Code commands to expand and shrink selection. “Select Next Item” and “Select Previous Item” let you navigate through your HTML as well as your CSS. Like other Emmet actions, these can be run through the command palette, or bound to custom keyboard shortcuts.

Nimble Navigation

Efficient editing requires being able to move quickly between different parts of your code, whether inside the same file or across different files. We’ve touched on navigation already, but there are a few more things worth mentioning.

⌘ + ⇧ + f will bring up the search sidebar, allowing you to search across all files in your workspace. Behind the scenes, this search uses the tool ripgrep, known for its speed. Clicking on the three dots under the search field lets you specify “files to include” and “files to exclude”. “Files to exclude” can be very useful — for example, to avoid searching through sourcemaps and minified files by entering something like *.map,*.min.* in this field.

By default, ⌘ + ⇧ + o is bound to “Go to Symbol in Editor”. This lets you navigate through “sections” in a file — what constitutes a section depends on the kind of code you’re editing. In CSS, sections may include selectors and media queries, while in JavaScript, they may include variables and functions. A very similar variant of this command is “Focus Breadcrumbs”, bound to ⌘ + ⇧ + . by default. As the name suggests, this command will bring focus to the breadcrumb navigation, but it will also pop up a list here allowing you to navigate through a file in a fashion similar to the “Go to Symbol in Editor” command.

Navigating using "Go to Symbol in Editor".


Often, working on a change involves making edits in several places, perhaps even in several different files. As mentioned before: ⌃ + - and ⌃ + ⇧ + - go back and forth in the history of moving the editing cursor, and work across files. This can be very convenient to jump back and forth between the parts of your code that you’re currently working on.

On the same topic, there’s a Bookmarks extension that is pretty useful. By default, after installing the extension, ⌘ + ⌥ + k will toggle a bookmark on the current line, while ⌘ + ⌥ + j and ⌘ + ⌥ + l will jump between them… though not between files, for that you need to use the command “Bookmarks: List from All Files”, perhaps with a key binding. There’s also a custom sidebar for bookmarks.

To get a high-level overview of a file, or to focus on some piece of code without being distracted by irrelevancies, you can fold regions of code. ⌘ + ⌥ + { and ⌘ + ⌥ + } fold and unfold the current region of code, ⌘ + k ⌘ + 0 folds all regions and ⌘ + k ⌘ + j unfolds all regions.

Through its language services, VS Code provides some navigation that’s built on an “understanding” of the code. Extensions can provide this functionality for new languages. So, for example in JavaScript, hovering over an object provides a popup with info about the properties of that object, while -clicking on the object (or using the keyboard shortcut F12) takes you to the place where it was defined. There are other navigation functions available — try right-clicking on a symbol in your code to see the different “Go to” commands provided by VS Code.

Jumping to, for example, a definition takes you away from the code you were editing. Even though you can then jump back using ⌘ + u to undo the latest cursor action, or ⌃ + - to navigate to the previous edit point, this may not be what you want. You can use the “peek” functionality in VS Code to bring up an inline view of what you’re looking for instead. Pressing ⌥ + F12 instead of F12 will show the definition of the current symbol in an inline window without moving away from where you were in the code. You can then press Esc to hide this window. ⇧ + F12 will search for references to the current symbol, likewise showing them in a peek editor.

"Peek Definition" command.


This has been a look at some of the ways VS Code can help you with editing and navigating your code. In the next article in the series, we'll examine some of the support for tasks and tooling built into VS Code. As always, we're happy to hear any feedback you might have — are there, for example, any other VS Code-related topics you think we should cover? Hopefully, you got something useful out of this article!

Your Download is in Progress…

Giveaways. Cheat Sheets. eBooks. Discounts. And great content from our blog!