1use ratatui::style::Color;
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
9pub enum CodeBlockTheme {
10 #[default]
12 AyuDark,
13 GitHubDark,
15 Dracula,
17 Nord,
19 Monokai,
21 OneDark,
23 Gruvbox,
25 TokyoNight,
27 Catppuccin,
29}
30
31#[derive(Debug, Clone, Copy)]
33pub struct CodeBlockColors {
34 pub border: Color,
36 pub background: Color,
38 pub header_bg: Color,
40 pub header_text: Color,
42 pub icon: Color,
44 pub line_number: Color,
46 pub line_separator: Color,
48}
49
50impl CodeBlockTheme {
51 pub fn colors(&self) -> CodeBlockColors {
53 match self {
54 CodeBlockTheme::AyuDark => CodeBlockColors {
55 border: Color::Rgb(57, 63, 84),
56 background: Color::Rgb(10, 14, 20),
57 header_bg: Color::Rgb(15, 20, 28),
58 header_text: Color::Rgb(179, 186, 197),
59 icon: Color::Rgb(255, 180, 84), line_number: Color::Rgb(70, 80, 100),
61 line_separator: Color::Rgb(45, 52, 70),
62 },
63 CodeBlockTheme::GitHubDark => CodeBlockColors {
64 border: Color::Rgb(70, 70, 70),
65 background: Color::Rgb(30, 30, 30),
66 header_bg: Color::Rgb(40, 40, 40),
67 header_text: Color::Rgb(180, 180, 180),
68 icon: Color::Rgb(255, 200, 100),
69 line_number: Color::Rgb(90, 90, 90),
70 line_separator: Color::Rgb(60, 60, 60),
71 },
72 CodeBlockTheme::Dracula => CodeBlockColors {
73 border: Color::Rgb(98, 114, 164),
74 background: Color::Rgb(40, 42, 54),
75 header_bg: Color::Rgb(68, 71, 90),
76 header_text: Color::Rgb(248, 248, 242),
77 icon: Color::Rgb(255, 121, 198), line_number: Color::Rgb(98, 114, 164),
79 line_separator: Color::Rgb(68, 71, 90),
80 },
81 CodeBlockTheme::Nord => CodeBlockColors {
82 border: Color::Rgb(76, 86, 106),
83 background: Color::Rgb(46, 52, 64),
84 header_bg: Color::Rgb(59, 66, 82),
85 header_text: Color::Rgb(216, 222, 233),
86 icon: Color::Rgb(136, 192, 208), line_number: Color::Rgb(76, 86, 106),
88 line_separator: Color::Rgb(59, 66, 82),
89 },
90 CodeBlockTheme::Monokai => CodeBlockColors {
91 border: Color::Rgb(117, 113, 94),
92 background: Color::Rgb(39, 40, 34),
93 header_bg: Color::Rgb(54, 55, 49),
94 header_text: Color::Rgb(248, 248, 242),
95 icon: Color::Rgb(230, 219, 116), line_number: Color::Rgb(117, 113, 94),
97 line_separator: Color::Rgb(73, 72, 62),
98 },
99 CodeBlockTheme::OneDark => CodeBlockColors {
100 border: Color::Rgb(76, 82, 99),
101 background: Color::Rgb(40, 44, 52),
102 header_bg: Color::Rgb(50, 56, 66),
103 header_text: Color::Rgb(171, 178, 191),
104 icon: Color::Rgb(229, 192, 123), line_number: Color::Rgb(76, 82, 99),
106 line_separator: Color::Rgb(58, 64, 76),
107 },
108 CodeBlockTheme::Gruvbox => CodeBlockColors {
109 border: Color::Rgb(146, 131, 116),
110 background: Color::Rgb(40, 40, 40),
111 header_bg: Color::Rgb(60, 56, 54),
112 header_text: Color::Rgb(235, 219, 178),
113 icon: Color::Rgb(250, 189, 47), line_number: Color::Rgb(146, 131, 116),
115 line_separator: Color::Rgb(80, 73, 69),
116 },
117 CodeBlockTheme::TokyoNight => CodeBlockColors {
118 border: Color::Rgb(61, 89, 161),
119 background: Color::Rgb(26, 27, 38),
120 header_bg: Color::Rgb(36, 40, 59),
121 header_text: Color::Rgb(169, 177, 214),
122 icon: Color::Rgb(125, 207, 255), line_number: Color::Rgb(61, 89, 161),
124 line_separator: Color::Rgb(41, 46, 66),
125 },
126 CodeBlockTheme::Catppuccin => CodeBlockColors {
127 border: Color::Rgb(127, 132, 156),
128 background: Color::Rgb(30, 30, 46),
129 header_bg: Color::Rgb(49, 50, 68),
130 header_text: Color::Rgb(205, 214, 244),
131 icon: Color::Rgb(249, 226, 175), line_number: Color::Rgb(127, 132, 156),
133 line_separator: Color::Rgb(69, 71, 90),
134 },
135 }
136 }
137
138 pub fn all() -> &'static [CodeBlockTheme] {
140 &[
141 CodeBlockTheme::AyuDark,
142 CodeBlockTheme::GitHubDark,
143 CodeBlockTheme::Dracula,
144 CodeBlockTheme::Nord,
145 CodeBlockTheme::Monokai,
146 CodeBlockTheme::OneDark,
147 CodeBlockTheme::Gruvbox,
148 CodeBlockTheme::TokyoNight,
149 CodeBlockTheme::Catppuccin,
150 ]
151 }
152
153 pub fn name(&self) -> &'static str {
155 match self {
156 CodeBlockTheme::AyuDark => "Ayu Dark",
157 CodeBlockTheme::GitHubDark => "GitHub Dark",
158 CodeBlockTheme::Dracula => "Dracula",
159 CodeBlockTheme::Nord => "Nord",
160 CodeBlockTheme::Monokai => "Monokai",
161 CodeBlockTheme::OneDark => "One Dark",
162 CodeBlockTheme::Gruvbox => "Gruvbox",
163 CodeBlockTheme::TokyoNight => "Tokyo Night",
164 CodeBlockTheme::Catppuccin => "Catppuccin",
165 }
166 }
167}
168
169pub const HEADING_ICONS: [&str; 6] = [
171 " ", " ", " ", " ", " ", " ", ];
178
179pub const BULLET_MARKERS: [&str; 4] = ["\u{25cf} ", "\u{25cb} ", "\u{25c6} ", "\u{25c7} "];
181
182pub 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}";
189
190pub const HORIZONTAL_RULE_CHAR: char = '\u{2500}';
192
193pub 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 {
200 let url_lower = url.to_lowercase();
201 if url_lower.contains("github.com") {
202 "\u{f02a4} "
203 } else if url_lower.contains("gitlab.com") {
204 "\u{f0ba0} "
205 } else if url_lower.contains("discord.com") || url_lower.contains("discord.gg") {
206 "\u{f066f} "
207 } else if url_lower.contains("linkedin.com") {
208 "\u{f033b} "
209 } else if url_lower.contains("reddit.com") {
210 "\u{f044d} "
211 } else if url_lower.contains("slack.com") {
212 "\u{f04b1} "
213 } else if url_lower.contains("stackoverflow.com") {
214 "\u{f04cc} "
215 } else if url_lower.contains("twitter.com") || url_lower.contains("x.com") {
216 " "
217 } else if url_lower.contains("wikipedia.org") {
218 "\u{f05ac} "
219 } else if url_lower.contains("youtube.com") || url_lower.contains("youtu.be") {
220 "\u{f05c3} "
221 } else if url_lower.starts_with("mailto:") {
222 EMAIL_ICON
223 } else if url_lower.ends_with(".png")
224 || url_lower.ends_with(".jpg")
225 || url_lower.ends_with(".jpeg")
226 || url_lower.ends_with(".gif")
227 || url_lower.ends_with(".svg")
228 || url_lower.ends_with(".webp")
229 {
230 IMAGE_ICON
231 } else {
232 LINK_ICON
233 }
234}
235
236pub fn get_language_icon(lang: &str) -> &'static str {
238 match lang.to_lowercase().as_str() {
239 "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} ",
247 "fortran" | "f90" | "f95" => "\u{f121a} ",
248 "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} ",
264 "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} ",
280 "fsharp" | "fs" | "f#" => "\u{e7a7} ", "vb" | "vbnet" | "visualbasic" => "\u{f06e4} ",
282
283 "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} ",
291 "scheme" | "scm" => "\u{f0627} ",
292 "lisp" | "cl" | "el" => "\u{f0172} ",
293
294 "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} ",
304
305 "bash" | "sh" | "shell" | "zsh" | "fish" | "ksh" | "csh" => "\u{e795} ", "powershell" | "ps1" | "psm1" => "\u{f0a0a} ",
308 "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} ",
316 "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} ",
338 "terraform" | "tf" | "hcl" => "\u{f1062} ",
339 "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} ",
355
356 "git" | "gitignore" | "gitconfig" | "gitattributes" => "\u{e702} ", "diff" | "patch" => "\u{e728} ", "vim" | "vimrc" | "neovim" | "nvim" => "\u{e62b} ", "emacs" | "elisp" => "\u{e632} ", "vscode" | "code" => "\u{f0a1e} ",
364
365 "solidity" | "sol" => "\u{e6ac} ", "move" => "\u{f01a7} ",
368 "cairo" => "\u{f0725} ",
369 "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} ", }
390}
391
392pub fn heading_bg_color(level: u8) -> Color {
394 match level {
395 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),
402 }
403}
404
405pub fn heading_fg_color(level: u8) -> Color {
407 match level {
408 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,
415 }
416}