7. The -r, -rv and -rr switches

You can instruct latexindent.pl to perform replacements/substitutions on your file by using any of the -r, -rv or -rr switches:

  • the -r switch will perform indentation and replacements, not respecting verbatim code blocks;

  • the -rv switch will perform indentation and replacements, and will respect verbatim code blocks;

  • the -rr switch will not perform indentation, and will perform replacements not respecting verbatim code blocks.

We will demonstrate each of the -r, -rv and -rr switches, but a summary is given in Table 4.

Table 4 The replacement mode switches

switch

indentation?

respect verbatim?

-r

yes

no

-rv

yes

yes

-rr

no

no

The default value of the replacements field is shown in Listing 538; as with all of the other fields, you are encouraged to customise and change this as you see fit. The options in this field will only be considered if the -r, -rv or -rr switches are active; when discussing YAML settings related to the replacement-mode switches, we will use the style given in Listing 538.

Listing 538 replacements
620replacements:
621  -
622    amalgamate: 1
623  -
624    this: latexindent.pl
625    that: pl.latexindent
626    lookForThis: 0
627    when: before
628

The first entry within the replacements field is amalgamate, and is optional; by default it is set to 1, so that replacements will be amalgamated from each settings file that you specify. As you’ll see in the demonstrations that follow, there is no need to specify this field.

You’ll notice that, by default, there is only one entry in the replacements field, but it can take as many entries as you would like; each one needs to begin with a - on its own line.

7.1. Introduction to replacements

Let’s explore the action of the default settings, and then we’ll demonstrate the feature with further examples.

Example 144

Beginning with the code in Listing 539 and running the command

latexindent.pl -r replace1.tex

gives the output given in Listing 540.

Listing 539 replace1.tex
Before text, latexindent.pl,
after text.
Listing 540 replace1.tex default
Before text, latexindent.pl,
after text.

We note that in Listing 538, because lookForThis is set to 0, the specified replacement has not been made, and there is no difference between Listing 539 and Listing 540.

If we do wish to perform this replacement, then we can tweak the default settings of Listing 538 by changing lookForThis to 1; we perform this action in Listing 542, and run the command

latexindent.pl -r replace1.tex -l=replace1.yaml

which gives the output in Listing 541.

Listing 541 replace1.tex using Listing 542
Before text, pl.latexindent,
after text.
Listing 542 replace1.yaml
replacements:
  - 
    amalgamate: 0
  -
    this: latexindent.pl
    that: pl.latexindent
    lookForThis: 1

Note that in Listing 542 we have specified amalgamate as 0 so that the default replacements are overwritten.

We haven’t yet discussed the when field; don’t worry, we’ll get to it as part of the discussion in what follows.

7.2. The two types of replacements

There are two types of replacements:

  1. string-based replacements, which replace the string in this with the string in that. If you specify this and you do not specify that, then the that field will be assumed to be empty.

  2. regex-based replacements, which use the substitution field.

We will demonstrate both in the examples that follow.

latexindent.pl chooses which type of replacement to make based on which fields have been specified; if the this field is specified, then it will make string-based replacements, regardless of if substitution is present or not.

7.3. Examples of replacements

Example 145

We begin with code given in Listing 543

Listing 543 colsep.tex
\begin{env}
1 2 3\arraycolsep=3pt
4 5 6\arraycolsep=5pt
\end{env}

Let’s assume that our goal is to remove both of the arraycolsep statements; we can achieve this in a few different ways.

Using the YAML in Listing 545, and running the command

latexindent.pl -r colsep.tex -l=colsep.yaml

then we achieve the output in Listing 544.

Listing 544 colsep.tex using Listing 543
\begin{env}
	1 2 3
	4 5 6
\end{env}
Listing 545 colsep.yaml
replacements:
  -
    this: \arraycolsep=3pt
  -
    this: \arraycolsep=5pt

Note that in Listing 545, we have specified two separate fields, each with their own ‘this’ field; furthermore, for both of the separate fields, we have not specified ‘that’, so the that field is assumed to be blank by latexindent.pl;

We can make the YAML in Listing 545 more concise by exploring the substitution field. Using the settings in Listing 547 and running the command

latexindent.pl -r colsep.tex -l=colsep1.yaml

then we achieve the output in Listing 546.

Listing 546 colsep.tex using Listing 547
\begin{env}
	1 2 3
	4 5 6
\end{env}
Listing 547 colsep1.yaml
replacements:
  -
    substitution: s/\\arraycolsep=\d+pt//sg

The code given in Listing 547 is an example of a regular expression, which we may abbreviate to regex in what follows. This manual is not intended to be a tutorial on regular expressions; you might like to read, for example, (Friedl, n.d.) for a detailed covering of the topic. With reference to Listing 547, we do note the following:

  • the general form of the substitution field is s/regex/replacement/modifiers. You can place any regular expression you like within this;

  • we have ‘escaped’ the backslash by using \\

  • we have used \d+ to represent at least one digit

  • the s modifier (in the sg at the end of the line) instructs latexindent.pl to treat your file as one single line;

  • the g modifier (in the sg at the end of the line) instructs latexindent.pl to make the substitution globally throughout your file; you might try removing the g modifier from Listing 547 and observing the difference in output.

