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