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 = $crate::indent!(
97                format!(
98                    "{} = {}\n",
99                    $crate::color::auto(stringify!(&$arg)),
100                    $crate::color::auto(format!("{:#?}", &$arg))));
101        eprintln!("{}", $crate::color::reset([$crate::location!(begin), obj, $crate::location!(end)].join("\n")));
102        $arg
103    }};
104    ($( $arg:expr ),* $(,)? ) => {{
105        $($crate::dbg!($arg))*
106    }};
107}
108
109/// indents an implementor of [std::fmt::Display]
110#[macro_export]
111macro_rules! indent {
112    ($indentation:literal, $obj:expr) => {{
113        format!("{}", $obj)
114            .lines()
115            .map(|line| format!("{}{}", " ".repeat($indentation), line))
116            .collect::<Vec<String>>()
117            .join("\n")
118    }};
119    ($obj:expr) => {{
120        $crate::indent!(4, $obj)
121    }};
122}
123/// indents an implementor of [std::fmt::Debug]
124#[macro_export]
125macro_rules! indent_objdump {
126    ($indentation:literal, $obj:expr) => {{
127        format!("{:#?}", $obj)
128            .lines()
129            .map(|line| format!("{}{}", " ".repeat($indentation), line))
130            .collect::<Vec<String>>()
131            .join("\n")
132    }};
133    ($obj:expr) => {{
134        $crate::indent_objdump!(4, $obj)
135    }};
136}
137
138/// returns a [String] with the name of the function calling the macro
139#[macro_export]
140macro_rules! function_name {
141    () => {{
142        fn f() {}
143        fn type_name_of<T>(_: T) -> &'static str {
144            std::any::type_name::<T>()
145        }
146        let name = type_name_of(f);
147        let name = name
148            .strip_suffix("::f")
149            .unwrap()
150            .replace(format!("{}::", module_path!()).as_str(), "");
151        name
152    }};
153}
154
155/// colorfully steps through code
156#[macro_export]
157macro_rules! step {
158    ($text:expr $(,)?) => {{
159        $crate::step!(length=$crate::color::term_cols(), $text)
160    }};
161    (fg=$fg:expr, $text:expr $(,)?) => {{
162        $crate::step!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $text)
163    }};
164    (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
165        $crate::step!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $text)
166    }};
167    (length=$length:expr, $text:expr $(,)?) => {{
168        let (bg, fg) = $crate::color::couple(line!() as usize);
169        let text = $text.to_string();
170        let bar = $crate::color::ansi(
171            " ".repeat($length),
172            fg.into(),
173            bg.into(),
174        );
175        eprintln!(
176            "\n{}",
177            [
178                bar.clone(),
179                $crate::color::ansi(
180                    $crate::color::pad_columns(
181                        [
182                            $crate::function_name!(),
183                            [
184                                file!().to_string(),
185                                line!().to_string(),
186                            ].join(":")
187                        ].join(" ").to_string()
188                    ),
189                    fg.into(),
190                    bg.into(),
191                ),
192                $crate::color::ansi(
193                    $crate::color::pad_columns(
194                        if text.is_empty() { String::new() } else { format!("{}", text) }
195                    ),
196                    bg.into(),
197                    fg.into(),
198                ),
199                bar.clone(),
200            ].join("\n")
201        );
202
203    }};
204    (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
205        let text = $text.to_string();
206        let bar = $crate::color::ansi(
207            " ".repeat($length),
208            $fg as usize,
209            $bg as usize,
210        );
211        eprintln!(
212            "\n{}",
213            [
214                bar.clone(),
215                $crate::color::ansi(
216                    $crate::color::pad_columns(
217                        [
218                            $crate::function_name!(),
219                            [
220                                file!().to_string(),
221                                line!().to_string(),
222                            ].join(":")
223                        ].join(" ").to_string()
224                    ),
225                    $fg as usize,
226                    $bg as usize,
227                ),
228                $crate::color::ansi(
229                    $crate::color::pad_columns(
230                        if text.is_empty() { String::new() } else { format!("{}", text) }
231                    ),
232                    $bg as usize,
233                    $fg as usize,
234                ),
235                bar.clone(),
236            ].join("\n")
237        );
238    }};
239    (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
240        $crate::step!(length=$length, format_args!($text, $($arg,)*))
241    }};
242    () => {{
243        $crate::step!("")
244    }};
245}
246
247/// colorfully prints an admonition
248#[macro_export]
249macro_rules! admonition {
250    ($color:literal, $message:expr) => {
251        $crate::admonition!($color, "{}", $message);
252    };
253    ($color:literal, $title:literal, $message:expr) => {
254        $crate::admonition!($color, title=$title, $message);
255    };
256
257    ($color:literal, title=$title:literal, $message:expr) => {
258        $crate::admonition!($color, title=$title, "{}", $message);
259    };
260    ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
261        use crate::color;
262        eprintln!(
263            "\n{}",
264            [
265                color::ansi(
266                    format!("{}:{} {}", crate::function_name!(), line!(), $title),
267                    color::invert_bw($color).into(),
268                    $color,
269                ),
270                color::ansi(
271                    format!($format, $($arg),*),
272                    $color,
273                    color::invert_bw($color).into(),
274                )
275            ]
276            .join(" ")
277        );
278    }};
279    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
280        use crate::color;
281        eprintln!(
282            "\n{}",
283            [
284                color::ansi(
285                    format!("{}:{}", crate::function_name!(), line!()),
286                    color::invert_bw($color).into(),
287                    $color,
288                ),
289                color::ansi(
290                    format!($format, $($arg),*),
291                    $color,
292                    color::invert_bw($color).into(),
293                )
294            ]
295            .join(" ")
296        );
297    }};
298}
299
300/// colorfully prints a "WARN" admonition
301#[macro_export]
302macro_rules! warn {
303    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
304        $crate::admonition!($color, title="WARNING", $format, $($arg),*);
305    };
306    ($color:literal, $message:expr) => {
307        $crate::admonition!($color, title="WARNING", $message);
308    };
309    ($message:expr) => {
310        $crate::warn!(220, $message);
311    };
312}
313
314/// colorfully prints an "INFO" admonition
315#[macro_export]
316macro_rules! info {
317    ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
318        $crate::admonition!($color, title="INFO", $format, $($arg),*);
319    };
320    ($color:literal, $message:expr) => {
321        $crate::admonition!($color, title="INFO", $message);
322    };
323    ($message:expr) => {
324        $crate::info!(74, $message);
325    };
326}