Skip to content

Add differenciation between keywords and storage keywords #51182

@Shimadakunn

Description

@Shimadakunn

Syntax token granularity gaps prevent 1:1 VS Code theme porting

Summary

Zed's syntax token types are coarser than VS Code's TextMate scopes, making it impossible to faithfully port VS Code themes. Several distinct VS Code scopes are merged into a single Zed token, forcing theme authors to choose one color and lose visual distinctions that users expect. This affects every VS Code theme port.

Problem

Gap 1: keyword vs storage

VS Code distinguishes between control flow keywords and declaration/storage keywords. Most themes color them differently — this is one of the most visible distinctions in any codebase.

VS Code scopes:

Scope Example Tokens
keyword if, else, return, throw, for, while, switch, case, break, import, export, from
storage, storage.type class, function, interface, type, enum, const, let, var
storage.modifier static, readonly, async, abstract, public, private, protected, extends, implements

Zed today: All of these map to keyword. Theme authors cannot assign different colors to class/const/function vs if/else/return.

Suggested solution: Add storage (or keyword.storage) and optionally storage.modifier syntax token types.

Gap 2: User-defined types vs built-in types

VS Code distinguishes between user-defined types and language-provided built-in types. Most themes use this to make primitives visually distinct from custom types.

VS Code scopes:

Scope Example Tokens
entity.name.type, entity.name.class User, Point, ApiResponse, EventEmitter
support.type, support.class number, string, boolean, void, Promise, Array, Map, Set, Date

Zed today: Both map to type. A user-defined User and the built-in number are visually identical.

Suggested solution: Add a type.builtin syntax token type for language-provided/primitive types.

Gap 3: Dedicated bracket pair colorization colors

VS Code provides dedicated theme keys for bracket nesting:

"editorBracketHighlight.foreground1": "...",
"editorBracketHighlight.foreground2": "...",
"editorBracketHighlight.foreground3": "..."

Zed today: Bracket pair colorization colors are derived from the players array, which is shared with multiplayer cursor/selection colors. Theme authors must compromise between optimal bracket nesting colors and appropriate multiplayer colors.

Suggested solution: Add dedicated bracket colorization keys to the theme schema, e.g.:

"editor.bracket_pair_colorization.color1": "...",
"editor.bracket_pair_colorization.color2": "...",
"editor.bracket_pair_colorization.color3": "..."

With a fallback to players if unset, for backward compatibility.

Impact

These gaps affect all VS Code theme ports. Themes that rely heavily on these distinctions include (non-exhaustive): Solarized, One Dark Pro, Dracula, Catppuccin, Nord, Gruvbox, Tokyo Night, GitHub Theme, Monokai Pro, Ayu.

The keyword vs storage gap is the most impactful — in a typical file, class, const, function, interface appear on nearly every line and are visually distinct from if/else/return in VS Code. Losing this distinction makes ported themes feel subtly wrong without users being able to identify why.

Reproduction

  1. Open this TypeScript snippet in both VS Code and Zed with the same theme colors:

    export class User {
      static readonly DEFAULT_ROLE = "user";
      constructor(public name: string, public id: number) {}
    }
    
    async function fetchUser(id: number): Promise<User | null> {
      if (id <= 0) {
        throw new Error("Invalid ID");
      }
      return null;
    }
  2. In VS Code, most themes show:

    • class, static, readonly, const, function, async in color A (storage)
    • if, throw, return, export in color B (keyword)
    • User in color C (user type)
    • number, string in color D (built-in type)
  3. In Zed, the best possible result is:

    • class, static, readonly, if, throw, return all in one color (keyword)
    • User, number, string all in one color (type)

Proposed additions

New Zed Token Maps to VS Code Scope Purpose
storage or keyword.storage storage, storage.type Declaration keywords: class, function, const, let, interface, type, enum
storage.modifier storage.modifier Modifiers: static, readonly, async, abstract, public, private, protected
type.builtin support.type, support.class Built-in/primitive types: number, string, boolean, void, Promise, Array
editor.bracket_pair_colorization.color1-6 editorBracketHighlight.foreground1-6 Dedicated bracket nesting colors, independent of players

All new tokens should be optional with sensible fallbacks (storage falls back to keyword, type.builtin falls back to type, bracket colors fall back to players) to avoid breaking existing themes.

image image

Current vs. Expected behavior

I want to have differenciation and granualirity just like in vs code to have better readibility

Zed version and system specs

Zed 0.225.12
8f51e07

0.225.12+stable.191.8f51e075bdf969725ce8fa2a032a19cdb821b9fb

Mac OS

Attach Zed log file

Zed.log

Relevant Zed settings

settings.json

Relevant Keymap

keymap.json

(for AI issues) Model provider details

No response

If you are using WSL on Windows, what flavor of Linux are you using?

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:parity/vscodeFeedback for VSCode parity featuresarea:tree-sitterSyntax highlighting and tree-sitter

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions