Skip to main content

oak_lua/lsp/highlighter/
mod.rs

1#![doc = include_str!("readme.md")]
2/// 高亮类型的本地定义
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum HighlightKind {
5    /// 关键字
6    Keyword,
7    /// 字符串
8    String,
9    /// 数字
10    Number,
11    /// 注释
12    Comment,
13    /// 宏
14    Macro,
15    /// 标识符
16    Identifier,
17    /// 运算符
18    Operator,
19}
20
21/// 高亮器 trait
22pub trait Highlighter {
23    /// 对给定的文本进行高亮处理
24    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)>;
25}
26
27/// Lua 语法高亮器
28pub struct LuaHighlighter;
29
30impl LuaHighlighter {
31    pub fn new() -> Self {
32        Self
33    }
34}
35
36impl Highlighter for LuaHighlighter {
37    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)> {
38        let mut highlights = Vec::new();
39
40        // 简单的正则表达式或基于词法分析的高亮实现
41        // 这里我们可以复用 LuaLexer 来获取 Token
42        use crate::lexer::{LuaLexer, token_type::LuaTokenType};
43        use oak_core::{LexOutput, Lexer, LexerCache, SourceText, Token};
44
45        struct SimpleCache {
46            tokens: Vec<Token<LuaTokenType>>,
47        }
48
49        impl LexerCache<crate::language::LuaLanguage> for SimpleCache {
50            fn set_lex_output(&mut self, output: LexOutput<crate::language::LuaLanguage>) {
51                if let Ok(tokens) = output.result {
52                    self.tokens = tokens.to_vec()
53                }
54            }
55            fn get_token(&self, index: usize) -> Option<Token<LuaTokenType>> {
56                self.tokens.get(index).cloned()
57            }
58            fn count_tokens(&self) -> usize {
59                self.tokens.len()
60            }
61            fn has_tokens(&self) -> bool {
62                !self.tokens.is_empty()
63            }
64        }
65
66        let config = crate::language::LuaLanguage::default();
67        let lexer = LuaLexer::new(&config);
68        let mut cache = SimpleCache { tokens: Vec::new() };
69        let source = SourceText::new(text);
70        let output = lexer.lex(&source, &[], &mut cache);
71
72        if let Ok(tokens) = output.result {
73            for token in tokens.iter() {
74                let kind = match token.kind {
75                    LuaTokenType::And
76                    | LuaTokenType::Break
77                    | LuaTokenType::Do
78                    | LuaTokenType::Else
79                    | LuaTokenType::Elseif
80                    | LuaTokenType::End
81                    | LuaTokenType::False
82                    | LuaTokenType::For
83                    | LuaTokenType::Function
84                    | LuaTokenType::Goto
85                    | LuaTokenType::If
86                    | LuaTokenType::In
87                    | LuaTokenType::Local
88                    | LuaTokenType::Nil
89                    | LuaTokenType::Not
90                    | LuaTokenType::Or
91                    | LuaTokenType::Repeat
92                    | LuaTokenType::Return
93                    | LuaTokenType::Then
94                    | LuaTokenType::True
95                    | LuaTokenType::Until
96                    | LuaTokenType::While => Some(HighlightKind::Keyword),
97                    LuaTokenType::String => Some(HighlightKind::String),
98                    LuaTokenType::Number => Some(HighlightKind::Number),
99                    LuaTokenType::Comment => Some(HighlightKind::Comment),
100                    LuaTokenType::Identifier => Some(HighlightKind::Identifier),
101                    LuaTokenType::Plus
102                    | LuaTokenType::Minus
103                    | LuaTokenType::Star
104                    | LuaTokenType::Slash
105                    | LuaTokenType::Percent
106                    | LuaTokenType::Caret
107                    | LuaTokenType::Hash
108                    | LuaTokenType::EqEq
109                    | LuaTokenType::TildeEq
110                    | LuaTokenType::LtEq
111                    | LuaTokenType::GtEq
112                    | LuaTokenType::Lt
113                    | LuaTokenType::Gt
114                    | LuaTokenType::Eq => Some(HighlightKind::Operator),
115                    _ => None,
116                };
117
118                if let Some(h_kind) = kind {
119                    highlights.push((token.span.start, token.span.end, h_kind))
120                }
121            }
122        }
123
124        highlights
125    }
126}