You might like to see https://perldoc.perl.org/perlre.html#Modifiers for details of modifiers; in general, I recommend starting with the sg modifiers for this feature.

Example 146

We’ll keep working with the file in Listing 543 for this example.

Using the YAML in Listing 549, and running the command

latexindent.pl -r colsep.tex -l=multi-line.yaml

then we achieve the output in Listing 548.

Listing 548 colsep.tex using Listing 549
multi-line!
Listing 549 multi-line.yaml
replacements:
  -
    this: |-
     \begin{env}
     1 2 3\arraycolsep=3pt
     4 5 6\arraycolsep=5pt
     \end{env}
    that: 'multi-line!'

With reference to Listing 549, we have specified a multi-line version of this by employing the literal YAML style |-. See, for example, https://stackoverflow.com/questions/3790454/in-yaml-how-do-i-break-a-string-over-multiple-lines for further options, all of which can be used in your YAML file.

This is a natural point to explore the when field, specified in Listing 538. This field can take two values: before and after, which respectively instruct latexindent.pl to perform the replacements before indentation or after it. The default value is before.

Using the YAML in Listing 551, and running the command

latexindent.pl -r colsep.tex -l=multi-line1.yaml

then we achieve the output in Listing 550.

Listing 550 colsep.tex using Listing 551
\begin{env}
	1 2 3\arraycolsep=3pt
	4 5 6\arraycolsep=5pt
\end{env}
Listing 551 multi-line1.yaml
replacements:
  -
    this: |-
     \begin{env}
     1 2 3\arraycolsep=3pt
     4 5 6\arraycolsep=5pt
     \end{env}
    that: 'multi-line!'
    when: after

We note that, because we have specified when: after, that latexindent.pl has not found the string specified in Listing 551 within the file in Listing 543. As it has looked for the string within Listing 551 after the indentation has been performed. After indentation, the string as written in Listing 551 is no longer part of the file, and has therefore not been replaced.

As a final note on this example, if you use the -rr switch, as follows,

latexindent.pl -rr colsep.tex -l=multi-line1.yaml

then the when field is ignored, no indentation is done, and the output is as in Listing 548.

Example 147

An important part of the substitution routine is in capture groups.

Assuming that we start with the code in Listing 552, let’s assume that our goal is to replace each occurrence of $$...$$ with \begin{equation*}...\end{equation*}. This example is partly motivated by tex stackexchange question 242150.

Listing 552 displaymath.tex
before text $$a^2+b^2=4$$ and $$c^2$$

$$
d^2+e^2 = f^2
$$
and also $$ g^2
$$ and some inline math: $h^2$

We use the settings in Listing 554 and run the command

latexindent.pl -r displaymath.tex -l=displaymath1.yaml

to receive the output given in Listing 553.

Listing 553 displaymath.tex using Listing 554
before text \begin{equation*}a^2+b^2=4\end{equation*} and \begin{equation*}c^2\end{equation*}

\begin{equation*}
	d^2+e^2 = f^2
\end{equation*}
and also \begin{equation*} g^2
\end{equation*} and some inline math: $h^2$
Listing 554 displaymath1.yaml
replacements:
  -
    substitution: |-
     s/\$\$
       (.*?)
       \$\$/\\begin{equation*}$1\\end{equation*}/sgx

A few notes about Listing 554:

  1. we have used the x modifier, which allows us to have white space within the regex;

  2. we have used a capture group, (.*?) which captures the content between the $$...$$ into the special variable, $1;

  3. we have used the content of the capture group, $1, in the replacement text.

See https://perldoc.perl.org/perlre.html#Capture-groups for a discussion of capture groups.

The features of the replacement switches can, of course, be combined with others from the toolkit of latexindent.pl. For example, we can combine the poly-switches of Section 6.3, which we do in Listing 556; upon running the command

latexindent.pl -r -m displaymath.tex -l=displaymath1.yaml,equation.yaml

then we receive the output in Listing 555.

Listing 555 displaymath.tex using Listing 554 and Listing 556
before text%
\begin{equation*}%
	a^2+b^2=4%
\end{equation*}%
and%
\begin{equation*}%
	c^2%
\end{equation*}

\begin{equation*}
	d^2+e^2 = f^2
\end{equation*}
and also%
\begin{equation*}%
	g^2
\end{equation*}%
and some inline math: $h^2$
Listing 556 equation.yaml
modifyLineBreaks:
    environments:
        equation*:
            BeginStartsOnOwnLine: 2
            BodyStartsOnOwnLine: 2
            EndStartsOnOwnLine: 2
            EndFinishesWithLineBreak: 2
        
Example 148

This example is motivated by tex stackexchange question 490086. We begin with the code in Listing 557.

Listing 557 phrase.tex
phrase 1       phrase 2 phrase 3             phrase 100

phrase 1       phrase 2 phrase 3             phrase 100

phrase 1       phrase 2 phrase 3             phrase 100

