我正在开发一个 Rust 项目,我需要将语法突出显示应用于多行字符串中的代码块。这些代码块类似于 markdown,由带有语言标识符的三个反引号封装(例如,“```rust”)。我遇到的问题是我的实现正确捕获并突出显示第一个代码块,但无法识别后续代码块。
这是我的代码的相关部分:
fn print_highlighted_response(response: &str) {
// ... (initialize SyntaxSet and ThemeSet)
let re = Regex::new(r"```(\w+)\n([\s\S]+?)\n```").unwrap();
// ... (iterating over captures and applying syntax highlighting)
}
// ... (rest of the code)
我使用正则表达式板条箱来解析字符串,并使用语法突出显示语法。该函数应该找到每个代码块,应用语法突出显示,并将其打印到控制台。但是,第一个代码块会突出显示,但在 ``` 之后它不会停止突出显示,因此响应的其余部分会突出显示。
任何关于为什么后续代码块没有被捕获的见解都将不胜感激,或者提供执行上述语法突出显示的替代方法!
这是我需要解析的响应示例。它有正常文本和代码块:
Here's a simple implementation of the Two Sum problem in Rust:
```rust
use std::collections::HashMap;
fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut map = HashMap::new();
for (i, num) in nums.iter().enumerate() {
if let Some(n) = map.get(&(target - num)) {
return vec![*n, i as i32];
}
map.insert(num, i);
}
vec![]
}
```
And now we have normal text again, but this is also highlighted
```rust
use std::collections::HashMap;
fn new_method(nums: Vec<i32>) -> Vec<i32> {
}
```
当很可能有多个代码块并且正则表达式/实现不能正常工作时,就会出现问题。这是完整的代码实现,希望这里允许。
fn print_highlighted_response(response: &str) {
let ss = SyntaxSet::load_defaults_newlines();
let ts = ThemeSet::load_defaults();
let re = Regex::new(r"```(\w+)\n([\s\S]+?)\n```").unwrap();
let mut last_end = 0;
for cap in re.captures_iter(response) {
print_plain_text(&response[last_end..cap.get(0).unwrap().start()]);
let language = cap.get(1).map_or("Plain Text", |m| m.as_str());
let code_block = cap.get(2).unwrap().as_str();
let syntax = ss.find_syntax_by_token(language)
.unwrap_or_else(|| ss.find_syntax_plain_text());
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
for line in LinesWithEndings::from(code_block) {
let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ss).unwrap();
let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
print!("{}", escaped);
}
last_end = cap.get(0).unwrap().end();
}
print_plain_text(&response[last_end..]);
}
fn print_plain_text(text: &str) {
print!("{}", text);
}
来自 as_24_bit_terminal_escaped() 的文档:
请注意,这当前不会取消设置颜色,因此行尾也会随背景突出显示。这意味着如果您可能想使用 println!("\x1b[0m");之后清除颜色。
因此,正如 @Jmb 在评论中建议的那样,最后一个着色转义代码在语法突出显示块的末尾仍然处于活动状态。 只需按照文档中的建议添加
println!("\x1b[0m");
。
顺便说一句,但这与您的语法突出显示问题无关,因为您认为
language
是可选的(默认为纯文本),您可能应该将 (\w+)
转换为 (\w*)
,否则它不会检测到未指定语言时块的开头。