use directories::ProjectDirs;
use lazy_static::lazy_static;
use ratatui::style::{Color, Style};
use syntect::{
highlighting::{Theme, ThemeSet},
parsing::SyntaxSet,
};
use unicode_width::UnicodeWidthStr;
pub type SyntectStyle = syntect::highlighting::Style;
pub const GUTTER: &str = "▌ ";
lazy_static! {
pub static ref GUTTER_WIDTH: u16 = UnicodeWidthStr::width(GUTTER) as u16;
}
pub const LIGHT_BLUE: Color = Color::Rgb(0, 122, 204);
pub const PURPLE: Color = Color::Rgb(197, 134, 192);
pub const LIGHT_GRAY: Color = Color::Rgb(205, 205, 205);
pub const DARK_GRAY2: Color = Color::Rgb(139, 148, 158);
pub const DARK_GRAY3: Color = Color::Rgb(40, 40, 40);
pub const NEAR_BLACK: Color = Color::Rgb(20, 20, 20);
pub const NEAR_BLACK2: Color = Color::Rgb(30, 30, 30);
pub const METALLIC_BLUE: Color = Color::Rgb(101, 154, 211);
pub const LIGHT_TOURQUOISE: Color = Color::Rgb(168, 218, 216);
pub const TOURQUOISE: Color = Color::Rgb(82, 197, 176);
pub const DARK_PURPLE: Color = Color::Rgb(97, 40, 119);
pub const DARK_BLUE: Color = Color::Rgb(20, 56, 92);
#[derive(Clone, Debug)]
pub struct TextStyle {
pub fg_color: Color,
pub bg_color: Color,
pub bold: bool,
pub italic: bool,
pub underline: bool,
pub strikethrough: bool,
}
impl TextStyle {
pub fn inverted_default() -> Self {
Self {
fg_color: NEAR_BLACK2,
bg_color: LIGHT_GRAY,
bold: false,
italic: false,
underline: false,
strikethrough: false,
}
}
pub fn with_fg_color(mut self, color: Color) -> Self {
self.fg_color = color;
self
}
pub fn with_bg_color(mut self, color: Color) -> Self {
self.bg_color = color;
self
}
pub fn with_bold(mut self) -> Self {
self.bold = true;
self
}
pub fn with_italic(mut self) -> Self {
self.italic = true;
self
}
pub fn with_underline(mut self) -> Self {
self.underline = true;
self
}
pub fn with_strikethrough(mut self) -> Self {
self.strikethrough = true;
self
}
}
impl Default for TextStyle {
fn default() -> Self {
Self {
fg_color: LIGHT_GRAY,
bg_color: NEAR_BLACK2,
bold: false,
italic: false,
underline: false,
strikethrough: false,
}
}
}
impl From<TextStyle> for Style {
fn from(val: TextStyle) -> Self {
let mut style = Style::new().fg(val.fg_color).bg(val.bg_color);
style = if val.bold { style.bold() } else { style };
style = if val.italic { style.italic() } else { style };
style = if val.underline {
style.underlined()
} else {
style
};
style = if val.strikethrough {
style.crossed_out()
} else {
style
};
style
}
}
#[derive(Clone, Debug, Default)]
pub struct HighlightConfig {
pub syntax_set: SyntaxSet,
pub theme: Theme,
}
impl HighlightConfig {
pub fn new() -> Self {
let syn_set = SyntaxSet::load_defaults_newlines();
let mut theme_set = ThemeSet::load_defaults();
if let Some(proj_dirs) = ProjectDirs::from("org", "codemonk", "monothink") {
let mut share_dir = proj_dirs.data_dir().to_path_buf();
share_dir.push("themes");
let share_path = share_dir.as_path();
theme_set
.add_from_folder(share_path)
.expect("Failed to load theme folder.");
}
let theme = theme_set.themes.get("darkplus").unwrap_or_else(|| {
theme_set
.themes
.get("base16-ocean.dark")
.expect("Cannot load default theme")
});
Self {
syntax_set: syn_set,
theme: theme.clone(),
}
}
}