git_igitt/util/
syntax_highlight.rs1use lazy_static::lazy_static;
2use syntect::easy::HighlightLines;
3use syntect::highlighting::Color as SynColor;
4use syntect::highlighting::{Style, Theme, ThemeSet};
5use syntect::parsing::SyntaxSet;
6use tui::style::Color;
7use tui::text::{Span, Spans, Text};
8
9lazy_static! {
10 static ref SYNTAX: Syntax = Syntax {
11 syntax: SyntaxSet::load_defaults_nonewlines(),
12 themes: ThemeSet::load_defaults()
13 };
14 static ref THEME: Theme = create_custom_theme();
15}
16
17struct Syntax {
18 pub syntax: SyntaxSet,
19 pub themes: ThemeSet,
20}
21
22fn create_custom_theme() -> Theme {
23 let mut theme = SYNTAX.themes.themes["Solarized (dark)"].clone();
24 theme.settings.foreground = theme.settings.foreground.map(|color| brighter(color, 0.4)); theme
26}
27
28fn brighter(color: SynColor, factor: f32) -> SynColor {
29 SynColor {
30 r: color.r + ((255 - color.r) as f32 * factor) as u8,
31 g: color.g + ((255 - color.g) as f32 * factor) as u8,
32 b: color.b + ((255 - color.b) as f32 * factor) as u8,
33 a: color.a,
34 }
35}
36
37pub fn highlight(lines: &str, extension: &str) -> Option<Vec<Vec<(Style, String)>>> {
38 let syntax = match SYNTAX.syntax.find_syntax_by_extension(extension) {
39 None => return None,
40 Some(syntax) => syntax,
41 };
42
43 let mut h = HighlightLines::new(syntax, &THEME);
44
45 let spans: Vec<_> = lines
48 .lines()
49 .map(|line| {
50 h.highlight_line(line.trim_end(), &SYNTAX.syntax)
51 .unwrap()
52 .into_iter()
53 .map(|(s, l)| (s, l.to_string()))
54 .collect::<Vec<_>>()
55 })
56 .collect();
57
58 Some(spans)
59}
60
61pub fn as_styled(lines: &'_ [Vec<(Style, String)>]) -> Text<'_> {
62 let spans: Vec<_> = lines
63 .iter()
64 .map(|line| {
65 Spans(
66 line.iter()
67 .map(|(style, string)| {
68 Span::styled(
69 string,
70 tui::style::Style::default().fg(Color::Rgb(
71 style.foreground.r,
72 style.foreground.g,
73 style.foreground.b,
74 )),
75 )
76 })
77 .collect(),
78 )
79 })
80 .collect();
81
82 Text::from(spans)
83}