Syntax Highlighting
So far we've styled the VS Code UI. Now let's colour the actual code.
Token Colours
VS Code uses TextMate scopes to identify parts of your code — keywords, strings, comments, function names, and so on. You style them with tokenColors entries, each containing a name, scope, and settings.
Add a tokenColors section inside theme:
theme:
tokenColors:
- name: Comments
scope: comment
settings:
foreground: $(std.fg.inactive)
fontStyle: italic
- name: Keywords
scope: keyword, storage.type
settings:
foreground: $(accent)
- name: Strings
scope: string
settings:
foreground: $(colors.green)
- name: Numbers
scope: constant.numeric
settings:
foreground: $(colors.yellow)
- name: Functions
scope: entity.name.function
settings:
foreground: $(colors.cyan)
- name: Classes
scope: entity.name.class, entity.name.type
settings:
foreground: $(colors.blue)
fontStyle: bold
How Scopes Work
Each scope is a TextMate grammar selector. VS Code matches them against the tokens in your code:
commentmatches all commentskeywordmatchesif,return,import, etc.stringmatches string literalsentity.name.functionmatches function declarations
Comma-separated scopes (like keyword, storage.type) apply the same style to multiple scopes. VS Code uses the first matching rule, so order can matter for overlapping scopes.
The settings block supports:
foreground— the text colourfontStyle—italic,bold,underline, or combinations likebold italic
Build It
TERMINALnpx @gesslar/sassy build ocean.yaml
To see the result, install the theme in VS Code and open a source file. Comments should appear faded and italic, keywords in your accent colour, strings in green, and so on.
Use VS Code's Developer: Inspect Editor Tokens and Scopes command (from the Command Palette) to see exactly which scopes apply to any token in your code. This is invaluable when fine-tuning syntax highlighting.
Semantic Token Colours
VS Code also supports semantic tokens — language-aware tokens provided by language servers rather than TextMate grammars. These are more precise: a language server knows the difference between a variable declaration and a variable reference, for example.
You style them with semanticTokenColors. Each key is a semantic token selector, and values can be either a string (shorthand for foreground) or an object with foreground and/or fontStyle:
theme:
semanticTokenColors:
variable.declaration:
foreground: $(std.fg)
fontStyle: italic
function.declaration:
foreground: $(accent)
fontStyle: bold
"string:escape": $$yellow
Semantic tokens override tokenColors when a language server is active. Use tokenColors as the baseline and semanticTokenColors for precision where it matters.
The theme is starting to look real. Let's finish it off with UI polish.