vscode_theme
A fully typed Rust representation of every color key in VS Code's official theme customization schema.
Repository Health
Technical Analysis
vscode_theme is a small Rust crate that turns Visual Studio Code’s workbench.colorCustomizations schema into a fully typed, serde-serializable set of structs instead of a loose bag of string keys. The entire type surface — a top-level Colors struct plus roughly a hundred grouped sub-structs like EditorColors and ActivityBarColors — is code-generated directly from Microsoft’s own theme-color reference documentation, so field names, groupings, and rustdoc comments come straight from the authoritative source rather than being hand-transcribed.
Because every generated struct field is annotated with #[serde(flatten)] where appropriate and a shared empty_string_as_none deserializer, a Colors value round-trips to and from the exact flat JSON object VS Code itself reads and writes, including its habit of representing an unset color as an empty string. The crate is intentionally minimal for consumers: its only runtime dependency is serde, keeping it easy to drop into any Rust tool that needs to read, construct, or validate a VS Code theme file.
What You Get
- A top-level
Colorsstruct covering every color key documented in VS Code’s official theme-color reference - Roughly 100 grouped sub-structs (e.g.
EditorColors,ActivityBarColors,DebugConsoleColors) that mirror VS Code’s own dot-namespaced key groupings - Serde
Serialize/Deserializeimplementations that round-trip to the exact flat JSON shape VS Code reads and writes - A shared
empty_string_as_nonedeserializer so VS Code’s empty-string “unset” convention maps cleanly to Rust’sOption<String> - Per-field rustdoc comments sourced verbatim from Microsoft’s theme-color documentation, giving inline descriptions for every color key
Common Use Cases
- Building a theme converter or importer that translates another editor’s or design tool’s color scheme into a valid VS Code theme JSON file
- Writing a linter or validator that checks a VS Code theme file for typos in color keys before publishing an extension
- Programmatically generating or templating VS Code themes (e.g. from a base palette or design tokens) with compile-time guarantees on key names
- Parsing an existing VS Code theme file in a Rust tool to inspect, diff, or migrate specific color values
Under The Hood
Architecture
The repository is a two-crate Cargo workspace: crates/vscode_theme, the published, consumer-facing library, and crates/codegen, an internal, unpublished binary that generates it. vscode_theme’s public API is a single re-export (pub use generated::* in lib.rs) exposing the Colors struct and its ~100 grouped *Colors sub-structs, all produced by codegen’s main.rs, which parses Microsoft’s official theme-color.md reference doc (vendored from the vscode-docs repo) with a hand-rolled line-based parser, groups color keys by their dot-delimited namespace prefix (e.g. editor.background groups under editor), and uses quote/syn/prettyplease to emit typed, serde-annotated Rust code back into crates/vscode_theme/src/generated/theme.rs — a checked-in file explicitly marked “Do not modify by hand!”. Ungrouped keys become top-level fields on Colors; grouped keys become a nested #[serde(flatten)] sub-struct field, so the wire format stays a single flat JSON object while the Rust type gives a hierarchical, discoverable surface. Updating for a new VS Code release means re-running the codegen binary against a refreshed reference doc, not hand-editing structs.
Tech Stack
Rust 2021 edition, published as a two-member Cargo workspace. The published vscode_theme crate has exactly one runtime dependency, serde (with the derive feature), pinned via workspace-level [workspace.dependencies]. The internal codegen crate depends on anyhow for error propagation, heck for snake_case/UpperCamelCase conversion, indexmap for order-preserving color maps, and proc-macro2/quote/syn/prettyplease for programmatic Rust code generation and pretty-printing. There is no async runtime, no CLI argument parser (codegen is a plain fn main), and no CI workflow configuration in the repository. The crate is published to crates.io with docs.rs documentation.
Code Quality
No test files exist anywhere in the repository — neither #[test] functions nor a #[cfg(test)] module appear in either crate. Error handling in codegen consistently uses anyhow::Result with ? propagation rather than panics, though the markdown parsing itself is a naive line-matching scan (line.starts_with("- \”)) with no validation that every documented color was actually captured. Naming is idiomatic Rust throughout (snake_case fields, UpperCamelCase struct names, both derived programmatically via heck), and the generated surface favors strong typing — every color field is Option<String>with a shared custom deserializer rather than a rawserde_json::Value. There is no linter or formatter configuration beyond prettyplease`‘s formatting of the generated file, and no CI workflow, so correctness currently rests on manual review rather than automated enforcement.
API Design
The crate’s core value is converting VS Code’s informally-documented, stringly-typed workbench.colorCustomizations schema into a fully typed Rust surface without hand-maintaining hundreds of struct fields — both the struct shape and the field-level rustdoc come straight from Microsoft’s own reference markdown, so documentation stays accurate to the spec rather than being re-written by a maintainer. Because every struct mirrors the flat JSON shape #[serde(flatten)], integrating with an existing theme file is a single serde_json::from_str::<Colors>() or to_string() call — there’s no builder API or configuration step. The trade-off is discoverability: with roughly 100 generated structs and only a one-line crate doc comment, a newcomer has to browse the generated module or docs.rs’s struct index to find the right nested field rather than following a guided top-level API.