From e0b9c3afd01d30d37732467ed7d885152da1da95 Mon Sep 17 00:00:00 2001
From: Bret Comnes <166301+bcomnes@users.noreply.github.com>
Date: Thu, 2 Apr 2026 06:22:35 -0700
Subject: [PATCH] Add support for `diff.plus` and `diff.minus` highlight
captures (#45459)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Update diff in highlights.scm to use semantic @diff.plus and
@diff.minus tokens
- Add diff.plus, diff.minus tokens to fallback theme
- Add diff syntax tokens to all official themes (One, Gruvbox, Ayu)
This fixes the issue where diff files showed inverted colors (additions
in purple/blue, deletions in green) by using proper semantic tokens
instead of @string and @keyword.
Related discussion in https://github.com/zed-industries/zed/issues/34057
(thought there might be second issue in that issue)
Release Notes:
- Added support for diff.plus, diff.minus and diff.deleta theme
selectors in the diff syntax grammar. Previously diff.plus was mapped to
@string and diff.minus was mapped to @keyword.
*Before:*
*After:*
*Before:*
*After:*
*Before:*
*After:*
---------
Co-authored-by: Finn Evers
Co-authored-by: MrSubidubi
---
assets/themes/ayu/ayu.json | 30 +++++++++++++
assets/themes/gruvbox/gruvbox.json | 60 +++++++++++++++++++++++++
assets/themes/one/one.json | 20 +++++++++
crates/grammars/src/diff/highlights.scm | 6 +--
crates/theme/src/fallback_themes.rs | 2 +
5 files changed, 114 insertions(+), 4 deletions(-)
diff --git a/assets/themes/ayu/ayu.json b/assets/themes/ayu/ayu.json
index 3450e35bf62d780bdaf0cff2c6bc9f8bdfea7c1e..c62f9eb11238e21bbc8c04c8fda4bbe7bfc72a81 100644
--- a/assets/themes/ayu/ayu.json
+++ b/assets/themes/ayu/ayu.json
@@ -391,6 +391,16 @@
"color": "#5ac1feff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#aad94cff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#f07178ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -783,6 +793,16 @@
"color": "#3b9ee5ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#6cbf43ff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#ff6666ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -1175,6 +1195,16 @@
"color": "#72cffeff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#aad94cff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#f07178ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
diff --git a/assets/themes/gruvbox/gruvbox.json b/assets/themes/gruvbox/gruvbox.json
index 16ae188712f7a800ab4fb8a81a2d24cac99da56b..a4fc1b561b36421b353187ef4a2639dae88e901d 100644
--- a/assets/themes/gruvbox/gruvbox.json
+++ b/assets/themes/gruvbox/gruvbox.json
@@ -406,6 +406,16 @@
"color": "#83a598ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#b8bb26ff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#fb4934ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -813,6 +823,16 @@
"color": "#83a598ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#b8bb26ff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#fb4934ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -1220,6 +1240,16 @@
"color": "#83a598ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#b8bb26ff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#fb4934ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -1627,6 +1657,16 @@
"color": "#0b6678ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#79740eff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#9d0006ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -2034,6 +2074,16 @@
"color": "#0b6678ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#79740eff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#9d0006ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -2441,6 +2491,16 @@
"color": "#0b6678ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#79740eff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#9d0006ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
diff --git a/assets/themes/one/one.json b/assets/themes/one/one.json
index 05af3f5cfeec7d4a24c4fe6d684fb21d04e2d81c..409a5c705c518e83f08dcbaafc1b29c8120beae9 100644
--- a/assets/themes/one/one.json
+++ b/assets/themes/one/one.json
@@ -403,6 +403,16 @@
"color": "#73ade9ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#98c379ff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#e06c75ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
@@ -805,6 +815,16 @@
"color": "#5b79e3ff",
"font_style": null,
"font_weight": null
+ },
+ "diff.plus": {
+ "color": "#50a14fff",
+ "font_style": null,
+ "font_weight": null
+ },
+ "diff.minus": {
+ "color": "#e45649ff",
+ "font_style": null,
+ "font_weight": null
}
}
}
diff --git a/crates/grammars/src/diff/highlights.scm b/crates/grammars/src/diff/highlights.scm
index a2e33190f154d6a210572dbb066000dca6f30455..3c9abbe147b6554d6894d5d8d3c8bcf5d93e2edd 100644
--- a/crates/grammars/src/diff/highlights.scm
+++ b/crates/grammars/src/diff/highlights.scm
@@ -3,15 +3,13 @@
[
(addition)
(new_file)
-] @string
+] @string @diff.plus
-; TODO: This should eventually be `@diff.plus` with a fallback of `@string`
[
(deletion)
(old_file)
-] @keyword
+] @keyword @diff.minus
-; TODO: This should eventually be `@diff.minus` with a fallback of `@keyword`
(commit) @constant
(location) @attribute
diff --git a/crates/theme/src/fallback_themes.rs b/crates/theme/src/fallback_themes.rs
index ba7f600fb05cc160f8d2668cf549853c8ae39ebe..a3831cafff68a3858a76b8e29071c88579090bcc 100644
--- a/crates/theme/src/fallback_themes.rs
+++ b/crates/theme/src/fallback_themes.rs
@@ -377,6 +377,8 @@ pub(crate) fn zed_default_dark() -> Theme {
("variable".into(), HighlightStyle::default()),
("variable.special".into(), red.into()),
("variant".into(), HighlightStyle::default()),
+ ("diff.plus".into(), green.into()),
+ ("diff.minus".into(), red.into()),
])),
},
}