Visual Studio Code is a Free, lightweight programming editor, available for Windows, Linux and Mac. It is open source and very actively developed. The monthly updates always include many new features and improvements. Thanks to a lively community ecosystem, numerous additional functionalities are available as free extensions.
This article is published from the DNC Magazine for Developers and Architects. Download this magazine from here [PDF] or Subscribe to this magazine for FREE and download all previous and current editions.
This article should help you get started, or make you more productive at this increasingly popular text editor.
Visual Studio Code - Getting Started
The Free Visual Studio Code installer for all supported platforms (Windows, Linux, macOS) can be downloaded from https://code.visualstudio.com/. You can also download the Insiders build, i.e. a preview version that can be installed in parallel to the stable version. Their icons are of different colors (blue icon for release build, green for the Insiders build), to easily differentiate between the two. Both builds automatically download and install updates, when the editor is restarted.
Once you open VS Code, you will observe most of the window is dedicated to the editor. There are tabs for switching between the currently opened files above it, and a status bar with basic information about the currently edited files, below it. To the left of the editor, there is a vertical view bar with five icons (See Figure 1). By clicking them, the following side bars open, from top to bottom:
- Explorer side bar (keyboard shortcut Ctrl+Shift+E) lists the currently opened files, and the contents of the open folder. The number in the icon badge (not shown in the figure) indicates how many files have unsaved changes.
- Search side bar (Ctrl+Shift+F or Ctrl+Shift+H) allows searching and replacing across all files in the opened folder, and provides a preview of the results.
- Git side bar (Ctrl+Shift+G) allows basic interaction with Git version control. The number in the icon badge indicates how many files have uncommitted changes.
- Debug side bar (Ctrl+Shift+D) contains the main debugger user interface.
- Extensions side bar (Ctrl+Shift+X) allows management of extensions. The number in the icon badge indicates how many installed extensions do newer versions have available.
The currently open side bar can be hidden using Ctrl+B.
Figure 1: View bar with Explorer side bar opened
Although the editor allows opening of individual files, many of its more advanced functionalities requires the user to open a folder, which takes on the role of a workspace. This can be done by selecting the File > Open Folder… menu item, or by clicking the Open Folder button in the Explorer side bar.
By default, Visual Studio Code will reopen the last open folder when it starts the next time. If the corresponding option is selected in the installer, the Open with Code shell extension can also be used when right clicking a folder in Explorer.
Figure 2: Open folder from Explorer side bar
The editor keeps a track of recently opened files and folders. They can be accessed by navigating to File > Open Recent menu item. In Windows, both the lists are also available from the taskbar jump list, which can be accessed by right clicking the application icon in the Windows taskbar.
The installer automatically adds Visual Studio Code executable to PATH (except on the Mac, where it can be done manually from within the editor), so that files and folders can easily be opened in the editor from the command line:
# open current folder in a new Visual Studio Code window
# open current folder in existing Visual Studio Code window
code . -reuse
# open the listed files in a new Visual Studio Code window
code readme.md .gitignore package.json
# open the listed folders, each one in its own Visual Studio Code window
code project1 project2
There are additional command line arguments available for even more control over the editor.
Becoming Productive with VS Code
Keyboard shortcuts in a text editor plays a big role in making users productive, therefore shortcuts will be mentioned throughout the remainder of the article. It is also strongly recommended that you print out the keyboard shortcuts reference for your OS, and keep it on your desk. You can download a copy via the Help > Keyboard shortcut Reference menu item.
Probably the most important part of the editor to learn about is the Command Palette (keyboard shortcut F1 or Ctrl+Shift+P). As an alternative to menus and keyboard shortcuts, it provides access to all available commands - both built-in, and those added by extensions. Each command in the list also displays the associated keyboard shortcut, if assigned. By typing in text, you can filter the sorted list for quicker access to the command.
Figure 3: Invoking a command from the Command Palette
Depending on the first character in the input box, the Command Palette supports different modes. Each one of them is also directly accessible with its own keyboard shortcut.
Table 1: Supported actions in Command Palette
As with commands, you can filter the resulting list by typing additional text in the input box. If you enter only the ‘?’ character, help with all the options will be shown.
Figure 4: Built-in Command Palette help
Tabs and Groups
By default, files will open as new tabs in the editor, unless there is already a file in the editor in preview mode. In this case, the newly opened file will replace it. Every opened file is in the preview mode, until you edit it or double click on it. Files in preview mode have their filename in italics.
The editor also supports side by side editing, by organizing the files in up to three groups. You can arrange the groups vertically or horizontally and switch between the two modes with a button in the Open Editors section of Explorer side bar, or with Shift+Alt+1 keyboard shortcut. To open another view of the current file in a new group, click on the Split Editor icon on the top right corner or press Ctrl+\ . To open a new file in a new group, Ctrl click on it in Explorer side bar, or press Ctrl+Enter in quick open dialog. Use Ctrl+1, Ctrl+2 or Ctrl+3 to switch to first, second or third group respectively. Use Ctrl+Tab to switch to a different file in the same group.
Figure 5: Switch between vertical and horizontal group layout
Being foremost a programming editor, Visual Studio Code includes all the standard functionalities you would expect:
- Bracket matching (Ctrl+Shift+\)
- Code block commenting (Ctrl+K Ctrl+C) and uncommenting (Ctrl+K Ctrl+U)
- Smart selection growing (Shift+Alt+right) and shrinking (Shift+Alt+left)
- Code folding (Ctrl+Shift+[) and unfolding (Ctrl+Shift+]), including folding the full file to a specific level (Ctrl+K Ctrl+0 to Ctrl+K Ctrl+5) and unfolding the full file (Ctrl+K Ctrl+J)
- Zooming the editor in (Ctrl++) and out (Ctrl+-)
- Find (Ctrl+F in file, Ctrl+Shift+F in workspace) and replace (Ctrl+H in file, Ctrl+Shift+H in workspace) with regular expression support (including referencing matched groups with $1, $2… when replacing) and filtering files by filename when searching in workspace (Ctrl+Shift+J when Search side bar is opened)
- Multi cursor editing with block selection (Ctrl+Shift+Alt+cursor or Shift+Alt+click), custom adding of cursors (Alt+click) and adding find results to selection (Ctrl+D)
For programming languages with language server support (built-in or extension-based), there are additional functionalities:
- IntelliSense code suggestions (automatically as you type and manually invoked with Ctrl+Space)
- Method parameter hints (automatically when you open parenthesis and manually invoked with Ctrl+Shift+Space)
- Go to symbol definition (F12, opens a new file or moves cursor in same file) and peek symbol definition (Alt+F12, opens inline view with full editing support, Esc closes it)
- Find all references (Shift+F12 opens inline view with full editing support, Esc closes it)
- Rename symbol (F2)
- Code formatting (Shift+Alt+F to format the full file, Ctrl+K Ctrl+F to format the current selection only)
Figure 6: All symbol references in inline view
Hovering over a symbol shows context dependent information in a popup, e.g. namespace for a type, declaration for a variable or field, parameters and documentation for method, etc.
Figure 7: Popup for Angular Component declaration
Customizing the Visual Studio Code Editor
Once you get familiar enough with the editor, you will want to customize it to your tastes. You can start by installing an extension. The Extensions side bar (Ctrl+Shift+X) will show the list of installed extensions when opened (initially empty). To find an extension to install, simply enter the search query in the input box or select one of the provided categories to list popular extensions.
Figure 8: Select a common extensions category
Before installing an extension, you can review its details by clicking on it in the list:
- Its description by the author(s)
- A list of contributions it adds to the editor: settings, commands, debuggers, etc.
- Number of downloads and average rating as an estimate of its popularity and quality
Enabling a newly installed or updated extension and disabling existing extensions will require you to restart the application.
There are many different categories of extensions and I will give more attention to many of them in the remainder of the article. To get you started, here are some of my favorite extensions, which I will not have an opportunity to mention later:
- Bookmarks allows you to add custom bookmarks to lines and quickly jump to them later.
- Contextual Duplicate adds a command to duplicate any text selection in the editor.
- Camel Case Navigation adds the ability to navigate through text by stopping at words separated by camel case humps not only by whitespace or by punctuation.
Themes and Icons
There are two options for customizing the appearance:
- Color themes (File > Preferences > Color Theme menu or Preferences: Color Theme from Command Palette) allows you to change the colors used for the windows and text including syntax highlighting.
- File icon themes (File > Preferences > File Icon Theme menu or Preferences: File Icon Theme from Command Palette) allows you to add icons based on file and folder type to the Explorer side bar and elsewhere in the application.
Both commands provide a list of available themes with a live preview when you select them. There is also an option to search for additional themes in the extensions marketplace if none of the available alternatives suits you. My current favorites are the built-in Dark+ (default dark) color theme and VS Code Icons file icon theme from the vscode-icons extension. The latter is currently probably the largest collection of icons for Visual Studio Code. Unfortunately, it only works well with dark color themes.
Snippets are a special type of item that appears in value completion lists (invoked with Ctrl+Space). Snippets are language dependent, and allow you to insert preconfigured custom blocks of code with optional tab stops and variables to modify the default values. Many snippets are already built-in. You can install some additional ones as extensions. To see which snippets are available for the language of your current file, you can invoke the Insert Snippet command from the Command Palette.
Figure 9: TypeScript snippet suggestions in Visual Studio Code
If you cannot find a snippet that suits your needs, you can also create your own. Open File > Preferences > User Snippets from the menu or invoke Preferences: Open User Snippets from the Command Palette and select the target language to open the dedicated JSON file for editing. Comments at the top of the file provide an explanation of the format and a sample snippet for the language, to get you started.
To modify keyboard bindings, open the configuration file from the Command Palette (Preferences: Open Keyboard Shortcuts) or from the menu (File > Preferences > Keyboard Shortcuts). The command will open two JSON files side by side: Default Keyboard Shortcuts with all built-in shortcuts defined in read-only mode, and keybindings.json with your customized shortcuts, which will be empty by default. In both files, you can use text search to find commands of interest. You can even use symbol search to navigate the files by keyboard shortcuts.
With Ctrl+K Ctrl+K you can invoke a simple wizard for adding a placeholder for a new shortcut. You will only need to modify the command value in most cases. To help you with that, there is value completion available (Ctrl+Space) for built-in commands. Alternatively, you can copy a keybinding definition from Default Keyboard Shortcuts and remove (by adding a ’-‘ character in front of the command value) or add a shortcut (by changing the key value) for the command.
The when part of the keybinding definition specifies the condition, when the shortcut is valid. Usually, you will not need to modify it. Nevertheless, the supported values are well documented.
Extensions will typically include suggested keybinding definitions in their description, so that you can simply copy and paste them to your keybindings.json file. Visual Studio Code supports JSON comments in configuration files, which you can use to document your intentions:
// remove default binding
// add alternative binding
// rebind shortcut to an extension command
If you want to reconfigure the keybindings to match your favorite text editor, there are extensions available, which will do that for you. Search for keymap in Extensions side bar and you can choose from most current editors: ReSharper, Sublime, Atom, Emacs, and others. There is even a Vim extension available.
You can change general application settings by modifying the settings.json file. You can access it from the menu (File > Preferences > User Settings) or from the Command Palette (Preferences: Open User Settings). Similar to keyboard bindings, Default Settings file will open in read-only mode on the left, and the initially empty settings.json file will open on the right.
Again, you can enter new values to the latter by using value completion (Ctrl+Space) or by copying settings from the left file. They are neatly grouped together by the subsystem they affect or the extension they originate from. Of course, you can also search for specific text in the file.
Here are some of the settings you might want to change:
- Automatic saving of files, file formatting and whitespace trimming on save: files.autoSave, files.autoSaveDelay, editor.formatOnSave, files.trimTrailingWhitespace
- Indentation guides, rulers and visible whitespace: editor.renderIndentGuides, editor.rulers, editor.renderWhitespace
- Font ligatures (you will need to use a font, which supports ligatures, e.g. FiraCode): editor.fontLigatures, editor.fontFamily
- Positioning of snippets in the value suggestion popup: editor.snippetSuggestions
- Automatic updating of extensions: extensions.autoUpdate
- Shell to use in the integrated terminal (which can be invoked with Ctrl+`): terminal.integrated.shell.windows. In Windows, you can use one of the following values, depending on your favorite shell:
- "C:\\WINDOWS\\system32\\cmd.exe" to use the classic cmd shell
- "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe" to use PowerShell
- "C:\\Windows\\system32\\bash.exe" to use Bash if you installed Windows Subsystem for Linux in Windows 10
- "C:\\Windows\\SysWOW64\\cmd.exe" for terminal.integrated.shell.windows and ["/c", "C:\\Program Files\\Git\\bin\\sh.exe"] for terminal.integrated.shellArgs.windows to use Git Bash
There are many other settings available, though. You will want to do some exploration on your own.
Configuring the Visual Studio Code Workspace
As the name implies, user settings are tied to the user profile. However, you can also configure settings at the workspace (i.e. folder) level and override the user settings. These settings will be stored in .vscode\settings.json file inside your folder. You can put the file in version control and share it with other developers working on the project. To create or edit the file, navigate to File > Preferences > Workspace Settings or invoke Preferences: Open Workspace Settings from the Command Palette. The file format is identical to the one for user settings.
Here are some good candidates for workspace settings:
- Files and folders to be hidden from the Explorer sidebar (e.g. .git and node_modules): files.exclude
- Code indentation settings: editor.detectIndentation, editor.insertSpaces, editor.tabSize
- Custom JSON schemas for files in the project: json.schemas
Visual Studio Code has extensive built-in support for Git. However, you must have Git already installed on the machine. Most of the interaction with Git occurs in the Git side bar. It provides an overview of uncommitted changes in the repository with the following functionalities:
- View the changes in individual files
- Clean the changes
- Stage the changed file
- Enter the commit message, and commit the staged files (or all changed files, when none are staged)
If remotes are configured in the repository pull, push and sync commands are available as well. If any merge conflicts occur, basic syntax highlighting is available to help you resolve them. In the status bar, there is information about the current branch. By clicking on it you can check out another branch.
Figure 10: Git information in status bar
In the marketplace, there are already many extensions available, which expand the existing Git support. Some of the most popular ones are:
- GitLens adds CodeLens information to code blocks as introduced in Visual Studio, and includes blame and history views.
- Git History (git log) implements a history graph with the ability to inspect details of each commit.
- Git Blame shows blame information about the current line in the status bar.
Other version control systems are not supported out of the box, but there are extensions available to provide basic support for most common ones: Mercurial, Subversion, Team Foundation Version Control, Perforce, etc.
Most software development today includes some kind of building process, usually involving a task runner, such as Grunt or Gulp. Visual Studio Code has support for many task runners out of the box. The configuration is stored in .vscode\tasks.json. Trying to invoke the Tasks: Run Build Task command (Ctrl+Shift+B by default) will open a list of supported runners if the file does not exist yet.
Figure 11: Task runner selection
Selecting one will generate a new file with default configuration for the runner of choice:
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"args": ["run", "test"]
The format is simple enough to understand. The generated file even includes a link to the official documentation, which you can consult for a detailed explanation. Nevertheless, a couple of things regarding this functionality are still worth mentioning:
- You can add a problemMatcher property to a task to enable parsing of its output. This will add the parsed errors and warnings to the Problems pane inside Visual Studio Code (Ctrl+Shift+M). Clicking individual entries will open the related file at the offending line to help you locate the issue. As always, value completion will suggest available built-in matchers. You can parse other output formats with regular expressions.
Figure 12: Problem matcher configuration
- You can use isBuildCommand and isTestCommand to mark a task as build, or test task. You will be able to run these two tasks using Tasks: Run Build Task and Tasks: Run Test Task, respectively. For the other tasks, you will need to invoke Tasks: Run Task command and select the task from the list. Alternatively, you can install vscode-status-bar-tasks extension to add the tasks as buttons to the status bar.
- Visual Studio Code will automatically detect tasks from Gulp, Grunt and Jake, and make them available in Command Palette even without specifying them in tasks.json. You will still need the file if you want to configure problem matchers or otherwise customize the tasks, though. Task Master extension will expand this automatic task detection to other formats, such as NPM, PowerShell, etc.
- Although you can have as many tasks as you want in a workspace, the tasks.json file format requires all of them to use the same task runner (specified as the command value). As a workaround for using more than one, you will need to use shell as command, or write a custom script which will delegate the calls to different task runners based on its arguments.
Debugging configuration is similar to task runner configuration: Debug: Start Debugging command (F5 by default) will open a list of supported debuggers if debugging is not configured yet. The number of debuggers available will depend on the extensions installed.
Figure 13: Debugger selection
Selecting one will initialize a new .vscode\launch.json configuration file:
// Use IntelliSense to learn about possible Node.js debug attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"name": "Launch Program",
"name": "Attach to Process",
The link will again bring you to the official documentation of the format. However, in the case of debuggers, the available options differ a lot between debuggers, therefore you will need to consult their own documentation or make do with the sample file each one generates, and the completion suggestions.
Unlike task runners, you can configure multiple debuggers in a single workspace. The only downside is that you will not get the sample configuration for them, when launch.json file already exists. To work around it, you can temporarily rename the file and then manually merge in the contents of the newly generated file.
Figure 14: Debug side bar
The Debug side bar is the common interface of all installed debuggers. At the top, you can select a configuration and start debugging it. Below it are four sections:
- In Variables section, you can inspect the values found in the current stack frame.
- In Watch section, you can add your own variables to inspect their values.
- Call Stack section shows the current call stack and allows you to select a different stack frame to inspect.
- Breakpoints shows a list of all breakpoints set, allowing you to temporarily disable or delete them.
You can set a breakpoint by pressing F9 in a source code line or by clicking in front of its line number. Right clicking the red dot indicating the breakpoint will give you the option to set a condition when the breakpoint will hit, based either on an expression value or on the hit count. Support for this and other debugger features can vary from debugger to debugger. The built-in Node.js debugger will support all features, while other debuggers might not have yet implemented all of them.
Visual Studio Code - Languages Support
Visual Studio Code only has built-in support for web development, including but not limited to:
- HTML with Emmet (formerly Zen Coding) support
- CSS, Sass and Less
- Node.js debugger
Many extensions can further improve the experience:
- Debuggers and more: Debugger for Chrome, Cordova Tools, React Native Tools, NativeScript
- Linters: TSLint, ESLint, jshint, stylelint
- Snippets for frameworks: Angular 2 TypeScript Snippets, AngularJs 1.x Code Snippets, Reactjs code snippets, Aurelia Snippets, ionic 2 Commands with Snippets, ionic1-snippets
- CodeLens visualizers: TypeLens, Version Lens
Thanks to extensions, Visual Studio Code is not limited to web development either. You can easily use it for development in many other languages:
I was not an early adopter of Visual Studio Code, but ever since I have started using it, it has grown on me. Of course, I still regularly use integrated development environments, such as Visual Studio and IntelliJ IDEA. However, Visual Studio Code is close to being the only text editor I am using on a regular basis. It has also become my tool of choice for client-side web development because of its small footprint and great debugging support.
I hope that after reading this article, you will want to try it out, if you have not done so already. Who knows, this awesome code editor will grow on you as well!