phrase 1       phrase 2 phrase 3             phrase 100

Our goal is to make the spacing uniform between the phrases. To achieve this, we employ the settings in Listing 559, and run the command

latexindent.pl -r phrase.tex -l=hspace.yaml

which gives the output in Listing 558.

Listing 558 phrase.tex using Listing 559
phrase 1 phrase 2 phrase 3 phrase 100

phrase 1 phrase 2 phrase 3 phrase 100

phrase 1 phrase 2 phrase 3 phrase 100

phrase 1 phrase 2 phrase 3 phrase 100

Listing 559 hspace.yaml
replacements:
  -
    substitution: s/\h+/ /sg

The \h+ setting in Listing 559 say to replace at least one horizontal space with a single space.

Example 149

We begin with the code in Listing 560.

Listing 560 references.tex
equation \eqref{eq:aa} and Figure  \ref{fig:bb}
and table~\ref{tab:cc}

Our goal is to change each reference so that both the text and the reference are contained within one hyperlink. We achieve this by employing Listing 562 and running the command

latexindent.pl -r references.tex -l=reference.yaml

which gives the output in Listing 561.

Listing 561 references.tex using Listing 562
\hyperref{equation \ref*{eq:aa}} and \hyperref{Figure \ref*{fig:bb}}
and \hyperref{table \ref*{tab:cc}}
Listing 562 reference.yaml
replacements:
  -
    substitution: |-
      s/(
        equation
        |
        table
        |
        figure
        |
        section
      )
      (\h|~)*
      \\(?:eq)?
      ref\{(.*?)\}/\\hyperref{$1 \\ref\*{$3}}/sgxi

Referencing Listing 562, the | means or, we have used capture groups, together with an example of an optional pattern, (?:eq)?.

Example 150

Let’s explore the three replacement mode switches (see Table 4) in the context of an example that contains a verbatim code block, Listing 563; we will use the settings in Listing 564.

Listing 563 verb1.tex
\begin{myenv}
body of verbatim
\end{myenv}
some verbatim
\begin{verbatim}
    body
        of
      verbatim
 text
\end{verbatim}
text
Listing 564 verbatim1.yaml
replacements:
  -
    this: 'body'
    that: 'head'

Upon running the following commands,

latexindent.pl -r verb1.tex -l=verbatim1.yaml -o=+mod1
latexindent.pl -rv verb1.tex -l=verbatim1.yaml -o=+-rv-mod1
latexindent.pl -rr verb1.tex -l=verbatim1.yaml -o=+-rr-mod1

we receive the respective output in Listing 565Listing 567

Listing 565 verb1-mod1.tex
\begin{myenv}
	head of verbatim
\end{myenv}
some verbatim
\begin{verbatim}
    head
        of
      verbatim
 text
\end{verbatim}
text
Listing 566 verb1-rv-mod1.tex
\begin{myenv}
	head of verbatim
\end{myenv}
some verbatim
\begin{verbatim}
    body
        of
      verbatim
 text
\end{verbatim}
text
Listing 567 verb1-rr-mod1.tex
\begin{myenv}
head of verbatim
\end{myenv}
some verbatim
\begin{verbatim}
    head
        of
      verbatim
 text
\end{verbatim}
text

We note that:

  1. in Listing 565 indentation has been performed, and that the replacements specified in Listing 564 have been performed, even within the verbatim code block;

  2. in Listing 566 indentation has been performed, but that the replacements have not been performed within the verbatim environment, because the rv switch is active;

  3. in Listing 567 indentation has not been performed, but that replacements have been performed, not respecting the verbatim code block.

See the summary within Table 4.

Example 151

Let’s explore the amalgamate field from Listing 538 in the context of the file specified in Listing 568.

Listing 568 amalg1.tex
one two three

Let’s consider the YAML files given in Listing 569Listing 571.

Listing 569 amalg1-yaml.yaml
replacements:
  -
    this: one
    that: 1
Listing 570 amalg2-yaml.yaml
replacements:
  -
    this: two
    that: 2
Listing 571 amalg3-yaml.yaml
replacements:
  - 
    amalgamate: 0
  -
    this: three
    that: 3

Upon running the following commands,

latexindent.pl -r amalg1.tex -l=amalg1-yaml
latexindent.pl -r amalg1.tex -l=amalg1-yaml,amalg2-yaml
latexindent.pl -r amalg1.tex -l=amalg1-yaml,amalg2-yaml,amalg3-yaml

we receive the respective output in Listing 572Listing 574.

Listing 572 amalg1.tex using Listing 569
1 two three
Listing 573 amalg1.tex using Listing 569 and Listing 570
1 2 three
Listing 574 amalg1.tex using Listing 569 and Listing 570 and Listing 571
one two 3

We note that:

  1. in Listing 572 the replacements from Listing 569 have been used;

  2. in Listing 573 the replacements from Listing 569 and Listing 570 have both been used, because the default value of amalgamate is 1;

  3. in Listing 574 only the replacements from Listing 571 have been used, because the value of amalgamate has been set to 0.

Friedl, Jeffrey E. F. n.d. Mastering Regular Expressions.