2

I was thinking that it since the architecture of LaTeX is a collection of pre-processors on top of TeX, that it may be possible that some macros could in theory do some sort of find-and-replace within the arguments of stuff that they receive.

Motivation: We have a lot of math environments. A lot of them can really be unified into one, if one could scan for the presence of certain elements within the input. For example: a sequation environment, that is unnumbered if it doesn't detect a \label macro, a multiline breqn environment if it sees an unbalanced long equation with optional line breaks, and an align without split if it sees multiple patterns of = & or some such.

Question: Is it possible to write such macros/environments, and if it is, how do I do that?

Attempt at a solution: I have a gnawing suspicion that the cleveref package has something interesting. The trouble is that it has lots of reference semantics too, and it might only be possible to look for some things specific to cleveref, that are not as useful for what I want to do.

10
  • You wrote, "We have a lot of math environments. A lot of them can really be unified into one..." What problem are you looking to solve?
    – Mico
    Commented Jan 6, 2021 at 17:58
  • Basically, I want a single equation environment that does the right thing. I want to remove the mental overhead of using breqn, align, aligned, equation, eqnarray, and have the program determine what is best. It's like cleveref for equations. Commented Jan 6, 2021 at 18:01
  • 1
    cleveref is the wrong track. There are tools to scan the input and look for patterns, e.g. in expl3 there is a regex module and imho tex4ht is using it to create mathml from the math. But the main problem is not to scan, but to define good rules--and to avoid that it slows down compilation a lot if you have many rules. Commented Jan 6, 2021 at 18:07
  • 1
    one issue is that your first sentence is essentially wrong. unlike say the C macro pre-processor, latex does not work as a pre-processor, so in the normal processing, tex doesn't have access to the full content of an environment before it starts processing. For your specific question, "just use breqn" is intended to be the answer breqn by design is trying to make these choices automatically. The fact that it doesn't work all the time and you need to manually choose to use align in some cases even if using breqn elsewhere is an indication that automating this choice is likely to be hard Commented Jan 6, 2021 at 19:35
  • 2
    "I want to remove the mental overhead of using breqn, align, aligned, equation, eqnarray, and have the program determine what is best" I think that this is a misguided aim. Firstly the choice between breqn and align is the choice between automatic and manual line breaking. Clearly it is not possible to make that choice automatically. The choice between align and equation is simple: use equation if it is 1 line, arguably align could act as equation if 1 line but that would be a modification to align not via any pre-processor parse. The choice for eqnarray is simple: do not use it. Commented Jan 6, 2021 at 23:34

1 Answer 1

2

etoolbox provides \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>} that allows you to search for <search> within <cmd> and replace it with <replace>. It also allows for branching whether the replacement resulted in <success> or <failure>. I've used this approach below:

enter image description here

\documentclass{article}

\usepackage{environ,etoolbox}
\usepackage{amsmath}

% Generic math display
\NewEnviron{mathenvironment}{%
  % \patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
  \patchcmd{\BODY}
    {\label}% Search for \label
    {\label}% If found, replace with \label
    {% \label is present
      \patchcmd{\BODY}
        {&}% Search for &
        {&}% If found, replace with &
        {% \label and & is present
          \begin{align}
            \BODY
          \end{align}
        }{% \label is present, but & is not
          \begin{equation}
            \BODY
          \end{equation}
        }%
    }
    {% \label is not present
      \[
        \BODY
      \]
    }
}

\begin{document}

\begin{mathenvironment}
  f(x) = a x^2 + b x + c
\end{mathenvironment}

\begin{mathenvironment}
  f(x) = a x^2 + b x + c \label{eqn:quadratic-1}
\end{mathenvironment}

\begin{mathenvironment}
  f(x) &= a_1 x^2 + b_1 x + c_1 \label{eqn:quadratic-2} \\
  g(y) &= a_2 y^2 + b_2 y + c_2 \label{eqn:quadratic-3}
\end{mathenvironment}

\end{document}

The entire body of mathenvironment is captured inside \BODY, then patched to identify elements that exist (or not) and condition accordingly. You can nest these if needed to look at a combination of elements and condition accordingly.

Note that \patchcmd is looking for an explicit match, so won't find anything implicit (like searching for \test, say, where \test is part of the expansion/replacement text for a macro within mathenvironment). So if you have macros that act as replacements for search items it will fail.

If you have numerous cases that you want to search for, with exclusions, it's probably best to use regular expressions to identify the patterns that you want to condition on, rather than nesting content inside \patchcmd. These regular expressions might be handled better using LaTeX3.

2
  • This sounds along the right track of what I was looking for.The etoolbox package lacks regular expression facilities, do you mean to use external pre-processing with regular expressions? Commented Jan 6, 2021 at 20:56
  • @AlexPetrosyan: I'd suggest using regular expressions (supported through LaTeX3) for processing \BODY and condition based on that. I'm not familiar with regular expressions, so I can't help there.
    – Werner
    Commented Jan 6, 2021 at 21:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .