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
69 (@open, $arg:expr) => {{
70 $crate::tag!(@open, $arg, 7, @color=fore)
71 }};
72 (@open, $arg:expr, @color=auto) => {{
73 $crate::tag!(@open, $arg, 7, @color=auto)
74 }};
75 (@open, $arg:expr, @color=fore) => {{
76 $crate::tag!(@open, $arg, 7, @color=fore)
77 }};
78 (@open, $arg:expr, @color=$color:expr) => {{
79 $crate::tag!(@open, $arg, 7, @color=$color)
80 }};
81
82 (@open, $arg:expr, $color:expr) => {{
83 $crate::tag!(@open, $arg, $color, @color=$color)
84 }};
85 (@open, $arg:expr, $color:expr, @color=auto) => {{
86 let auto_color = $crate::color::from_display($arg) as usize;
87 format!(
88 "{}{}{}",
89 $crate::color::fore("<", $color),
90 $crate::color::fore($arg, auto_color),
91 $crate::color::fore(">", $color),
92 )
93 }};
94 (@open, $arg:expr, $color:expr, @color=fore) => {{
95 format!(
96 "{}{}{}",
97 $crate::color::fore("<", $color),
98 $crate::color::fore($arg, $color),
99 $crate::color::fore(">", $color),
100 )
101 }};
102 (@open, $arg:expr, $color:expr, @color=$fore:expr) => {{
103 format!(
104 "{}{}{}",
105 $crate::color::fore("<", $color),
106 $crate::color::fore($arg, $fore),
107 $crate::color::fore(">", $color),
108 )
109 }};
110
111 (@close, $arg:expr) => {{
112 $crate::tag!(@close, $arg, 7, @color=fore)
113 }};
114 (@close, $arg:expr, @color=auto) => {{
115 $crate::tag!(@close, $arg, 7, @color=auto)
116 }};
117 (@close, $arg:expr, @color=fore) => {{
118 $crate::tag!(@close, $arg, 7, @color=fore)
119 }};
120 (@close, $arg:expr, @color=$color:expr) => {{
121 $crate::tag!(@close, $arg, 7, @color=$color)
122 }};
123
124 (@close, $arg:expr, $color:expr) => {{
125 $crate::tag!(@close, $arg, $color, @color=$color)
126 }};
127 (@close, $arg:expr, $color:expr, @color=auto) => {{
128 let auto_color = $crate::color::from_display($arg) as usize;
129 format!(
130 "{}{}{}",
131 $crate::color::fore("</", $color),
132 $crate::color::fore($arg, auto_color),
133 $crate::color::fore(">", $color),
134 )
135 }};
136 (@close, $arg:expr, $color:expr, @color=fore) => {{
137 format!(
138 "{}{}{}",
139 $crate::color::fore("</", $color),
140 $crate::color::fore($arg, $color),
141 $crate::color::fore(">", $color),
142 )
143 }};
144 (@close, $arg:expr, $color:expr, @color=$fore:expr) => {{
145 format!(
146 "{}{}{}",
147 $crate::color::fore("</", $color),
148 $crate::color::fore($arg, $fore),
149 $crate::color::fore(">", $color),
150 )
151 }};
152
153
154 (@wrap, $tag:expr, $arg:expr) => {{
155 [
156 $crate::tag!(@open, $tag),
157 $crate::indent!($crate::color::fore($arg, 7)),
158 $crate::tag!(@close, $tag),
159 ].join("\n").to_string()
160 }};
161 (@wrap, $tag:expr, $arg:expr, @color=auto) => {{
162 [
163 $crate::tag!(@open, $tag, 7, @color=auto),
164 $crate::indent!($crate::color::auto($arg)),
165 $crate::tag!(@close, $tag, 7, @color=auto),
166 ].join("\n").to_string()
167
168 }};
169 (@wrap, $tag:expr, $arg:expr, @color=fore) => {{
170 [
171 $crate::tag!(@open, $tag, 7, @color=fore),
172 $crate::indent!($crate::color::fore($arg, 7)),
173 $crate::tag!(@close, $tag, 7, @color=fore),
174
175 ].join("\n").to_string()
176 }};
177 (@wrap, $tag:expr, $arg:expr, @color=$color:expr) => {{
178 [
179 $crate::tag!(@open, $arg, $color, @color=$color),
180 $crate::indent!($crate::color::fore($arg, $color)),
181 $crate::tag!(@close, $arg, $color, @color=$color),
182 ].join("\n").to_string()
183 }};
184
185 (@wrap, $tag:expr, $arg:expr, $color:expr) => {{
186 [
187 $crate::tag!(@open, $tag, $color, @color=$color),
188 $crate::indent!($crate::color::fore($arg, $color)),
189 $crate::tag!(@close, $tag, $color, @color=$color),
190 ].join("\n").to_string()
191 }};
192 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=auto) => {{
193 let auto_tag_color = $crate::color::from_display($tag) as usize;
194 let auto_arg_color = $crate::color::from_display($arg) as usize;
195 [
196 $crate::tag!(@open, $tag, $color, @color=auto_tag_color),
197 $crate::indent!($crate::color::fore($arg, auto_arg_color)),
198 $crate::tag!(@close, $tag, $color, @color=auto_tag_color),
199 ].join("\n").to_string()
200 }};
201 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=fore) => {{
202 [
203 $crate::tag!(@open, $tag, $color, @color=fore),
204 $crate::indent!($crate::color::fore($arg, $color)),
205 $crate::tag!(@close, $tag, $color, @color=fore),
206 ].join("\n").to_string()
207 }};
208 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=$fore:expr) => {{
209 [
210 $crate::tag!(@open, $tag, $color, @color=$fore),
211 $crate::indent!($crate::color::fore($arg, $color)),
212 $crate::tag!(@close, $tag, $color, @color=$fore),
213 ].join("\n").to_string()
214 }};
215
216 ($arg:expr) => {{
261 $crate::tag!(@open, $arg, 7)
262 }};
263 ($arg:expr, $color:expr) => {{
264 $crate::tag!(@open, $arg, $color)
265 }};
266 ($arg:expr, @color=auto) => {{
267 $crate::tag!(@open, $arg, 7, @color=auto)
268 }};
269 ($arg:expr, @color=fore) => {{
270 $crate::tag!(@open, $arg, 7, @color=fore)
271 }};
272 ($arg:expr, @color=$fore:expr) => {{
273 $crate::tag!(@open, $arg, 7, @color=$fore)
274 }};
275 ($arg:expr, $color:expr, @color=$fore:expr) => {{
276 $crate::tag!(@open, $arg, $color, @color=$fore)
277 }};
278
279}
280
281#[macro_export]
283macro_rules! dbg {
284 ($arg:expr $(,)? ) => {{
285 eprintln!("{}", $crate::format_dbg_location!($arg));
286 $arg
287 }};
288 ($( $arg:expr ),* $(,)? ) => {{
289 eprintln!("{}", $crate::format_dbg_location!($($arg),*));
290 }};
291}
292
293#[macro_export]
294macro_rules! format_dbg {
295 ($arg:expr $(,)? ) => {{
296 $crate::indent!(
297 format!(
298 "{} = {}\n",
299 $crate::color::auto(stringify!(&$arg)),
300 $crate::color::auto(format!("{:#?}", &$arg))))
301
302 }};
303 ($( $arg:expr ),* $(,)? ) => {{
304 [$($crate::format_dbg!($arg)),*].join("\n")
305 }};
306}
307#[macro_export]
308macro_rules! format_dbg_location {
309 ($arg:expr $(,)? ) => {{
310 format!("{}", $crate::color::reset([$crate::location!(begin), $crate::format_dbg!($arg), $crate::location!(end)].join("\n")))
311 }};
312 ($( $arg:expr ),* $(,)? ) => {{
313 [$crate::location!(begin), $($crate::format_dbg!($arg)),*, $crate::location!(end)].join("\n")
314 }};
315}
316
317#[macro_export]
319macro_rules! indent {
320 ($indentation:literal, $obj:expr) => {{
321 format!("{}", $obj)
322 .lines()
323 .map(|line| format!("{}{}", " ".repeat($indentation), line))
324 .collect::<Vec<String>>()
325 .join("\n")
326 }};
327 ($obj:expr) => {{
328 $crate::indent!(4, $obj)
329 }};
330}
331#[macro_export]
333macro_rules! indent_objdump {
334 ($indentation:literal, $obj:expr) => {{
335 format!("{:#?}", $obj)
336 .lines()
337 .map(|line| format!("{}{}", " ".repeat($indentation), line))
338 .collect::<Vec<String>>()
339 .join("\n")
340 }};
341 ($obj:expr) => {{
342 $crate::indent_objdump!(4, $obj)
343 }};
344}
345
346#[macro_export]
348macro_rules! function_name {
349 () => {{
350 fn f() {}
351 fn type_name_of<T>(_: T) -> &'static str {
352 std::any::type_name::<T>()
353 }
354 let name = type_name_of(f);
355 let name = name
356 .strip_suffix("::f")
357 .unwrap()
358 .replace(format!("{}::", module_path!()).as_str(), "");
359 name
360 }};
361}
362
363#[macro_export]
365macro_rules! step {
366 ($text:expr $(,)?) => {{
367 $crate::step!(length=$crate::color::term_cols(), $text)
368 }};
369 (fg=$fg:expr, $text:expr $(,)?) => {{
370 $crate::step!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $text)
371 }};
372 (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
373 $crate::step!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $text)
374 }};
375 (length=$length:expr, $text:expr $(,)?) => {{
376 let (bg, fg) = $crate::color::couple(line!() as usize);
377 $crate::step!(bg=bg, fg=fg, length=$length, $text)
378 }};
379 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
380 let bg = $crate::color::wrap($bg as usize);
381 let fg = $crate::color::wrap($fg as usize);
382
383 let text = $text.to_string();
384 let bar = $crate::color::ansi(
385 " ".repeat($length),
386 $fg as usize,
387 $bg as usize,
388 );
389 eprintln!(
390 "\n{}",
391 [
392 bar.clone(),
393 $crate::color::ansi(
394 $crate::color::pad_columns(
395 [
396 $crate::function_name!(),
397 [
398 file!().to_string(),
399 line!().to_string(),
400 ].join(":")
401 ].join(" ").to_string()
402 ),
403 $fg as usize,
404 $bg as usize,
405 ),
406 $crate::color::ansi(
407 $crate::color::pad_columns(
408 if text.is_empty() { String::new() } else { format!("{}", text) }
409 ),
410 $bg as usize,
411 $fg as usize,
412 ),
413 bar.clone(),
414 ].join("\n")
415 );
416 }};
417 (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
418 $crate::step!(length=$length, format_args!($text, $($arg,)*))
419 }};
420 () => {{
421 $crate::step!("")
422 }};
423}
424#[macro_export]
426macro_rules! step_dbg {
427 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $($arg:expr),* $(,)?) => {{
428 let text = format!("{}", [
429 $($crate::indent!(format!("{} = {}", $crate::color::auto(stringify!($arg)), $crate::color::auto(format!("{:#?}", $arg))))),*
430 ].join("\n"));
431 $crate::step!(bg=$bg, fg=$fg, length=$length, text);
432 }};
433 (bg=$bg:expr, fg=$fg:expr, $($arg:expr),* $(,)?) => {{
434 $crate::step_dbg!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $($arg),*)
435 }};
436 (fg=$fg:expr, $($arg:expr),* $(,)?) => {{
437 $crate::step_dbg!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $($arg),*)
438 }};
439 ($($arg:expr),* $(,)?) => {{
440 let fg=$crate::color::wrap(line!() as usize);
441 $crate::step_dbg!(bg=fg, fg=$crate::color::invert_bw(fg), length=$crate::color::term_cols(), $($arg),*)
442 }};
443 () => {{
444 $crate::step!("")
445 }};
446}
447
448#[macro_export]
450macro_rules! admonition {
451 ($color:literal, $message:expr) => {
452 $crate::admonition!($color, "{}", $message);
453 };
454 ($color:literal, $title:literal, $message:expr) => {
455 $crate::admonition!($color, title=$title, $message);
456 };
457
458 ($color:literal, title=$title:literal, $message:expr) => {
459 $crate::admonition!($color, title=$title, "{}", $message);
460 };
461 ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
462 use crate::color;
463 eprintln!(
464 "\n{}",
465 [
466 color::ansi(
467 format!("{}:{} {}", crate::function_name!(), line!(), $title),
468 color::invert_bw($color).into(),
469 $color,
470 ),
471 color::ansi(
472 format!($format, $($arg),*),
473 $color,
474 color::invert_bw($color).into(),
475 )
476 ]
477 .join(" ")
478 );
479 }};
480 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
481 use crate::color;
482 eprintln!(
483 "\n{}",
484 [
485 color::ansi(
486 format!("{}:{}", crate::function_name!(), line!()),
487 color::invert_bw($color).into(),
488 $color,
489 ),
490 color::ansi(
491 format!($format, $($arg),*),
492 $color,
493 color::invert_bw($color).into(),
494 )
495 ]
496 .join(" ")
497 );
498 }};
499}
500
501#[macro_export]
503macro_rules! warn {
504 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
505 $crate::admonition!($color, title="WARNING", $format, $($arg),*);
506 };
507 ($color:literal, $message:expr) => {
508 $crate::admonition!($color, title="WARNING", $message);
509 };
510 ($message:expr) => {
511 $crate::warn!(220, $message);
512 };
513}
514
515#[macro_export]
517macro_rules! info {
518 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
519 $crate::admonition!($color, title="INFO", $format, $($arg),*);
520 };
521 ($color:literal, $message:expr) => {
522 $crate::admonition!($color, title="INFO", $message);
523 };
524 ($message:expr) => {
525 $crate::info!(74, $message);
526 };
527}
528
529#[macro_export]
531macro_rules! format_byte {
532 (hex_only, $byte:expr $(,)? ) => {{
533 use $crate::color::{auto, fore, from_byte, pad};
534 let color = $crate::color::from_byte($byte);
535 $crate::color::fore(format!("0x{:02x}", $byte), color.into())
536 }};
537 (hex, $byte:expr $(,)? ) => {{
538 use $crate::color::{auto, fore, from_bytes, pad};
539 let color = $crate::color::from_bytes(&[$byte]);
540 [
541 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
542 if $byte < 127 {
543 $crate::color::fore(
544 format!("{:#?}", char::from($byte).to_string()),
545 color.into(),
546 )
547 } else {
548 String::new()
549 },
550 ]
551 .iter()
552 .filter(|c| !c.is_empty())
553 .map(String::from)
554 .collect::<Vec<String>>()
555 .join(" => ")
556 }};
557 (bin, $byte:expr $(,)? ) => {{
558 use $crate::color::{auto, fore, from_bytes, pad};
559 let color = $crate::color::from_bytes(&[$byte]);
560 [
561 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
562 if $byte < 127 {
563 $crate::color::fore(
564 format!("{:#?}", char::from($byte).to_string()),
565 color.into(),
566 )
567 } else {
568 String::new()
569 },
570 ]
571 .iter()
572 .filter(|c| !c.is_empty())
573 .map(String::from)
574 .collect::<Vec<String>>()
575 .join(" => ")
576 }};
577 ($byte:expr $(,)? ) => {{
578 use $crate::color::{auto, fore, from_bytes, pad};
579 let color = $crate::color::from_bytes(&[$byte]);
580 [
581 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
582 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
583 $crate::color::fore(format!("{:#?}", $byte), color.into()),
584 if $byte < 127 {
585 $crate::color::fore(
586 format!("{:#?}", char::from($byte).to_string()),
587 color.into(),
588 )
589 } else {
590 String::new()
591 },
592 ]
593 .iter()
594 .filter(|c| !c.is_empty())
595 .map(String::from)
596 .collect::<Vec<String>>()
597 .join(" => ")
598 }};
599}
600#[macro_export]
602macro_rules! dbg_byte {
603 ($byte:expr $(,)? ) => {{
604 use $crate::color::{auto, fore, from_display};
605 let color = $crate::color::from_display($byte);
606 $crate::step!(format!(
607 "{} = {}",
608 $crate::color::auto(stringify!($byte)),
609 $crate::format_byte!($byte)
610 ));
611 $byte
612 }};
613}
614
615#[macro_export]
617macro_rules! dbg_bytes {
618 ($slice:expr $(,)? ) => {{
619 use $crate::color::{auto, back, fore, from_display, pad};
620 $crate::step!($crate::indent!(format!(
621 "{} = {}",
622 $crate::color::auto(stringify!($slice)),
623 $crate::format_bytes!($slice)
624 )));
625 $slice
626 }};
627}
628#[macro_export]
630macro_rules! dbg_bytes_str {
631 ($slice:expr $(,)? ) => {{
632 use $crate::color::{auto, back, fore, from_display, pad};
633 use $crate::indent;
634 eprintln!(
635 "\n{}",
636 [
637 $crate::location!(begin),
638 String::new(),
639 $crate::color::auto(stringify!($slice)),
640 $crate::format_bytes_str!($slice),
641 String::new(),
642 $crate::location!(end),
643 ]
644 .join("\n")
645 );
646 $slice
647 }};
648}
649#[macro_export]
651macro_rules! dbg_bytes_if_str {
652 ($slice:expr $(,)? ) => {
653 if let Ok(c) = std::str::from_utf8($slice) {
654 $crate::dbg_bytes!($slice)
655 } else {
656 $slice
657 }
658 };
659}
660#[macro_export]
662macro_rules! format_bytes {
663 ($slice:expr $(,)? ) => {
664 $crate::format_bytes!($slice, " => ");
665 };
666 (hex, $slice:expr $(,)? ) => {
667 $crate::format_bytes!(hex, $slice, " => ");
668 };
669 (bin, $slice:expr $(,)? ) => {
670 $crate::format_bytes!(bin, $slice, " => ");
671 };
672 ($slice:expr, $sep:literal $(,)? ) => {{
673 [
674 format!(
675 "[\n{}]",
676 $slice
677 .iter()
678 .map(Clone::clone)
679 .map(|byte| format!(
680 "{}, // {}\n",
681 $crate::indent!($crate::format_byte!(byte)),
682 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
683 ))
684 .collect::<Vec<String>>()
685 .join("")
686 ),
687 format!("{} bytes", $slice.len()),
688 std::str::from_utf8($slice)
689 .map(|s| {
690 let chars = s.chars().collect::<Vec<char>>();
691 format!(
692 "\"{s}\" => {} chars => [{}]",
693 chars.len(),
694 chars
695 .iter()
696 .map(|c| format!("{c:?}"))
697 .collect::<Vec<String>>()
698 .join(", ")
699 )
700 })
701 .unwrap_or_default(),
702 ]
703 .iter()
704 .filter(|c| !c.is_empty())
705 .map(String::from)
706 .collect::<Vec<String>>()
707 .join($sep.to_string().as_str())
708 }};
709 (hex, $slice:expr, $sep:literal $(,)? ) => {{
710 [
711 format!(
712 "[\n{}]",
713 $slice
714 .iter()
715 .map(Clone::clone)
716 .map(|byte| format!(
717 "{}, // {}\n",
718 $crate::indent!($crate::format_byte!(hex, byte)),
719 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
720 ))
721 .collect::<Vec<String>>()
722 .join("")
723 ),
724 std::str::from_utf8($slice)
725 .map(|s| format!("{s:#?}"))
726 .unwrap_or_default(),
727 ]
728 .iter()
729 .filter(|c| !c.is_empty())
730 .map(String::from)
731 .collect::<Vec<String>>()
732 .join($sep.to_string().as_str())
733 }};
734 (bin, $slice:expr, $sep:literal $(,)? ) => {{
735 [
736 format!(
737 "[\n{}]",
738 $slice
739 .iter()
740 .map(Clone::clone)
741 .map(|byte| format!(
742 "{}, // {}\n",
743 $crate::indent!($crate::format_byte!(bin, byte)),
744 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
745 ))
746 .collect::<Vec<String>>()
747 .join("")
748 ),
749 std::str::from_utf8($slice)
750 .map(|s| format!("{s:#?}"))
751 .unwrap_or_default(),
752 ]
753 .iter()
754 .filter(|c| !c.is_empty())
755 .map(String::from)
756 .collect::<Vec<String>>()
757 .join($sep.to_string().as_str())
758 }};
759}
760
761#[macro_export]
763macro_rules! format_bytes_str {
764 ($slice:expr $(,)? ) => {
765 $crate::format_bytes_str!($slice, " => ");
766 };
767 ($slice:expr, $sep:literal $(,)? ) => {{
768 [
769 format!(
770 "[{}]",
771 $slice
772 .iter()
773 .map(Clone::clone)
774 .map(|byte| $crate::format_byte!(hex_only, byte))
775 .collect::<Vec<String>>()
776 .join(", ")
777 ),
778 std::str::from_utf8($slice)
779 .map(|s| format!("{s:#?}"))
780 .unwrap_or_default(),
781 ]
782 .iter()
783 .filter(|c| !c.is_empty())
784 .map(String::from)
785 .collect::<Vec<String>>()
786 .join($sep.to_string().as_str())
787 }};
788}