1#[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#[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#[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#[macro_export]
94macro_rules! dbg {
95 ($arg:expr $(,)? ) => {{
96 eprintln!("{}", $crate::format_dbg_location!($arg));
97 $arg
98 }};
99 ($( $arg:expr ),* $(,)? ) => {{
100 eprintln!("{}", $crate::format_dbg_location!($($arg),*));
101 }};
102}
103
104#[macro_export]
105macro_rules! format_dbg {
106 ($arg:expr $(,)? ) => {{
107 $crate::indent!(
108 format!(
109 "{} = {}\n",
110 $crate::color::auto(stringify!(&$arg)),
111 $crate::color::auto(format!("{:#?}", &$arg))))
112
113 }};
114 ($( $arg:expr ),* $(,)? ) => {{
115 [$($crate::format_dbg!($arg)),*].join("\n")
116 }};
117}
118#[macro_export]
119macro_rules! format_dbg_location {
120 ($arg:expr $(,)? ) => {{
121 format!("{}", $crate::color::reset([$crate::location!(begin), $crate::format_dbg!($arg), $crate::location!(end)].join("\n")))
122 }};
123 ($( $arg:expr ),* $(,)? ) => {{
124 [$crate::location!(begin), $($crate::format_dbg!($arg)),*, $crate::location!(end)].join("\n")
125 }};
126}
127
128#[macro_export]
130macro_rules! indent {
131 ($indentation:literal, $obj:expr) => {{
132 format!("{}", $obj)
133 .lines()
134 .map(|line| format!("{}{}", " ".repeat($indentation), line))
135 .collect::<Vec<String>>()
136 .join("\n")
137 }};
138 ($obj:expr) => {{
139 $crate::indent!(4, $obj)
140 }};
141}
142#[macro_export]
144macro_rules! indent_objdump {
145 ($indentation:literal, $obj:expr) => {{
146 format!("{:#?}", $obj)
147 .lines()
148 .map(|line| format!("{}{}", " ".repeat($indentation), line))
149 .collect::<Vec<String>>()
150 .join("\n")
151 }};
152 ($obj:expr) => {{
153 $crate::indent_objdump!(4, $obj)
154 }};
155}
156
157#[macro_export]
159macro_rules! function_name {
160 () => {{
161 fn f() {}
162 fn type_name_of<T>(_: T) -> &'static str {
163 std::any::type_name::<T>()
164 }
165 let name = type_name_of(f);
166 let name = name
167 .strip_suffix("::f")
168 .unwrap()
169 .replace(format!("{}::", module_path!()).as_str(), "");
170 name
171 }};
172}
173
174#[macro_export]
176macro_rules! step {
177 ($text:expr $(,)?) => {{
178 $crate::step!(length=$crate::color::term_cols(), $text)
179 }};
180 (fg=$fg:expr, $text:expr $(,)?) => {{
181 $crate::step!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $text)
182 }};
183 (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
184 $crate::step!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $text)
185 }};
186 (length=$length:expr, $text:expr $(,)?) => {{
187 let (bg, fg) = $crate::color::couple(line!() as usize);
188 let text = $text.to_string();
189 let bar = $crate::color::ansi(
190 " ".repeat($length),
191 fg.into(),
192 bg.into(),
193 );
194 eprintln!(
195 "\n{}",
196 [
197 bar.clone(),
198 $crate::color::ansi(
199 $crate::color::pad_columns(
200 [
201 $crate::function_name!(),
202 [
203 file!().to_string(),
204 line!().to_string(),
205 ].join(":")
206 ].join(" ").to_string()
207 ),
208 fg.into(),
209 bg.into(),
210 ),
211 $crate::color::ansi(
212 $crate::color::pad_columns(
213 if text.is_empty() { String::new() } else { format!("{}", text) }
214 ),
215 bg.into(),
216 fg.into(),
217 ),
218 bar.clone(),
219 ].join("\n")
220 );
221
222 }};
223 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
224 let text = $text.to_string();
225 let bar = $crate::color::ansi(
226 " ".repeat($length),
227 $fg as usize,
228 $bg as usize,
229 );
230 eprintln!(
231 "\n{}",
232 [
233 bar.clone(),
234 $crate::color::ansi(
235 $crate::color::pad_columns(
236 [
237 $crate::function_name!(),
238 [
239 file!().to_string(),
240 line!().to_string(),
241 ].join(":")
242 ].join(" ").to_string()
243 ),
244 $fg as usize,
245 $bg as usize,
246 ),
247 $crate::color::ansi(
248 $crate::color::pad_columns(
249 if text.is_empty() { String::new() } else { format!("{}", text) }
250 ),
251 $bg as usize,
252 $fg as usize,
253 ),
254 bar.clone(),
255 ].join("\n")
256 );
257 }};
258 (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
259 $crate::step!(length=$length, format_args!($text, $($arg,)*))
260 }};
261 () => {{
262 $crate::step!("")
263 }};
264}
265
266#[macro_export]
268macro_rules! admonition {
269 ($color:literal, $message:expr) => {
270 $crate::admonition!($color, "{}", $message);
271 };
272 ($color:literal, $title:literal, $message:expr) => {
273 $crate::admonition!($color, title=$title, $message);
274 };
275
276 ($color:literal, title=$title:literal, $message:expr) => {
277 $crate::admonition!($color, title=$title, "{}", $message);
278 };
279 ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
280 use crate::color;
281 eprintln!(
282 "\n{}",
283 [
284 color::ansi(
285 format!("{}:{} {}", crate::function_name!(), line!(), $title),
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 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
299 use crate::color;
300 eprintln!(
301 "\n{}",
302 [
303 color::ansi(
304 format!("{}:{}", crate::function_name!(), line!()),
305 color::invert_bw($color).into(),
306 $color,
307 ),
308 color::ansi(
309 format!($format, $($arg),*),
310 $color,
311 color::invert_bw($color).into(),
312 )
313 ]
314 .join(" ")
315 );
316 }};
317}
318
319#[macro_export]
321macro_rules! warn {
322 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
323 $crate::admonition!($color, title="WARNING", $format, $($arg),*);
324 };
325 ($color:literal, $message:expr) => {
326 $crate::admonition!($color, title="WARNING", $message);
327 };
328 ($message:expr) => {
329 $crate::warn!(220, $message);
330 };
331}
332
333#[macro_export]
335macro_rules! info {
336 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
337 $crate::admonition!($color, title="INFO", $format, $($arg),*);
338 };
339 ($color:literal, $message:expr) => {
340 $crate::admonition!($color, title="INFO", $message);
341 };
342 ($message:expr) => {
343 $crate::info!(74, $message);
344 };
345}
346
347#[macro_export]
349macro_rules! format_byte {
350 ($byte:expr $(,)? ) => {{
351 use $crate::color::{auto, fore, from_bytes, pad};
352 let color = $crate::color::from_bytes(&[$byte]);
353 [
354 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
355 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
356 $crate::color::fore(format!("{:#?}", $byte), color.into()),
357 if $byte < 127 {
358 $crate::color::fore(
359 format!("{:#?}", char::from($byte).to_string()),
360 color.into(),
361 )
362 } else {
363 String::new()
364 },
365 ]
366 .iter()
367 .filter(|c| !c.is_empty())
368 .map(String::from)
369 .collect::<Vec<String>>()
370 .join(" => ")
371 }};
372}
373#[macro_export]
375macro_rules! dbg_byte {
376 ($byte:expr $(,)? ) => {{
377 use $crate::color::{auto, fore, from_display};
378 let color = $crate::color::from_display($byte);
379 eprintln!(
380 "\n{} = {}",
381 $crate::color::auto(stringify!($byte)),
382 [$crate::format_byte!($byte), $crate::location!(),].join("\t"),
383 );
384 $byte
385 }};
386}
387
388#[macro_export]
390macro_rules! dbg_bytes {
391 ($slice:expr $(,)? ) => {{
392 use $crate::color::{auto, back, fore, from_display, pad};
393 use $crate::indent;
394 eprintln!(
395 "\n{} = {}",
396 $crate::color::auto(stringify!($slice)),
397 [$crate::format_bytes!($slice), $crate::location!(),].join(" => ")
398 );
399 $slice
400 }};
401}
402#[macro_export]
404macro_rules! format_bytes {
405 ($slice:expr $(,)? ) => {
406 $crate::format_bytes!($slice, " => ");
407 };
408 ($slice:expr, $sep:literal $(,)? ) => {{
409 [
410 format!(
411 "[\n{}]",
412 $slice
413 .iter()
414 .map(Clone::clone)
415 .map(|byte| format!(
416 "{}, // {}\n",
417 $crate::indent!($crate::format_byte!(byte)),
418 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
419 ))
420 .collect::<Vec<String>>()
421 .join("")
422 ),
423 std::str::from_utf8($slice)
424 .map(|s| format!("{s:#?}"))
425 .unwrap_or_default(),
426 ]
427 .iter()
428 .filter(|c| !c.is_empty())
429 .map(String::from)
430 .collect::<Vec<String>>()
431 .join($sep.to_string().as_str())
432 }};
433}