0
$\begingroup$

I have a large (>300 page) latex project split across multiple .tex files that I have decided I want to change some notation around in. A minimal working example would be a main file main.tex that reads

\documentclass{book}
\usepackage{amsmath}
\newcommand{\funct}[2]{f \left( #1 , #2 \right)}
\begin{document}
\include{ch1}
\end{document}

with ch1 reading

\chapter{Chapter 1}
words words words $\funct{a}{b}$ words word $\funct  { \sum_{k=1}^\infty \frac{1}{k^2}} {\lim_{n\to \infty} n }$

and so forth. Now, I've decided that I would like to globally reverse the inputs of \funct. Changing main.tex to \newcommand{\funct}[2]{f \left( #2 , #1 \right)} would do the exact right thing, except that this would be really psychedelic and problematic for any future editing. As such, I need to go through and reverse ever instance of this macro being used in the individual tex files, i.e., replace \funct{a}{b} with \funct{b}{a}. The problem is that there are...hundreds?...of instances of this macro being used among the various tex files, not to mention that the individual inputs to this macro are often several lines worth of latex. Basically, going through by hand would be an absolute nightmare and necessitate several days worth of hunting down typos.

As such, I've had the thought of trying to use some of Mathematica's string pattern matching to do this reordering automatically. After making ALL THE BACKUPS, I've gotten as far as:

ch1=Import[<file path for ch1.tex>, "String"]
StringCases[ch1, "\funct{"~~_~~"}{"~~_~~"}"]

Before getting hopelessly stuck. In particular, Mathematica doesn't seem to like all the \ characters, not to mention the issues of inconsistent spacing between braces, nor dealing with matched sets of nested open/close braces (e.g., the second \funct { ....} {...} above).

Any suggestions? Or is this going to become a quagmire, and I would be better off just brewing a pot of coffee and getting busy with the old ctrl-x ctrl-v routine?

$\endgroup$
2
  • 1
    $\begingroup$ Use linux, sed, awk, egrep, or perl, keep versioned copies with GIT, so you can always back-step. I wouldn't use MMA for this. But if you want to learn lots of string function particulars? It'll be a lot of pain. You'll need to brush up on REGEX & back-references for sure, either way. $\endgroup$
    – prog9910
    Commented May 23, 2020 at 0:39
  • 1
    $\begingroup$ PS. I do lots of Vi macros, for such edits, too. Although, a shell script or keeping a record of your bash history lines, also useful. $\endgroup$
    – prog9910
    Commented May 23, 2020 at 0:42

1 Answer 1

4
$\begingroup$

Easiest way in my mind:

ch1=Import[<file path for ch1.tex>, "Text"];
StringReplace[ch1,
 "\\funct{"~~a:Shortest[__]~~"}"~~(ws:(Whitespace|""))~~"{"~~b:Shortest[__]~~"}"/;(
    StringCount[a, "{"]==StringCount[a, "}] &&
      StringCount[b, "{"]==StringCount[b, "}"]
   ):>"\\funct{"<>"b}"<>ws<>"{"<>a<>"}"
 ]

What am I doing here? First I find the shortest instance of a that is between brackets. Then I find the shortest instance of b that's the same. Then I check to make sure that these instances themselves have balanced brackets. Should cover ~90% of cases.

Once I have those, I stitch them back together

Given that I hate LaTeX and its very 1990s syntax (despite using it all the time for my work), I have no idea if \f{a} {b} is valid or not, but I figured it might be and so added that as another case we handle. If it's impossible, you should be able to safely ditch the ws stuff.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.