Regex 未捕获 Rust 中多行字符串中的所有代码块

问题描述 投票:0回答:1

我正在开发一个 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);
}

Image for reference when running CLI in terminal (iTerm)

regex rust syntax-highlighting
1个回答
0
投票

来自 as_24_bit_terminal_escaped() 的文档:

请注意,这当前不会取消设置颜色,因此行尾也会随背景突出显示。这意味着如果您可能想使用 println!("\x1b[0m");之后清除颜色。

因此,正如 @Jmb 在评论中建议的那样,最后一个着色转义代码在语法突出显示块的末尾仍然处于活动状态。 只需按照文档中的建议添加

println!("\x1b[0m");

顺便说一句,但这与您的语法突出显示问题无关,因为您认为

language
是可选的(默认为纯文本),您可能应该将
(\w+)
转换为
(\w*)
,否则它不会检测到未指定语言时块的开头。

© www.soinside.com 2019 - 2024. All rights reserved.