mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
fix(tui): highlight C++ module files (#28554)
## Why Codex syntax-highlights diffs for conventional C++ extensions such as `.cpp` and `.cxx`, but C++ module interface files using `.cppm`, `.ixx`, or `.cxxm` fall back to plain diff coloring. The bundled syntax set already includes C++, but it does not resolve those module extensions by itself. Closes #28223. ## What changed - map `.cppm`, `.ixx`, and `.cxxm` to the existing `cpp` syntax in `render/highlight.rs` - extend alias-resolution coverage for all three module extensions - verify `.cpp`, `.cppm`, `.ixx`, and `.cxxm` diffs produce syntax-highlighted RGB spans while unknown extensions retain the plain fallback - snapshot the syntax-colored token segmentation for the supported C++ module extensions ## How to Test 1. Ask Codex to create or modify a C++ module interface file using `.cppm`, `.ixx`, or `.cxxm`. 2. Confirm C++ tokens in the rendered diff receive syntax colors instead of only the red/green diff treatment. 3. Modify an equivalent `.cpp` file and confirm its existing highlighting remains unchanged. 4. Modify a file with an unknown extension and confirm it still uses the plain diff fallback. Targeted tests: - `just test -p codex-tui -E 'test(find_syntax_resolves_languages_and_aliases) | test(cpp_module_extensions_use_cpp_highlighting) | test(unknown_extension_falls_back_without_syntax_highlighting)'`
This commit is contained in:
committed by
GitHub
Unverified
parent
a376781a3c
commit
3ded846488
@@ -1307,6 +1307,7 @@ fn style_gutter_dim() -> Style {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use insta::assert_debug_snapshot;
|
||||
use insta::assert_snapshot;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::Terminal;
|
||||
@@ -2200,6 +2201,58 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cpp_module_extensions_use_cpp_highlighting() {
|
||||
let highlighted_tokens = ["cpp", "cppm", "CPPM", "cxxm", "CxXm", "ixx", "IXX"]
|
||||
.into_iter()
|
||||
.map(|extension| {
|
||||
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();
|
||||
changes.insert(
|
||||
PathBuf::from(format!("math.{extension}")),
|
||||
FileChange::Add {
|
||||
content:
|
||||
"export module math;\nexport int sum(int a, int b) { return a + b; }\n"
|
||||
.to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let lines =
|
||||
create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80);
|
||||
let rgb_tokens = lines
|
||||
.iter()
|
||||
.flat_map(|line| &line.spans)
|
||||
.filter(|span| matches!(span.style.fg, Some(ratatui::style::Color::Rgb(..))))
|
||||
.map(|span| span.content.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
assert!(
|
||||
!rgb_tokens.is_empty(),
|
||||
"add diff for .{extension} file should produce syntax-highlighted (RGB) spans"
|
||||
);
|
||||
(extension, rgb_tokens.join("|"))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_debug_snapshot!("cpp_module_extension_highlighting", highlighted_tokens);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_extension_falls_back_without_syntax_highlighting() {
|
||||
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();
|
||||
changes.insert(
|
||||
PathBuf::from("math.unknown-extension"),
|
||||
FileChange::Add {
|
||||
content: "export module math;\nexport int value = 42;\n".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80);
|
||||
assert!(lines.iter().all(|line| {
|
||||
line.spans
|
||||
.iter()
|
||||
.all(|span| !matches!(span.style.fg, Some(ratatui::style::Color::Rgb(..))))
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_diff_uses_path_extension_for_highlighting() {
|
||||
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();
|
||||
|
||||
@@ -526,8 +526,10 @@ fn find_syntax(lang: &str) -> Option<&'static SyntaxReference> {
|
||||
let ss = syntax_set();
|
||||
|
||||
// Aliases that two-face does not resolve on its own.
|
||||
let patched = match lang {
|
||||
let normalized = lang.to_ascii_lowercase();
|
||||
let patched = match normalized.as_str() {
|
||||
"csharp" | "c-sharp" => "c#",
|
||||
"cppm" | "cxxm" | "ixx" => "cpp",
|
||||
"golang" => "go",
|
||||
"python3" => "python",
|
||||
"shell" => "bash",
|
||||
@@ -1203,7 +1205,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
// Patched aliases that two-face cannot resolve on its own.
|
||||
for alias in ["csharp", "c-sharp", "golang", "python3", "shell"] {
|
||||
for alias in [
|
||||
"csharp", "c-sharp", "cppm", "CPPM", "cxxm", "CxXm", "ixx", "IXX", "golang", "python3",
|
||||
"shell",
|
||||
] {
|
||||
assert!(
|
||||
find_syntax(alias).is_some(),
|
||||
"find_syntax({alias:?}) returned None — patched alias broken"
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: tui/src/diff_render.rs
|
||||
expression: highlighted_tokens
|
||||
---
|
||||
[
|
||||
(
|
||||
"cpp",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"cppm",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"CPPM",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"cxxm",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"CxXm",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"ixx",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
(
|
||||
"IXX",
|
||||
"export| module math|;|export| |int| |sum|(|int| |a|,| |int| |b|)| |{| |return| a |+| b|;| |}",
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user