vtcode_core/utils/
cached_style_parser.rs1use anstyle::Style as AnsiStyle;
2use anyhow::{Context, Result};
3use vtcode_commons::lr_map::LrMap;
4
5pub struct CachedStyleParser {
7 git_cache: LrMap<String, AnsiStyle>,
8 ls_colors_cache: LrMap<String, AnsiStyle>,
9}
10
11impl CachedStyleParser {
12 pub fn new() -> Self {
13 Self {
14 git_cache: LrMap::new(),
15 ls_colors_cache: LrMap::new(),
16 }
17 }
18
19 pub fn parse_git_style(&self, input: &str) -> Result<AnsiStyle> {
20 if let Some(cached) = self.git_cache.get(input) {
21 return Ok(cached);
22 }
23
24 let result =
25 anstyle_git::parse(input).map_err(|e| anyhow::anyhow!("Failed to parse Git style '{input}': {e:?}"))?;
26
27 self.git_cache.insert(input.to_string(), result);
28 Ok(result)
29 }
30
31 pub fn parse_ls_colors(&self, input: &str) -> Result<AnsiStyle> {
32 if let Some(cached) = self.ls_colors_cache.get(input) {
33 return Ok(cached);
34 }
35
36 let result = anstyle_ls::parse(input).ok_or_else(|| anyhow::anyhow!("Failed to parse LS_COLORS '{input}'"))?;
37
38 self.ls_colors_cache.insert(input.to_string(), result);
39 Ok(result)
40 }
41
42 pub fn parse_flexible(&self, input: &str) -> Result<AnsiStyle> {
43 match self.parse_git_style(input) {
44 Ok(style) => Ok(style),
45 Err(_) => self
46 .parse_ls_colors(input)
47 .with_context(|| format!("Could not parse style string: '{input}'")),
48 }
49 }
50}
51
52impl Default for CachedStyleParser {
53 fn default() -> Self {
54 Self::new()
55 }
56}