use ratatui::style::Color;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum CodeBlockTheme {
#[default]
AyuDark,
GitHubDark,
Dracula,
Nord,
Monokai,
OneDark,
Gruvbox,
TokyoNight,
Catppuccin,
}
#[derive(Debug, Clone, Copy)]
pub struct CodeBlockColors {
pub border: Color,
pub background: Color,
pub header_bg: Color,
pub header_text: Color,
pub icon: Color,
pub line_number: Color,
pub line_separator: Color,
}
impl CodeBlockTheme {
pub fn colors(&self) -> CodeBlockColors {
match self {
CodeBlockTheme::AyuDark => CodeBlockColors {
border: Color::Rgb(57, 63, 84),
background: Color::Rgb(10, 14, 20),
header_bg: Color::Rgb(15, 20, 28),
header_text: Color::Rgb(179, 186, 197),
icon: Color::Rgb(255, 180, 84), line_number: Color::Rgb(70, 80, 100),
line_separator: Color::Rgb(45, 52, 70),
},
CodeBlockTheme::GitHubDark => CodeBlockColors {
border: Color::Rgb(70, 70, 70),
background: Color::Rgb(30, 30, 30),
header_bg: Color::Rgb(40, 40, 40),
header_text: Color::Rgb(180, 180, 180),
icon: Color::Rgb(255, 200, 100),
line_number: Color::Rgb(90, 90, 90),
line_separator: Color::Rgb(60, 60, 60),
},
CodeBlockTheme::Dracula => CodeBlockColors {
border: Color::Rgb(98, 114, 164),
background: Color::Rgb(40, 42, 54),
header_bg: Color::Rgb(68, 71, 90),
header_text: Color::Rgb(248, 248, 242),
icon: Color::Rgb(255, 121, 198), line_number: Color::Rgb(98, 114, 164),
line_separator: Color::Rgb(68, 71, 90),
},
CodeBlockTheme::Nord => CodeBlockColors {
border: Color::Rgb(76, 86, 106),
background: Color::Rgb(46, 52, 64),
header_bg: Color::Rgb(59, 66, 82),
header_text: Color::Rgb(216, 222, 233),
icon: Color::Rgb(136, 192, 208), line_number: Color::Rgb(76, 86, 106),
line_separator: Color::Rgb(59, 66, 82),
},
CodeBlockTheme::Monokai => CodeBlockColors {
border: Color::Rgb(117, 113, 94),
background: Color::Rgb(39, 40, 34),
header_bg: Color::Rgb(54, 55, 49),
header_text: Color::Rgb(248, 248, 242),
icon: Color::Rgb(230, 219, 116), line_number: Color::Rgb(117, 113, 94),
line_separator: Color::Rgb(73, 72, 62),
},
CodeBlockTheme::OneDark => CodeBlockColors {
border: Color::Rgb(76, 82, 99),
background: Color::Rgb(40, 44, 52),
header_bg: Color::Rgb(50, 56, 66),
header_text: Color::Rgb(171, 178, 191),
icon: Color::Rgb(229, 192, 123), line_number: Color::Rgb(76, 82, 99),
line_separator: Color::Rgb(58, 64, 76),
},
CodeBlockTheme::Gruvbox => CodeBlockColors {
border: Color::Rgb(146, 131, 116),
background: Color::Rgb(40, 40, 40),
header_bg: Color::Rgb(60, 56, 54),
header_text: Color::Rgb(235, 219, 178),
icon: Color::Rgb(250, 189, 47), line_number: Color::Rgb(146, 131, 116),
line_separator: Color::Rgb(80, 73, 69),
},
CodeBlockTheme::TokyoNight => CodeBlockColors {
border: Color::Rgb(61, 89, 161),
background: Color::Rgb(26, 27, 38),
header_bg: Color::Rgb(36, 40, 59),
header_text: Color::Rgb(169, 177, 214),
icon: Color::Rgb(125, 207, 255), line_number: Color::Rgb(61, 89, 161),
line_separator: Color::Rgb(41, 46, 66),
},
CodeBlockTheme::Catppuccin => CodeBlockColors {
border: Color::Rgb(127, 132, 156),
background: Color::Rgb(30, 30, 46),
header_bg: Color::Rgb(49, 50, 68),
header_text: Color::Rgb(205, 214, 244),
icon: Color::Rgb(249, 226, 175), line_number: Color::Rgb(127, 132, 156),
line_separator: Color::Rgb(69, 71, 90),
},
}
}
pub fn all() -> &'static [CodeBlockTheme] {
&[
CodeBlockTheme::AyuDark,
CodeBlockTheme::GitHubDark,
CodeBlockTheme::Dracula,
CodeBlockTheme::Nord,
CodeBlockTheme::Monokai,
CodeBlockTheme::OneDark,
CodeBlockTheme::Gruvbox,
CodeBlockTheme::TokyoNight,
CodeBlockTheme::Catppuccin,
]
}
pub fn name(&self) -> &'static str {
match self {
CodeBlockTheme::AyuDark => "Ayu Dark",
CodeBlockTheme::GitHubDark => "GitHub Dark",
CodeBlockTheme::Dracula => "Dracula",
CodeBlockTheme::Nord => "Nord",
CodeBlockTheme::Monokai => "Monokai",
CodeBlockTheme::OneDark => "One Dark",
CodeBlockTheme::Gruvbox => "Gruvbox",
CodeBlockTheme::TokyoNight => "Tokyo Night",
CodeBlockTheme::Catppuccin => "Catppuccin",
}
}
}
pub const HEADING_ICONS: [&str; 6] = [
"󰲡 ", "󰲣 ", "󰲥 ", "󰲧 ", "󰲩 ", "󰲫 ", ];
pub const BULLET_MARKERS: [&str; 4] = ["\u{25cf} ", "\u{25cb} ", "\u{25c6} ", "\u{25c7} "];
pub const CHECKBOX_UNCHECKED: &str = "\u{f0131} "; pub const CHECKBOX_CHECKED: &str = "\u{f0c52} "; pub const CHECKBOX_TODO: &str = "\u{f0954} ";
pub const BLOCKQUOTE_MARKER: &str = "\u{258b}";
pub const HORIZONTAL_RULE_CHAR: char = '\u{2500}';
pub const LINK_ICON: &str = "\u{f0339} "; pub const IMAGE_ICON: &str = "\u{f0976} "; pub const EMAIL_ICON: &str = "\u{f0013} ";
pub fn get_link_icon(url: &str) -> &'static str {
let url_lower = url.to_lowercase();
if url_lower.contains("github.com") {
"\u{f02a4} "
} else if url_lower.contains("gitlab.com") {
"\u{f0ba0} "
} else if url_lower.contains("discord.com") || url_lower.contains("discord.gg") {
"\u{f066f} "
} else if url_lower.contains("linkedin.com") {
"\u{f033b} "
} else if url_lower.contains("reddit.com") {
"\u{f044d} "
} else if url_lower.contains("slack.com") {
"\u{f04b1} "
} else if url_lower.contains("stackoverflow.com") {
"\u{f04cc} "
} else if url_lower.contains("twitter.com") || url_lower.contains("x.com") {
" "
} else if url_lower.contains("wikipedia.org") {
"\u{f05ac} "
} else if url_lower.contains("youtube.com") || url_lower.contains("youtu.be") {
"\u{f05c3} "
} else if url_lower.starts_with("mailto:") {
EMAIL_ICON
} else if url_lower.ends_with(".png")
|| url_lower.ends_with(".jpg")
|| url_lower.ends_with(".jpeg")
|| url_lower.ends_with(".gif")
|| url_lower.ends_with(".svg")
|| url_lower.ends_with(".webp")
{
IMAGE_ICON
} else {
LINK_ICON
}
}
pub fn get_language_icon(lang: &str) -> &'static str {
match lang.to_lowercase().as_str() {
"rust" | "rs" => "\u{e7a8} ", "c" => "\u{e61e} ", "cpp" | "c++" | "cxx" | "cc" => "\u{e61d} ", "zig" => "\u{e6a9} ", "nim" => "\u{e677} ", "d" => "\u{e7af} ", "ada" => "\u{f1786} ",
"fortran" | "f90" | "f95" => "\u{f121a} ",
"assembly" | "asm" | "nasm" => "\u{e6ab} ",
"javascript" | "js" | "mjs" | "cjs" => "\u{e74e} ", "typescript" | "ts" | "mts" | "cts" => "\u{e628} ", "jsx" | "tsx" | "react" => "\u{e7ba} ", "html" | "htm" => "\u{e736} ", "css" => "\u{e749} ", "scss" | "sass" => "\u{e74b} ", "less" => "\u{e758} ", "svelte" => "\u{e697} ", "vue" => "\u{e6a0} ", "astro" => "\u{e6b6} ",
"python" | "py" | "pyw" | "pyi" => "\u{f0320} ",
"ruby" | "rb" | "erb" => "\u{e739} ", "php" => "\u{e73d} ", "perl" | "pl" | "pm" => "\u{e769} ", "lua" => "\u{e620} ", "r" | "rmd" => "\u{e68a} ", "julia" => "\u{e624} ",
"java" => "\u{e738} ", "kotlin" | "kt" | "kts" => "\u{e634} ", "scala" => "\u{e737} ", "groovy" => "\u{e775} ", "clojure" | "clj" | "cljs" | "cljc" => "\u{e76a} ",
"csharp" | "cs" | "c#" => "\u{f031b} ",
"fsharp" | "fs" | "f#" => "\u{e7a7} ", "vb" | "vbnet" | "visualbasic" => "\u{f06e4} ",
"haskell" | "hs" => "\u{e777} ", "elixir" | "ex" | "exs" => "\u{e62d} ", "erlang" | "erl" => "\u{e7b1} ", "ocaml" | "ml" => "\u{e67a} ", "elm" => "\u{e62c} ", "purescript" | "purs" => "\u{e630} ", "racket" | "rkt" => "\u{f0627} ",
"scheme" | "scm" => "\u{f0627} ",
"lisp" | "cl" | "el" => "\u{f0172} ",
"swift" => "\u{e755} ", "objectivec" | "objc" | "m" => "\u{e61e} ", "dart" => "\u{e798} ",
"go" | "golang" => "\u{e626} ", "v" | "vlang" => "\u{e6ac} ", "crystal" => "\u{e7a3} ", "odin" => "\u{f0b94} ",
"bash" | "sh" | "shell" | "zsh" | "fish" | "ksh" | "csh" => "\u{e795} ", "powershell" | "ps1" | "psm1" => "\u{f0a0a} ",
"batch" | "bat" | "cmd" => "\u{e629} ", "nushell" | "nu" => "\u{e795} ",
"json" | "jsonc" | "json5" => "\u{e60b} ", "yaml" | "yml" => "\u{e6a8} ", "toml" => "\u{e6b2} ", "xml" | "xsl" | "xslt" => "\u{f05c0} ",
"ini" | "conf" | "cfg" => "\u{e615} ", "env" | "dotenv" => "\u{e615} ", "csv" => "\u{e64a} ",
"markdown" | "md" | "mdx" => "\u{e73e} ", "latex" | "tex" => "\u{e69b} ", "rst" | "restructuredtext" => "\u{e6a5} ", "asciidoc" | "adoc" => "\u{e6a5} ", "org" => "\u{e633} ",
"sql" | "mysql" | "postgresql" | "postgres" | "sqlite" => "\u{e706} ", "plsql" | "plpgsql" => "\u{e706} ", "mongodb" | "mongo" => "\u{e7a4} ", "redis" => "\u{e76d} ", "graphql" | "gql" => "\u{e662} ", "prisma" => "\u{e684} ",
"docker" | "dockerfile" | "containerfile" => "\u{e7b0} ", "kubernetes" | "k8s" => "\u{f10fe} ",
"terraform" | "tf" | "hcl" => "\u{f1062} ",
"ansible" => "\u{e7b0} ", "vagrant" => "\u{e7b0} ", "nix" => "\u{e779} ", "nginx" => "\u{e776} ", "apache" => "\u{e769} ",
"makefile" | "make" | "mk" => "\u{e779} ", "cmake" => "\u{e615} ", "gradle" => "\u{e660} ", "maven" | "pom" => "\u{e674} ", "cargo" => "\u{e7a8} ", "npm" | "package.json" => "\u{e71e} ", "yarn" => "\u{e6a7} ", "pnpm" => "\u{e71e} ", "pip" | "requirements" => "\u{f0320} ",
"git" | "gitignore" | "gitconfig" | "gitattributes" => "\u{e702} ", "diff" | "patch" => "\u{e728} ",
"vim" | "vimrc" | "neovim" | "nvim" => "\u{e62b} ", "emacs" | "elisp" => "\u{e632} ", "vscode" | "code" => "\u{f0a1e} ",
"solidity" | "sol" => "\u{e6ac} ", "move" => "\u{f01a7} ",
"cairo" => "\u{f0725} ",
"wasm" | "wat" | "webassembly" => "\u{e6a1} ", "llvm" | "ir" => "\u{e61e} ", "cuda" | "cu" => "\u{e61e} ", "opencl" => "\u{e61e} ", "glsl" | "hlsl" | "shader" => "\u{e6ad} ", "proto" | "protobuf" => "\u{e6ae} ", "thrift" => "\u{e6ae} ", "avro" => "\u{e6ae} ", "capnp" => "\u{e6ae} ", "flatbuffers" | "fbs" => "\u{e6ae} ",
"regex" | "regexp" => "\u{e656} ", "http" | "rest" => "\u{e60c} ", "binary" | "hex" => "\u{e7a3} ", "log" | "logs" => "\u{e714} ", "text" | "txt" | "plain" => "\u{e612} ",
_ => "\u{e612} ", }
}
pub fn heading_bg_color(level: u8) -> Color {
match level {
1 => Color::Rgb(80, 40, 80), 2 => Color::Rgb(40, 60, 80), 3 => Color::Rgb(40, 80, 60), 4 => Color::Rgb(80, 60, 40), 5 => Color::Rgb(60, 60, 60), 6 => Color::Rgb(50, 50, 50), _ => Color::Rgb(50, 50, 50),
}
}
pub fn heading_fg_color(level: u8) -> Color {
match level {
1 => Color::Rgb(255, 180, 255), 2 => Color::Rgb(130, 180, 255), 3 => Color::Rgb(130, 255, 180), 4 => Color::Rgb(255, 200, 130), 5 => Color::Rgb(200, 200, 200), 6 => Color::Rgb(170, 170, 170), _ => Color::White,
}
}