texlang_stdlib/
tracingmacros.rs

1//! TeX macro debugging
2
3use colored::*;
4use texlang::{command, texmacro, token::write_tokens, traits::*, variable, vm};
5
6/// Component for storing state related to macro tracing.
7#[derive(Default)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Component {
10    tracing_macros: i32,
11}
12
13/// Get the `\tracingmacros` command.
14pub fn get_tracingmacros<S: HasComponent<Component>>() -> command::BuiltIn<S> {
15    variable::Command::new_singleton(
16        |state: &S, _: variable::Index| -> &i32 { &state.component().tracing_macros },
17        |state: &mut S, _: variable::Index| -> &mut i32 {
18            &mut state.component_mut().tracing_macros
19        },
20    )
21    .into()
22}
23
24pub fn hook<S: HasComponent<Component>>(
25    token: texlang::token::Token,
26    input: &vm::ExpansionInput<S>,
27    tex_macro: &texlang::texmacro::Macro,
28    arguments: &[&[texlang::token::Token]],
29    reversed_expansion: &[texlang::token::Token],
30) {
31    if input.state().component().tracing_macros <= 0 {
32        return;
33    }
34    let trace = input.trace(token);
35    println!(
36        "{}{}",
37        "Macro expansion trace of ".bold(),
38        trace.value.bold()
39    );
40    // TODO
41    // println!("{trace}");
42    let interner = input.vm().cs_name_interner();
43    println!["                        ┌──",];
44    print!["              arguments "];
45    if arguments.is_empty() {
46        print!["│ (none)\n                        "];
47    }
48    for (i, argument) in arguments.iter().enumerate() {
49        print![
50            "│ {}{}={} \n                        ",
51            "#".bright_yellow(),
52            (i + 1).to_string().bright_yellow(),
53            write_tokens(*argument, interner).bright_yellow()
54        ]
55    }
56
57    print!["├──\n replacement definition │ ",];
58    for replacement in tex_macro.replacements() {
59        match replacement {
60            texmacro::Replacement::Tokens(tokens) => {
61                print!("{}", write_tokens(tokens.iter().rev(), interner))
62            }
63            texmacro::Replacement::Parameter(i) => {
64                print!(
65                    "{}{}",
66                    "#".bright_yellow(),
67                    (i + 1).to_string().bright_yellow(),
68                )
69            }
70        }
71    }
72
73    println![
74        "\n                        ├──\n              expansion │ {}",
75        write_tokens(reversed_expansion.iter().rev(), interner)
76    ];
77    println!["                        └──"];
78}