leetcode_api/render/
mod.rs1pub mod qs_detail;
2pub mod run_res;
3pub mod submit_list;
4
5use std::{
6 io::prelude::Write,
7 process::{Command, Stdio},
8};
9
10#[cfg(feature = "ratatui")]
11use ratatui::text::Line;
12use regex::{Captures, Regex};
13
14#[derive(Clone, Copy)]
15#[derive(Debug)]
16#[derive(Default)]
17#[derive(PartialEq, Eq)]
18pub enum SupSub {
19 #[default]
20 Sup,
21 Sub,
22}
23
24#[derive(Clone, Copy)]
25#[derive(Debug)]
26#[derive(Default)]
27#[derive(PartialEq, Eq)]
28pub enum StTy {
29 Str,
30 #[default]
31 Tty,
32}
33
34pub trait Render {
35 fn to_md_str(&self, _with_env: bool) -> String {
39 String::new()
40 }
41
42 #[cfg(feature = "ratatui")]
44 fn to_para_vec(&self) -> Vec<Line>;
45
46 fn render_with_mdcat(&self) {
48 let content = self.to_md_str(false);
49 'out: {
50 let Ok(mut child) = Command::new("mdcat")
51 .stdin(Stdio::piped())
52 .stdout(Stdio::inherit())
53 .spawn()
54 else {
55 break 'out;
56 };
57 if let Some(mut stdin) = child.stdin.take() {
58 if stdin
59 .write_all(content.as_bytes())
60 .is_err()
61 {
62 break 'out;
63 };
64 }
66 else {
67 break 'out;
68 };
69
70 let Ok(exit_status) = child.wait()
71 else {
72 break 'out;
73 };
74 if exit_status.success() {
75 return;
76 }
77 }
78
79 println!("{content}");
80 }
81}
82
83pub fn to_sub_sup_script(content: &str) -> String {
84 let sup_re = Regex::new("<sup>(?P<num>[0-9]*)</sup>").expect("regex new failed");
85 let sub_re = Regex::new("<sub>(?P<num>[0-9]*)</sub>").expect("regex new failed");
86
87 let content = sup_re.replace_all(content, |cap: &Captures| {
88 let num = cap["num"].parse().unwrap_or_default();
89 superscript(num, SupSub::Sup)
90 });
91
92 let content = sub_re.replace_all(&content, |cap: &Captures| {
93 let num = cap["num"].parse().unwrap_or_default();
94 superscript(num, SupSub::Sub)
95 });
96
97 content.to_string()
98}
99
100const SUPER_NUM: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'];
101const SUB_NUM: [char; 10] = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'];
102
103pub fn superscript(n: usize, sub_or_sup: SupSub) -> String {
104 let sub_or_sup = match sub_or_sup {
105 SupSub::Sup => SUPER_NUM,
106 SupSub::Sub => SUB_NUM,
107 };
108 match n {
109 0..=9 => sub_or_sup[n].to_string(),
110 mut num => {
111 let mut res = String::with_capacity(2);
113 while num > 0 {
114 res.push(sub_or_sup[num % 10]);
115 num /= 10;
116 }
117 res.chars().rev().collect()
118 },
119 }
120}