debug_et_diagnostics/
macros.rs

1/// colofully prints the "location" of the macro call (function name, filename and line number) in the code
2#[macro_export]
3macro_rules! location {
4    () => {{
5        let location = format!(
6            "{}{}{}:{}",
7            $crate::color::auto($crate::function_name!()),
8            $crate::color::fore(" @ ", 220),
9            $crate::filename!(),
10            $crate::color::auto(line!().to_string())
11        );
12        location
13    }};
14    (begin) => {
15        $crate::tag!([
16            $crate::color::auto(format!("in function")),
17            $crate::location!()
18        ]
19        .join(" "))
20    };
21    (end) => {
22        $crate::tag!([
23            $crate::color::auto(format!("from function")),
24            $crate::location!()
25        ]
26        .join(" "))
27    };
28    (unexpected) => {
29        [
30            $crate::color::fore(format!("<unexpected branch in function"), 160),
31            $crate::location!(),
32            $crate::color::fore(format!(">"), 160),
33        ]
34        .join(" ")
35    };
36}
37/// colofully prints the filename of the macro call
38#[macro_export]
39macro_rules! filename {
40    () => {{
41        let mut parts = file!()
42            .split(std::path::MAIN_SEPARATOR_STR)
43            .map(String::from)
44            .map(|part| $crate::color::auto(part.to_string()))
45            .collect::<Vec<String>>();
46        let (folder, filename) = if parts.len() > 1 {
47            let last = parts.remove(parts.len() - 1);
48            let parts = parts.iter().map(Clone::clone).collect::<Vec<String>>();
49            (parts, last)
50        } else {
51            (Vec::<String>::new(), parts[0].to_string())
52        };
53        if folder.len() > 1 {
54            format!(
55                "{}{}{}",
56                filename,
57                $crate::color::fore(" in ", 7),
58                folder.join(std::path::MAIN_SEPARATOR_STR)
59            )
60        } else {
61            filename
62        }
63    }};
64}
65/// colorfully wraps the given text in "<", ">": "<{text}>"
66#[macro_export]
67macro_rules! tag {
68    ($arg:expr) => {{
69        $crate::tag!($arg, 7)
70    }};
71    (close, $arg:expr) => {{
72        $crate::tag!(close, $arg, 7)
73    }};
74    ($arg:expr, $color:literal) => {{
75        format!(
76            "{}{}{}",
77            $crate::color::fore("<", $color),
78            $crate::color::auto($arg),
79            $crate::color::fore(">", $color),
80        )
81    }};
82    (close, $arg:expr, $color:literal) => {{
83        format!(
84            "{}{}{}",
85            $crate::color::fore("</", $color),
86            $arg,
87            $crate::color::fore(">", $color),
88        )
89    }};
90}
91
92/// colorful alternative to [std::dbg]
93#[macro_export]
94macro_rules! dbg {
95    ($arg:expr $(,)? ) => {{
96        let obj = format!("{}", [$(
97            $crate::indent!(format!("{} = {}", $crate::color::auto(stringify!($arg)), $crate::color::auto(format!("{:#?}", &$arg)))),
98        )*].iter().map($crate::color::reset).collect::<Vec<String>>().join("\n"));
99        eprintln!("{}", $crate::color::reset([$crate::location!(begin), obj, $crate::location!(end)].join("\n")));
100        $arg
101    }};
102    ($( $arg:expr ),* $(,)? ) => {
103        $($crate::dbg!($arg))*
104    };
105}
106
107/// indents an implementor of [std::fmt::Display]
108#[macro_export]
109macro_rules! indent {
110    ($indentation:literal, $obj:expr) => {{
111        format!("{}", $obj)
112            .lines()
113            .map(|line| format!("{}{}", " ".repeat($indentation), line))
114            .collect::<Vec<String>>()
115            .join("\n")
116    }};
117    ($obj:expr) => {{
118        $crate::indent!(4, $obj)
119    }};
120}
121/// indents an implementor of [std::fmt::Debug]
122#[macro_export]
123macro_rules! indent_objdump {
124    ($indentation:literal, $obj:expr) => {{
125        format!("{:#?}", $obj)
126            .lines()
127            .map(|line| format!("{}{}", " ".repeat($indentation), line))
128            .collect::<Vec<String>>()
129            .join("\n")
130    }};
131    ($obj:expr) => {{
132        $crate::indent_objdump!(4, $obj)
133    }};
134}
135
136/// returns a [String] with the name of the function calling the macro
137#[macro_export]
138macro_rules! function_name {
139    () => {{
140        fn f() {}
141        fn type_name_of<T>(_: T) -> &'static str {
142            std::any::type_name::<T>()
143        }
144        let name = type_name_of(f);
145        let name = name
146            .strip_suffix("::f")
147            .unwrap()
148            .replace(format!("{}::", module_path!()).as_str(), "");
149        name
150    }};
151}
152
153
154/// colorfully steps through code
155#[macro_export]
156macro_rules! step {
157    ($text:expr $(,)?) => {{
158        $crate::step!(length=$crate::color::term_cols(), $text)
159    }};
160    (fg=$fg:expr, $text:expr $(,)?) => {{
161        $crate::step!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $text)
162    }};
163    (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
164        $crate::step!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $text)
165    }};
166    (length=$length:expr, $text:expr $(,)?) => {{
167        let (bg, fg) = $crate::color::couple(line!() as usize);
168        let text = $text.to_string();
169        let bar = $crate::color::ansi(
170            " ".repeat($length),
171            fg.into(),
172            bg.into(),
173        );
174        eprintln!(
175            "\n{}",
176            [
177                bar.clone(),
178                $crate::color::ansi(
179                    $crate::color::pad_columns(
180                        [
181                            $crate::function_name!(),
182                            [
183                                file!().to_string(),
184                                line!().to_string(),
185                            ].join(":")
186                        ].join(" ").to_string()
187                    ),
188                    fg.into(),
189                    bg.into(),
190                ),
191                $crate::color::ansi(
192                    $crate::color::pad_columns(
193                        if text.is_empty() { String::new() } else { format!("{}", text) }
194                    ),
195                    bg.into(),
196                    fg.into(),
197                ),
198                bar.clone(),
199            ].join("\n")
200        );
201
202    }};
203    (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
204        let text = $text.to_string();
205        let bar = $crate::color::ansi(
206            " ".repeat($length),
207            $fg as usize,
208            $bg as usize,
209        );
210        eprintln!(
211            "\n{}",
212            [
213                bar.clone(),
214                $crate::color::ansi(
215                    $crate::color::pad_columns(
216                        [
217                            $crate::function_name!(),
218                            [
219                                file!().to_string(),
220                                line!().to_string(),
221                            ].join(":")
222                        ].join(" ").to_string()
223                    ),
224                    $fg as usize,
225                    $bg as usize,
226                ),
227                $crate::color::ansi(
228                    $crate::color::pad_columns(
229                        if text.is_empty() { String::new() } else { format!("{}", text) }
230                    ),
231                    $bg as usize,
232                    $fg as usize,
233                ),
234                bar.clone(),
235            ].join("\n")
236        );
237    }};
238    (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
239        $crate::step!(length=$length, format_args!($text, $($arg,)*))
240    }};
241    () => {{
242        $crate::step!("")
243    }};
244}
245
246/// colorfully prints an admonition
247#[macro_export]
248macro_rules! admonition {
249    ($color:literal, $message:expr) => {
250        $crate::admonition!($color, "{}", $message);
251    };
252    ($color:literal, $title:literal, $message:expr) => {
253        $crate::admonition!($color, title=$title, $message);
254    };
255
256    ($color:literal, title=$title:literal, $message:expr) => {
257        $crate::admonition!($color, title=$title, "{}", $message);
258    };
259    ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
260        use crate::color;
261        eprintln!(
262            "\n{}",
263            [
264                color::ansi(
265                    format!("{}:{} {}", crate::function_name!(), line!(), $title),
266                    color::invert_bw($color).into(),
267                    $color,
268                ),
269                color::ansi(
270                    format!($format, $($arg),*),
271                    $color,
272                    color::invert_bw($color).into(),
273                )
274            ]
275            .join(" ")
276        );
277    }};
278    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
279        use crate::color;
280        eprintln!(
281            "\n{}",
282            [
283                color::ansi(
284                    format!("{}:{}", crate::function_name!(), line!()),
285                    color::invert_bw($color).into(),
286                    $color,
287                ),
288                color::ansi(
289                    format!($format, $($arg),*),
290                    $color,
291                    color::invert_bw($color).into(),
292                )
293            ]
294            .join(" ")
295        );
296    }};
297}
298
299/// colorfully prints a "WARN" admonition
300#[macro_export]
301macro_rules! warn {
302    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
303        $crate::admonition!($color, title="WARNING", $format, $($arg),*);
304    };
305    ($color:literal, $message:expr) => {
306        $crate::admonition!($color, title="WARNING", $message);
307    };
308    ($message:expr) => {
309        $crate::warn!(220, $message);
310    };
311}
312
313/// colorfully prints an "INFO" admonition
314#[macro_export]
315macro_rules! info {
316    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
317        $crate::admonition!($color, title="INFO", $format, $($arg),*);
318    };
319    ($color:literal, $message:expr) => {
320        $crate::admonition!($color, title="INFO", $message);
321    };
322    ($message:expr) => {
323        $crate::info!(74, $message);
324    };
325}