apple_code_assistant/utils/
syntax_highlight.rs1use syntect::easy::HighlightLines;
4use syntect::highlighting::ThemeSet;
5use syntect::parsing::SyntaxSet;
6use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
7
8fn lang_to_extension(lang: &str) -> &str {
10 match lang.to_lowercase().as_str() {
11 "rust" => "rs",
12 "typescript" | "ts" => "ts",
13 "javascript" | "js" => "js",
14 "python" | "py" => "py",
15 "go" => "go",
16 "java" => "java",
17 "c" => "c",
18 "cpp" | "c++" => "cpp",
19 "csharp" | "c#" => "cs",
20 "swift" => "swift",
21 "kotlin" => "kt",
22 "ruby" => "rb",
23 "php" => "php",
24 "html" => "html",
25 "css" => "css",
26 "sql" => "sql",
27 "shell" | "bash" | "sh" => "sh",
28 "json" => "json",
29 "yaml" | "yml" => "yml",
30 "markdown" | "md" => "md",
31 _ => "txt",
32 }
33}
34
35pub fn highlight_to_ansi(code: &str, language: Option<&str>, dark: bool) -> String {
37 let ps = SyntaxSet::load_defaults_newlines();
38 let ts = ThemeSet::load_defaults();
39 let theme_name = if dark {
40 "base16-ocean.dark"
41 } else {
42 "base16-ocean.light"
43 };
44 let theme = match ts.themes.get(theme_name) {
45 Some(t) => t,
46 None => return code.to_string(),
47 };
48 let ext = language.map(lang_to_extension).unwrap_or("txt");
49 let syntax = match ps.find_syntax_by_extension(ext) {
50 Some(s) => s,
51 None => return code.to_string(),
52 };
53 let mut highlighter = HighlightLines::new(syntax, theme);
54 let mut out = String::new();
55 for line in LinesWithEndings::from(code) {
56 if let Ok(ranges) = highlighter.highlight_line(line, &ps) {
57 out.push_str(&as_24_bit_terminal_escaped(&ranges[..], true));
58 } else {
59 out.push_str(line);
60 }
61 out.push('\n');
62 }
63 out
64}