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