devela/code/util/
cdbg.rs

1// devela::code::util::cdbg
2//
3//! Custom debug macro.
4//
5
6/// *`c`ustomizable [`dbg!`]* macro.
7///
8/// - By default uses `{:?}` instead of `{:#?}` for formatting.
9/// - By default doesn't show the location (file, line and column).
10/// - It can show the `$n` last components, instead of the full path.
11///
12/// # Examples
13/// ```
14/// # use devela::cdbg;
15/// let a = vec![1, 2, 3];
16///
17/// let _ = cdbg![&a];
18/// let _ = cdbg![@ &a];
19/// let _ = cdbg![0@ &a];
20/// //      ^-- prints: &a = [1, 2, 3]
21/// let _ = cdbg![1@ &a];
22/// //      ^-- prints: [main.rs:6:10] &a = [1, 2, 3]
23/// let _ = cdbg![2@ &a];
24/// //      ^-- prints: [src/main.rs:8:10] &a = [1, 2, 3]
25/// let _ = cdbg![f@ &a];
26/// //      ^-- prints: [/full/path/.../src/main.rs:10:9] &a = [1, 2, 3]
27/// let _ = cdbg![fln@ &a];
28/// //      ^-- prints: [/full/path/.../src/main.rs:12:9]
29/// //                  &a = [1, 2, 3]
30///
31/// // use `#` for pretty-printing:
32/// let _ = cdbg![# &a];
33/// let _ = cdbg![0# &a];    // same as cdbg![# &a]
34/// let _ = cdbg![1# &a];
35/// let _ = cdbg![f # &a];   // same as `dbg!` macro (notice the required whitespace)
36/// let _ = cdbg![fln # &a]; // same as before, but separates the path in a new line
37/// ```
38// Source code is based on Rust std `dbg!` implementation
39#[macro_export]
40#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "std")))]
41#[cfg_attr(cargo_primary_package, doc(hidden))]
42macro_rules! cdbg {
43    // has to be the first arm
44    (
45     // shows no location (pretty-print)                            cdbg![# x];
46     # $v:expr $(,)?) => { match $v { v => { eprintln!("{} = {:#?}", stringify!($v), &v); v } } };
47    (# $($v:expr),+ $(,)?) => { ($($crate::cdbg![# $v]),+,) };
48    (
49     // shows no location                                           cdbg![x];
50     //                                                             cdbg![@ x];
51     $(@)? $v:expr $(,)?) => { match $v { v => { eprintln!("{} = {:?}", stringify!($v), &v); v } } };
52    ($($v:expr),+ $(,)?) => { ($($crate::cdbg![$v]),+,) };
53    (
54
55     // shows the last $n location components                       cdbg![1@ x];
56     // ($n=0 no location, $n=1 just the filename)
57     $n:literal @ $v:expr $(,)?) => {{
58        if $crate::cif!(diff($n, 0)) {
59            let (path, mut new_path) = (std::path::Path::new(file!()), std::path::PathBuf::new());
60            for c in path.components().rev().take($n).collect::<Vec<_>>().into_iter().rev() {
61                new_path.push(c.as_os_str()); }
62            eprint!("[{}:{}:{}] ", new_path.display(), line!(), column!());
63        }
64        $crate::cdbg![$v]
65    }};
66    ($n:literal @ $($v:expr),+ $(,)?) => { ($( $crate::cdbg![$n@ $v] ),+,) };
67    ($n:literal @) => {{
68        let (path, mut new_path) = (std::path::Path::new(file!()), std::path::PathBuf::new());
69        for c in path.components().rev().take($n).collect::<Vec<_>>().into_iter().rev() {
70            new_path.push(c.as_os_str()); }
71        eprintln!("[{}:{}:{}]", new_path.display(), line!(), column!())
72    }};
73    (// (pretty-print)                                              cdbg![1# x];
74     $n:literal # $v:expr $(,)?) => {{
75        if $crate::cif!(diff($n, 0)) {
76            let (path, mut new_path) = (std::path::Path::new(file!()), std::path::PathBuf::new());
77            for c in path.components().rev().take($n).collect::<Vec<_>>().into_iter().rev() {
78                new_path.push(c.as_os_str()); }
79            eprint!("[{}:{}:{}] ", new_path.display(), line!(), column!());
80        }
81        $crate::cdbg![# $v]
82    }};
83    ($n:literal # $($v:expr),+ $(,)?) => { ($( $crate::cdbg![$n # $v] ),+,) };
84    ($n:literal #) => {{
85        let (path, mut new_path) = (std::path::Path::new(file!()), std::path::PathBuf::new());
86        for c in path.components().rev().take($n).collect::<Vec<_>>().into_iter().rev() {
87            new_path.push(c.as_os_str()); }
88        eprintln!("[{}:{}:{}]", new_path.display(), line!(), column!())
89    }};
90    (
91
92     // shows the full path location                                cdbg![f@ x];
93     f @ $v:expr $(,)?) => {{
94        eprint!("[{}:{}:{}] ", file!(), line!(), column!());
95        $crate::cdbg![$v]
96    }};
97    (f @ $($v:expr),+ $(,)?) => { ($($crate::cdbg![f @ $v]),+,) };
98    (f @) => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) };
99    (// (pretty-print) (equivalent to `dbg!`)                       cdbg![f # x];
100     f # $v:expr $(,)?) => {{
101        eprint!("[{}:{}:{}] ", file!(), line!(), column!());
102        $crate::cdbg![# $v]
103    }};
104    (f # $($v:expr),+ $(,)?) => { ($($crate::cdbg![f # $v]),+,) };
105    (f #) => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) };
106    (
107     // shows the full path location in a separate line             cdbg![fln@ x];
108     fln @ $v:expr $(,)?) => {{
109        eprintln!("[{}:{}:{}]", file!(), line!(), column!());
110        $crate::cdbg![$v]
111    }};
112    (fln @ $($v:expr),+ $(,)?) => { ($($crate::cdbg![fln @ $v]),+,) };
113    (fln @) => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) };
114    (// (pretty-print)                                              cdbg![fln # x];
115     fln # $v:expr $(,)?) => {{
116        eprintln!("[{}:{}:{}]", file!(), line!(), column!());
117        $crate::cdbg![# $v]
118    }};
119    (fln # $($v:expr),+ $(,)?) => { ($($crate::cdbg![fln # $v]),+,) };
120    (fln #) => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) };
121    // no-op:
122    () => { () };
123}
124#[doc(inline)]
125pub use cdbg;