How To Customize Semantic Token Colorization With Visual Studio Code

A Node.js terminal printout which exclaims in colorful text: “COLORS!”.

When I installed the most recent Visual Studio Code release (Update 1.45.1, April 2020 (version 1.45), I noticed something funky occurring with the syntax highlighting. The short story is that the default colors for some tokens had changed, and I wanted the default colors to stay as I was used to! This is a guide to customizing semantic token colorization for VS Code users.

Syntax highlighting determines the color and style of source code in the text editor. This is extremely useful. It provides contrast to key words, e.g. if & for in JavaScript, so that your eyes can more immediately locate a particular text among a sea of strings, variables, comments, et cetera.

The two processes that make syntax highlighting possible are:

  • Tokenization: segmenting the text based on lexical rules (regular expressions contained in a TextMate grammar) and classifying each segment with a token type.
  • Theming: using themes or user settings to map the tokens to specific colors and styles.

Semantic highlighting is an adjunct to syntax highlighting. It’s basically fancier syntax highlighting. The same idea as benefitting from a promotional deal and getting a new computer with additional memory and storage. The basic model works just fine, but the deluxe model is really worth it!

Semantic highlighting is language specific. Currently, it is available for TypeScript and JavaScript. Semantic tokenization allows language servers to improve and refine the syntax highlighting of tokens based on knowledge of how to resolve symbols in the context of a project.

This is useful because it enables greater specificity, offering the user more flexibility and control. For example, one can assign a different color or style to constant variables to distinguish them among all variables.

Customization:

VS Code, and most text editors, provide built-in themes for the editor view. It is also possible to create your own theme, but many are content to select one of the available built-ins. I use a built-in theme, hence, upon updating VS Code, I was subject to its defaults. Semantic highlighting is a default for built-in themes, but there is the ability to customize elements of the theme.

The first step is to access settings so they can be edited. There are user settings (global) and workspace settings (local). I’ll be demonstrating how to edit user settings since I’d like my color customization to persist across all projects. There are multiple ways to access the user settings. In particular, I’m targeting the settings.json file, for there I can customize. Here’s how to find it:

Command Line: Navigate to the file in the terminal.

  • macOS: $HOME/Library/Application\ Support/Code/User/settings.json
  • Linux: $HOME/.config/Code/User/settings.json
  • Windows: %APPDATA%\Code\User\settings.json
  • Note: for macOS, once in the User directory, you can open the settings.json file in the current window with this command: code -r settings.json.
Animated GIF of command line navigation of terminal.
Animated GIF of command line navigation of terminal.
Demonstration for macOS (sorry for the low resolution)

UI: Navigate to the file from the application.

  • macOS:
1. Code -> Preferences -> Settings || keyboard: [⌘][,] (command + ,)
2. Click icon of dog-eared page with flip arrow that is located on the right-hand side of the tabs header.
  • Linux & Windows:
1. File -> Preferences -> Settings || keyboard: [^][,] (control + ,)
2. Click icon of dog-eared page with flip arrow that is located on the right-hand side of the tabs header.
Animated GIF of UI navigation of application.
Animated GIF of UI navigation of application.
Demonstration for macOS (sorry for the low resolution)

The next step is to inspect the source code in order to determine the scope of what you want to customize, and evaluate its metadata. There is a convenient built-in tool for this called the Scope Inspector. You can activate the scope inspector from the Command Palette. You can launch the Command Palette with this keyboard shortcut: [⇧][⌘][P](shift + command + P), or control-click/right-click the text you want to inspect, then select “Command Palette” from the context menu.

From the Command Palette, you can type Developer: Inspect Editor Tokens and Scopes and select the matching option from the selection box to launch the Scope Inspector. With the Scope Inspector, click on or highlight the text you mean to evaluate.

A screen capture of using the VSC Scope Inspector.
Highlight the text/token console to evaluate its metadata.

In the screen capture above, the text/token console has been inspected. This is how I discovered the cause of the new colorization that I did not want from the VS Code update. In the metadata, the semantic token is assigned the color theming {“foreground”: “#9CDCFE”} (blue), and it overrides the TextMate scopes assignment {“foreground”: “#4EC9B0”} (green)—the previous color. Notice in the screen shot that console is the same color blue as variables like arr and tempArr. I like to easily find console.log, so my goal was to revert this theming.

in order to customize the theming for this token, we need to use the information listed by the Scope Inspector for semantic token type: variable, and modifier: defaultLibrary.

Now, with the needed information, we can add a key-value pair to the JSON object in settings.json. This is a model of what you’d insert:

"editor.semanticTokenColorCustomizations": {
// location
"rules": {
// identifier // theme
// identifier // theme
},

In terms of location, suppose you wanted this styling to apply globally. You could enable semantic highlighting for all themes with a key-value pair like this:

"editor.semanticTokenColorCustomizations": {
"enabled": true,
"rules": {
// identifier // theme
// identifier // theme
},

In my case, I only designated the styling for the theme I use, so the location is represented by a key-value pair of the theme name and an object:

"editor.semanticTokenColorCustomizations": {
"[Default Dark+]": {
"rules": {
// identifier // theme
// identifier // theme
},

Identifier and theme represent the targeted token and how it should be styled. The identifier is referred to as the selector and is formatted as tokenType.tokenModifier. The value of the selector represents the theme and is formatted as a value, or an object containing key-value pairs, which dictate styling.

"editor.semanticTokenColorCustomizations": {
"[Default Dark+]": {
"rules": {
// different color for all constants
"property.readonly": "#35166d",
// make all symbol declarations bold and italic
"*.declaration": {"bold": true, "italic": true}
},

In my case, I just wanted to revert the color for support variables like console and Math, and I preferred a different color for constant variables.

"editor.semanticTokenColorCustomizations": {
"[Default Dark+]": {
"rules": {
"variable.defaultLibrary": "#4EC9B0",
"variable.readonly": "#51a3c4"
}
}
}

Once I edited my settings.json file, I had the semantic token colorization just the way I like it.

This is just the tip of the iceberg when it comes to VS Code customizations! Dig in to the documentation, get some extensions, and optimize your editor to be the coding powerhouse it needs to be.

github.com/dangrammer
linked.com/in/danieljromans
danromans.com

// fullStackWebDeveloper, # software_engineer, Musician & Woodworker