5. defaultSettings.yaml

latexindent.pl loads its settings from defaultSettings.yaml. The idea is to separate the behaviour of the script from the internal working – this is very similar to the way that we separate content from form when writing our documents in LaTeX.

If you look in defaultSettings.yaml you’ll find the switches that govern the behaviour of latexindent.pl. If you’re not sure where defaultSettings.yaml resides on your computer, don’t worry as indent.log will tell you where to find it. defaultSettings.yaml is commented, but here is a description of what each switch is designed to do. The default value is given in each case; whenever you see integer in this section, assume that it must be greater than or equal to 0 unless otherwise stated.

fileExtensionPreference: fields

latexindent.pl can be called to act on a file without specifying the file extension. For example we can call

latexindent.pl myfile

in

Listing 15 fileExtensionPreference
38
39
40
41
42
fileExtensionPreference:
    .tex: 1
    .sty: 2
    .cls: 3
    .bib: 4

which case the script will look for myfile with the extensions specified in fileExtensionPreference in their numeric order. If no match is found, the script will exit. As with all of the fields, you should change and/or add to this as necessary.

Calling latexindent.pl myfile with the (default) settings specified in Listing 15 means that the script will first look for myfile.tex, then myfile.sty, myfile.cls, and finally myfile.bib in order [1].

backupExtension: extension name

If you call latexindent.pl with the -w switch (to overwrite myfile.tex) then it will create a backup file before doing any indentation; the default extension is .bak, so, for example, myfile.bak0 would be created when calling latexindent.pl myfile.tex for the first time.

By default, every time you subsequently call latexindent.pl with the -w to act upon myfile.tex, it will create successive back up files: myfile.bak1, myfile.bak2, etc.

onlyOneBackUp: integer

If you don’t want a backup for every time that you call latexindent.pl (so you don’t want myfile.bak1, myfile.bak2, etc) and you simply want myfile.bak (or whatever you chose backupExtension to be) then change onlyOneBackUp to 1; the default value of onlyOneBackUp is 0.

maxNumberOfBackUps: integer

Some users may only want a finite number of backup files, say at most \(3\), in which case, they can change this switch. The smallest value of maxNumberOfBackUps is \(0\) which will not prevent backup files being made; in this case, the behaviour will be dictated entirely by onlyOneBackUp. The default value of maxNumberOfBackUps is 0.

cycleThroughBackUps: integer

Some users may wish to cycle through backup files, by deleting the oldest backup file and keeping only the most recent; for example, with maxNumberOfBackUps: 4, and cycleThroughBackUps set to 1 then the copy procedure given below would be obeyed.

copy myfile.bak1 to myfile.bak0
copy myfile.bak2 to myfile.bak1
copy myfile.bak3 to myfile.bak2
copy myfile.bak4 to myfile.bak3

The default value of cycleThroughBackUps is 0.

logFilePreferences: fields

latexindent.pl writes information to indent.log, some of which can be customized by changing logFilePreferences; see Listing 16. If you load your own user settings (see Section 4) then latexindent.pl will detail them in indent.log; you can choose not to have the details logged by switching showEveryYamlRead to 0. Once all of your settings have been loaded, you can see the amalgamated settings in the log file by switching showAmalgamatedSettings to 1, if you wish.

Listing 16 logFilePreferences
79
80
81
82
83
84
85
86
87
88
89
logFilePreferences:
    showEveryYamlRead: 1
    showAmalgamatedSettings: 0
    showDecorationStartCodeBlockTrace: 0
    showDecorationFinishCodeBlockTrace: 0
    endLogFileWith: '--------------' 
    showGitHubInfoFooter: 1
    PatternLayout:
        default: "%A%n"
        trace: "%A%n"
        ttrace: "%A%n"

When either of the trace modes (see ) are active, you will receive detailed information in indent.log. You can specify character strings to appear before and after the notification of a found code block using, respectively, showDecorationStartCodeBlockTrace and showDecorationFinishCodeBlockTrace. A demonstration is given in Section 9.3.

The log file will end with the characters given in endLogFileWith, and will report the GitHub address of latexindent.pl to the log file if showGitHubInfoFooter is set to 1.

latexindent.pl uses the log4perl module (“Log4perl Perl Module” 2017) to handle the creation of the logfile. You can specify the layout of the information given in the logfile using any of the Log Layouts detailed at (“Log4perl Perl Module” 2017).

verbatimEnvironments: fields

A field that contains a list of environments that you would like left completely alone – no indentation will be performed on environments that you have specified in this field, see Listing 17.

Listing 17 verbatimEnvironments
93
94
95
96
verbatimEnvironments:
    verbatim: 1
    lstlisting: 1
    minted: 1
Listing 18 verbatimCommands
 99
100
101
verbatimCommands:
    verb: 1
    lstinline: 1

Note that if you put an environment in verbatimEnvironments and in other fields such as lookForAlignDelims or noAdditionalIndent then latexindent.pl will always prioritize verbatimEnvironments.

verbatimCommands: fields

A field that contains a list of commands that are verbatim commands, for example \verb; any commands populated in this field are protected from line breaking routines (only relevant if the -m is active, see Section 6).

noIndentBlock: fields

Listing 19 noIndentBlock
107
108
109
noIndentBlock:
    noindent: 1
    cmhtest: 1

If you have a block of code that you don’t want latexindent.pl to touch (even if it is not a verbatim-like environment) then you can wrap it in an environment from noIndentBlock; you can use any name you like for this, provided you populate it as demonstrate in Listing 19.

Of course, you don’t want to have to specify these as null environments in your code, so you use them with a comment symbol, %, followed by as many spaces (possibly none) as you like; see Listing 20 for example.

Listing 20 noIndentBlock demonstration
 %(*@@*) \begin{noindent}
         this code
                 won't
      be touched
                     by
              latexindent.pl!
 %(*@@*)\end{noindent}

removeTrailingWhitespace: fields

Listing 21 removeTrailingWhitespace
112
113
114
removeTrailingWhitespace:
    beforeProcessing: 0
    afterProcessing: 1
Listing 22 removeTrailingWhitespace (alt)
 removeTrailingWhitespace: 1

Trailing white space can be removed both before and after processing the document, as detailed in Listing 21; each of the fields can take the values 0 or 1. See Listing 297 and Listing 298 and Listing 299 for before and after results. Thanks to Voßkuhle (2013) for providing this feature.

You can specify removeTrailingWhitespace simply as 0 or 1, if you wish; in this case, latexindent.pl will set both beforeProcessing and afterProcessing to the value you specify; see Listing 22. fileContentsEnvironments: field

Listing 23 fileContentsEnvironments
118
119
120
fileContentsEnvironments:
    filecontents: 1
    filecontents*: 1

Before latexindent.pl determines the difference between preamble (if any) and the main document, it first searches for any of the environments specified in fileContentsEnvironments, see Listing 23. The behaviour of latexindent.pl on these environments is determined by their location (preamble or not), and the value indentPreamble, discussed next.

indentPreamble: 0|1

The preamble of a document can sometimes contain some trickier code for latexindent.pl to operate upon. By default, latexindent.pl won’t try to operate on the preamble (as indentPreamble is set to 0, by default), but if you’d like latexindent.pl to try then change indentPreamble to 1.

lookForPreamble: fields

Listing 24 lookForPreamble
126
127
128
129
130
lookForPreamble:
    .tex: 1
    .sty: 0
    .cls: 0
    .bib: 0

Not all files contain preamble; for example, sty, cls and bib files typically do not. Referencing Listing 24, if you set, for example, .tex to 0, then regardless of the setting of the value of indentPreamble, preamble will not be assumed when operating upon .tex files. preambleCommandsBeforeEnvironments: 0|1

Assuming that latexindent.pl is asked to operate upon the preamble of a document, when this switch is set to 0 then environment code blocks will be sought first, and then command code blocks. When this switch is set to 1, commands will be sought first. The example that first motivated this switch contained the code given in Listing 25.

Listing 25 Motivating preambleCommandsBeforeEnvironments
 ...
 preheadhook={\begin{mdframed}[style=myframedstyle]},
 postfoothook=\end{mdframed},
 ...

defaultIndent: horizontal space

This is the default indentation (\t means a tab, and is the default value) used in the absence of other details for the command or environment we are working with; see indentRules in Section 5.2 for more details.

If you’re interested in experimenting with latexindent.pl then you can remove all indentation by setting defaultIndent: "".

lookForAlignDelims: fields

Listing 26 lookForAlignDelims (basic)
 lookForAlignDelims:
    tabular: 1
    tabularx: 1
    longtable: 1
    array: 1
    matrix: 1
    ...

This contains a list of environments and/or commands that are operated upon in a special way by latexindent.pl (see Listing 26). In fact, the fields in lookForAlignDelims can actually take two different forms: the basic version is shown in Listing 26 and the advanced version in Listing 29; we will discuss each in turn.

The environments specified in this field will be operated on in a special way by latexindent.pl. In particular, it will try and align each column by its alignment tabs. It does have some limitations (discussed further in Section 7), but in many cases it will produce results such as those in Listing 27 and Listing 28.

If you find that latexindent.pl does not perform satisfactorily on such environments then you can set the relevant key to 0, for example tabular: 0; alternatively, if you just want to ignore specific instances of the environment, you could wrap them in something from noIndentBlock (see Listing 19).

Listing 27 tabular1.tex
\begin{tabular}{cccc}
1&	2 &3       &4\\
5& &6       &\\
\end{tabular}
Listing 28 tabular1.tex default output
\begin{tabular}{cccc}
	1 & 2 & 3 & 4 \\
	5 &   & 6 &   \\
\end{tabular}

If, for example, you wish to remove the alignment of the \\ within a delimiter-aligned block, then the advanced form of lookForAlignDelims shown in Listing 29 is for you.

Listing 29 tabular.yaml
lookForAlignDelims:
   tabular: 
      delims: 1
      alignDoubleBackSlash: 0
      spacesBeforeDoubleBackSlash: 0
      multiColumnGrouping: 0
      alignRowsWithoutMaxDelims: 1
      spacesBeforeAmpersand: 1
      spacesAfterAmpersand: 1
   tabularx:
      delims: 1
   longtable: 1

Note that you can use a mixture of the basic and advanced form: in Listing 29 tabular and tabularx are advanced and longtable is basic. When using the advanced form, each field should receive at least 1 sub-field, and can (but does not have to) receive any of the following fields:

  • delims: binary switch (0 or 1) equivalent to simply specifying, for example, tabular: 1 in the basic version shown in Listing 26. If delims is set to 0 then the align at ampersand routine will not be called for this code block (default: 1);
  • alignDoubleBackSlash: binary switch (0 or 1) to determine if \\ should be aligned (default: 1);
  • spacesBeforeDoubleBackSlash: optionally, *update to spacesBeforeDoubleBackSlash in ampersand alignment specifies the number (integer \(\geq\) 0) of spaces to be inserted before \\ (default: 1). [2]
  • multiColumnGrouping: binary switch (0 or 1) that details if latexindent.pl should group columns above and below a \multicolumn command (default: 0);
  • alignRowsWithoutMaxDelims: binary switch (0 or 1) that details if rows that do not contain the maximum number of delimeters should be formatted so as to have the ampersands aligned (default: 1);
  • spacesBeforeAmpersand: optionally specifies the number (integer \(\geq\) 0) of spaces to be placed before ampersands (default: 1);
  • spacesAfterAmpersand: optionally specifies the number (integer \(\geq\) 0) of spaces to be placed After ampersands (default: 1);
  • justification: optionally specifies the justification of each cell as either left or right (default: left).

We will explore each of these features using the file tabular2.tex in Listing 30 (which contains a \multicolumn command), and the YAML files in Listing 31Listing 37.

Listing 30 tabular2.tex
\begin{tabular}{cccc}
A&    B & C       &D\\
AAA&    BBB & CCC       &DDD\\
  \multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading}\\
one&    two & three       &four\\
five& &six      &\\
seven & \\
\end{tabular}
Listing 31 tabular2.yaml
lookForAlignDelims:
   tabular: 
      multiColumnGrouping: 1
Listing 32 tabular3.yaml
lookForAlignDelims:
   tabular: 
      alignRowsWithoutMaxDelims: 0
Listing 33 tabular4.yaml
lookForAlignDelims:
   tabular: 
      spacesBeforeAmpersand: 4
Listing 34 tabular5.yaml
lookForAlignDelims:
   tabular: 
      spacesAfterAmpersand: 4
Listing 35 tabular6.yaml
lookForAlignDelims:
   tabular: 
      alignDoubleBackSlash: 0
Listing 36 tabular7.yaml
lookForAlignDelims:
   tabular: 
      spacesBeforeDoubleBackSlash: 0
Listing 37 tabular8.yaml
lookForAlignDelims:
   tabular: 
      justification: "right"

On running the commands

latexindent.pl tabular2.tex
latexindent.pl tabular2.tex -l tabular2.yaml
latexindent.pl tabular2.tex -l tabular3.yaml
latexindent.pl tabular2.tex -l tabular2.yaml,tabular4.yaml
latexindent.pl tabular2.tex -l tabular2.yaml,tabular5.yaml
latexindent.pl tabular2.tex -l tabular2.yaml,tabular6.yaml
latexindent.pl tabular2.tex -l tabular2.yaml,tabular7.yaml
latexindent.pl tabular2.tex -l tabular2.yaml,tabular8.yaml

we obtain the respective outputs given in Listing 38Listing 45.

Listing 38 tabular2.tex default output
\begin{tabular}{cccc}
	A                                 & B                                  & C     & D    \\
	AAA                               & BBB                                & CCC   & DDD  \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading}                \\
	one                               & two                                & three & four \\
	five                              &                                    & six   &      \\
	seven                             &                                                   \\
\end{tabular}
Listing 39 tabular2.tex using Listing 31
\begin{tabular}{cccc}
	A     & B                         & C     & D                          \\
	AAA   & BBB                       & CCC   & DDD                        \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading} \\
	one   & two                       & three & four                       \\
	five  &                           & six   &                            \\
	seven &                                                                \\
\end{tabular}
Listing 40 tabular2.tex using Listing 32
\begin{tabular}{cccc}
	A    & B   & C     & D                                                 \\
	AAA  & BBB & CCC   & DDD                                               \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading} \\
	one  & two & three & four                                              \\
	five &     & six   &                                                   \\
	seven &                                                                \\
\end{tabular}
Listing 41 tabular2.tex using Listing 31 and Listing 33
\begin{tabular}{cccc}
	A        & B                         & C        & D                       \\
	AAA      & BBB                       & CCC      & DDD                     \\
	\multicolumn{2}{c}{first heading}    & \multicolumn{2}{c}{second heading} \\
	one      & two                       & three    & four                    \\
	five     &                           & six      &                         \\
	seven    &                                                                \\
\end{tabular}
Listing 42 tabular2.tex using Listing 31 and Listing 34
\begin{tabular}{cccc}
	A     &    B                      &    C     &    D                       \\
	AAA   &    BBB                    &    CCC   &    DDD                     \\
	\multicolumn{2}{c}{first heading} &    \multicolumn{2}{c}{second heading} \\
	one   &    two                    &    three &    four                    \\
	five  &                           &    six   &                            \\
	seven &                                                                   \\
\end{tabular}
Listing 43 tabular2.tex using Listing 31 and Listing 35
\begin{tabular}{cccc}
	A     & B                         & C     & D \\
	AAA   & BBB                       & CCC   & DDD \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading} \\
	one   & two                       & three & four \\
	five  &                           & six   & \\
	seven & \\
\end{tabular}
Listing 44 tabular2.tex using Listing 31 and Listing 36
\begin{tabular}{cccc}
	A     & B                         & C     & D                         \\
	AAA   & BBB                       & CCC   & DDD                       \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading}\\
	one   & two                       & three & four                      \\
	five  &                           & six   &                           \\
	seven &                                                               \\
\end{tabular}
Listing 45 tabular2.tex using Listing 31 and Listing 37
\begin{tabular}{cccc}
	                          A &   B &                           C &    D \\
	                        AAA & BBB &                         CCC &  DDD \\
	\multicolumn{2}{c}{first heading} & \multicolumn{2}{c}{second heading} \\
	                        one & two &                       three & four \\
	                       five &     &                         six &      \\
	                      seven &                                          \\
\end{tabular}

Notice in particular:

  • in both Listing 38 and Listing 39 all rows have been aligned at the ampersand, even those that do not contain the maximum number of ampersands (3 ampersands, in this case);
  • in Listing 38 the columns have been aligned at the ampersand;
  • in Listing 39 the \multicolumn command has grouped the \(2\) columns beneath and above it, because multiColumnGrouping is set to \(1\) in Listing 31;
  • in Listing 40 rows 3 and 6 have not been aligned at the ampersand, because alignRowsWithoutMaxDelims has been to set to \(0\) in Listing 32; however, the \\ have still been aligned;
  • in Listing 41 the columns beneath and above the \multicolumn commands have been grouped (because multiColumnGrouping is set to \(1\)), and there are at least \(4\) spaces before each aligned ampersand because spacesBeforeAmpersand is set to \(4\);
  • in Listing 42 the columns beneath and above the \multicolumn commands have been grouped (because multiColumnGrouping is set to \(1\)), and there are at least \(4\) spaces after each aligned ampersand because spacesAfterAmpersand is set to \(4\);
  • in Listing 43 the \\ have not been aligned, because alignDoubleBackSlash is set to 0, otherwise the output is the same as Listing 39;
  • in Listing 44 the \\ have been aligned, and because spacesBeforeDoubleBackSlash is set to 0, there are no spaces ahead of them; the output is otherwise the same as Listing 39.
  • in Listing 45 the cells have been right-justified; note that cells above and below the \multicol statements have still been group correctly, because of the settings in Listing 31.

As of Version 3.0, the alignment routine works on mandatory and optional arguments within commands, and also within ‘special’ code blocks (see specialBeginEnd on ); for example, assuming that you have a command called \matrix and that it is populated within lookForAlignDelims (which it is, by default), and that you run the command

latexindent.pl matrix1.tex

then the before-and-after results shown in Listing 46 and Listing 47 are achievable by default.

Listing 46 matrix1.tex
\matrix [
	1&2   &3
4&5&6]{
7&8   &9
10&11&12
}
Listing 47 matrix1.tex default output
\matrix [
	1 & 2 & 3
	4 & 5 & 6]{
	7  & 8  & 9
	10 & 11 & 12
}

If you have blocks of code that you wish to align at the & character that are not wrapped in, for example, \begin{tabular}\end{tabular}, then you can use the mark up illustrated in Listing 48; the default output is shown in Listing 49. Note that the %* must be next to each other, but that there can be any number of spaces (possibly none) between the * and \begin{tabular}; note also that you may use any environment name that you have specified in lookForAlignDelims.

Listing 48 align-block.tex
%* \begin{tabular}
   1 & 2 & 3 & 4 \\
   5 &   & 6 &   \\
  %* \end{tabular}
Listing 49 align-block.tex default output
%* \begin{tabular}
	1 & 2 & 3 & 4 \\
	5 &   & 6 &   \\
%* \end{tabular}

With reference to Table 2 and the, yet undiscussed, fields of noAdditionalIndent and indentRules (see Section 5.2), these comment-marked blocks are considered environments.

indentAfterItems: fields

Listing 50 indentAfterItems
183
184
185
186
187
indentAfterItems:
    itemize: 1
    enumerate: 1
    description: 1
    list: 1

The environment names specified in indentAfterItems tell latexindent.pl to look for \item commands; if these switches are set to 1 then indentation will be performed so as indent the code after each item. A demonstration is given in Listing 51 and Listing 52

Listing 51 items1.tex
\begin{itemize}
\item some text here
some more text here
some more text here
\item another item
some more text here
\end{itemize}
Listing 52 items1.tex default output
\begin{itemize}
	\item some text here
	      some more text here
	      some more text here
	\item another item
	      some more text here
\end{itemize}

itemNames: fields

Listing 53 itemNames
193
194
195
itemNames:
    item: 1
    myitem: 1
If you have your own item commands (perhaps you prefer to use myitem, for example) then you can put populate them in itemNames. For example, users of the exam document class might like to add parts to indentAfterItems and part to itemNames to their user settings (see Section 4 for details of how to configure user settings, and Listing 13
in particular

.)

specialBeginEnd: fields

The fields specified *specialBeginEnd in specialBeginEnd are, in their default state, focused on math mode begin and end statements, but there is no requirement for this to be the case; Listing 54 shows the default settings of specialBeginEnd.

Listing 54 specialBeginEnd
199
200
201
202
203
204
205
206
207
208
209
210
211
212
specialBeginEnd:
    displayMath:
        begin: '\\\['
        end: '\\\]'
        lookForThis: 1
    inlineMath:
        begin: '(?<!\$)(?<!\\)\$(?!\$)'
        end: '(?<!\\)\$(?!\$)'
        lookForThis: 1
    displayMathTeX:
        begin: '\$\$'
        end: '\$\$'
        lookForThis: 1
    specialBeforeCommand: 0

The field displayMath represents \[...\], inlineMath represents $...$ and displayMathTex represents $$...$$. You can, of course, rename these in your own YAML files (see Section 4.2); indeed, you might like to set up your own special begin and end statements.

A demonstration of the before-and-after results are shown in Listing 55 and Listing 56.

Listing 55 special1.tex before
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
g(x)=f(2x)
$
Listing 56 special1.tex default output
The function $f$ has formula
\[
	f(x)=x^2.
\]
If you like splitting dollars,
$
	g(x)=f(2x)
$

For each field, lookForThis is set to 1 by default, which means that latexindent.pl will look for this pattern; you can tell latexindent.pl not to look for the pattern, by setting lookForThis to 0.

There are examples in which it is advantageous to search for specialBeginEnd fields before searching for commands, and the specialBeforeCommand switch controls this behaviour. For example, consider the file shown in Listing 57.

Listing 57 specialLR.tex
\begin{equation}
\left[
\sqrt{
a+b
}
\right]
\end{equation}

Now consider the YAML files shown in Listing 58 and Listing 59

Listing 58 specialsLeftRight.yaml
specialBeginEnd:
    leftRightSquare:
        begin: '\\left\['
        end: '\\right\]'
        lookForThis: 1
Listing 59 specialBeforeCommand.yaml
specialBeginEnd:
    specialBeforeCommand: 1

Upon running the following commands

latexindent.pl specialLR.tex -l=specialsLeftRight.yaml
latexindent.pl specialLR.tex -l=specialsLeftRight.yaml,specialBeforeCommand.yaml

we receive the respective outputs in Listing 60 and Listing 61.

Listing 60 specialLR.tex using Listing 58
\begin{equation}
	\left[
		\sqrt{
			a+b
		}
		\right]
\end{equation}
Listing 61 specialLR.tex using Listing 58 and Listing 59
\begin{equation}
	\left[
		\sqrt{
			a+b
		}
	\right]
\end{equation}

Notice that in:

  • Listing 60 the \left has been treated as a command, with one optional argument;
  • Listing 61 the specialBeginEnd pattern in Listing 58 has been obeyed because Listing 59 specifies that the specialBeginEnd should be sought before commands.

indentAfterHeadings: fields

Listing 62 indentAfterHeadings
222
223
224
225
226
227
228
229
230
231
indentAfterHeadings:
    part:
       indentAfterThisHeading: 0
       level: 1
    chapter: 
       indentAfterThisHeading: 0
       level: 2
    section:
       indentAfterThisHeading: 0
       level: 3

This field enables the user to specify indentation rules that take effect after heading commands such as \part, \chapter, \section, \subsection*, or indeed any user-specified command written in this field. [3]

The default settings do not place indentation after a heading, but you can easily switch them on by changing
indentAfterThisHeading: 0 to
indentAfterThisHeading: 1. The level field tells latexindent.pl the hierarchy of the heading structure in your document. You might, for example, like to have both section and subsection set with level: 3 because you do not want the indentation to go too deep.

You can add any of your own custom heading commands to this field, specifying the level as appropriate. You can also specify your own indentation in indentRules (see Section 5.2); you will find the default indentRules contains chapter: " " which tells latexindent.pl simply to use a space character after headings (once indent is set to 1 for chapter).

For example, assuming that you have the code in Listing 63 saved into headings1.yaml, and that you have the text from Listing 64 saved into headings1.tex.

Listing 63 headings1.yaml
indentAfterHeadings:
    subsection:
       indentAfterThisHeading: 1
       level: 1
    paragraph:
       indentAfterThisHeading: 1
       level: 2
Listing 64 headings1.tex
\subsection{subsection title}
subsection text
subsection text
\paragraph{paragraph title}
paragraph text
paragraph text
\paragraph{paragraph title}
paragraph text
paragraph text

If you run the command

latexindent.pl headings1.tex -l=headings1.yaml

then you should receive the output given in Listing 65.

Listing 65 headings1.tex using Listing 63
\subsection{subsection title}
	subsection text
	subsection text
	\paragraph{paragraph title}
		paragraph text
		paragraph text
	\paragraph{paragraph title}
		paragraph text
		paragraph text
Listing 66 headings1.tex second modification
\subsection{subsection title}
	subsection text
	subsection text
\paragraph{paragraph title}
	paragraph text
	paragraph text
\paragraph{paragraph title}
	paragraph text
	paragraph text

Now say that you modify the YAML from Listing 63 so that the paragraph level is 1; after running

latexindent.pl headings1.tex -l=headings1.yaml

you should receive the code given in Listing 66; notice that the paragraph and subsection are at the same indentation level.

maximumIndentation: horizontal space

You can control the maximum indentation given to your file by specifying the maximumIndentation field as horizontal space (but not including tabs). This feature uses the Text::Tabs module (“Text:Tabs Perl Module” 2017), and is off by default.

For example, consider the example shown in Listing 67 together with the default output shown in Listing 68.

Listing 67 mult-nested.tex
\begin{one}
one
\begin{two}
    two
\begin{three}
     three 
\begin{four}
       four
\end{four}
\end{three}
\end{two}
\end{one}
Listing 68 mult-nested.tex default output
\begin{one}
	one
	\begin{two}
		two
		\begin{three}
			three
			\begin{four}
				four
			\end{four}
		\end{three}
	\end{two}
\end{one}

Now say that, for example, you have the max-indentation1.yaml from Listing 69 and that you run the following command:

latexindent.pl mult-nested.tex -l=max-indentation1

You should receive the output shown in Listing 70.

Listing 69 max-indentation1.yaml
maximumIndentation: " "
Listing 70 mult-nested.tex using Listing 69
\begin{one}
 one
 \begin{two}
 two
 \begin{three}
 three
 \begin{four}
 four
 \end{four}
 \end{three}
 \end{two}
\end{one}

Comparing the output in Listing 68 and Listing 70 we notice that the (default) tabs of indentation have been replaced by a single space.

In general, when using the maximumIndentation feature, any leading tabs will be replaced by equivalent spaces except, of course, those found in verbatimEnvironments (see Listing 17) or noIndentBlock (see Listing 19).

5.1. The code blocks known latexindent.pl

As of Version 3.0, latexindent.pl processes documents using code blocks; each of these are shown in Table 2.

Table 2 Code blocks known to latexindent.pl
Code block characters allowed in name example
environments a-zA-Z@\*0-9_\\ \begin{myenv}body of myenv\end{myenv}
optionalArguments inherits name from parent (e.g environment name) [opt arg text]
mandatoryArguments inherits name from parent (e.g environment name) {mand arg text}
commands +a-zA-Z@\*0-9_\: \mycommand<arguments>
keyEqualsValuesBracesBrackets a-zA-Z@\*0-9_\/.\h\{\}:\#- my key/.style=<arguments>
namedGroupingBracesBrackets a-zA-Z@\*>< in<arguments>
UnNamedGroupingBracesBrackets No name! { or [ or , or & or ) or ( or $ followed by <arguments>
ifElseFi @a-zA-Z but must begin with either \if of \@if \ifnum......\else...\fi
items User specified, see Listing 50 and Listing 53 \begin{enumerate}  \item ...\end{enumerate}
specialBeginEnd User specified, see Listing 54 \[  ...\]
afterHeading User specified, see Listing 62 \chapter{title}  ...\section{title}
filecontents User specified, see Listing 23 \begin{filecontents}...\end{filecontents}

We will refer to these code blocks in what follows.

5.2. noAdditionalIndent and indentRules

latexindent.pl operates on files by looking for code blocks, as detailed in Section 5.1; for each type of code block in Table 2 (which we will call a <thing> in what follows) it searches YAML fields for information in the following order:

  1. noAdditionalIndent for the name of the current <thing>;
  2. indentRules for the name of the current <thing>;
  3. noAdditionalIndentGlobal for the type of the current <thing>;
  4. indentRulesGlobal for the type of the current <thing>.

Using the above list, the first piece of information to be found will be used; failing that, the value of defaultIndent is used. If information is found in multiple fields, the first one according to the list above will be used; for example, if information is present in both indentRules and in noAdditionalIndentGlobal, then the information from indentRules takes priority.

We now present details for the different type of code blocks known to latexindent.pl, as detailed in Table 2; for reference, there follows a list of the code blocks covered.

5.2.1. Environments and their arguments

There are a few different YAML switches governing the indentation of environments; let’s start with the code shown in Listing 71.

Listing 71 myenv.tex
\begin{outer}
\begin{myenv}
  body of environment
body of environment
     body of environment
\end{myenv}
\end{outer}

noAdditionalIndent: fields

If we do not wish myenv to receive any additional indentation, we have a few choices available to us, as demonstrated in Listing 72 and Listing 73.

Listing 72 myenv-noAdd1.yaml
noAdditionalIndent:
    myenv: 1
Listing 73 myenv-noAdd2.yaml
noAdditionalIndent:
    myenv: 
        body: 1

On applying either of the following commands,

latexindent.pl myenv.tex -l myenv-noAdd1.yaml
latexindent.pl myenv.tex -l myenv-noAdd2.yaml

we obtain the output given in Listing 74; note in particular that the environment myenv has not received any additional indentation, but that the outer environment has still received indentation.

Listing 74 myenv.tex output (using either Listing 72 or Listing 73)
\begin{outer}
	\begin{myenv}
	body of environment
	body of environment
	body of environment
	\end{myenv}
\end{outer}

Upon changing the YAML files to those shown in Listing 75 and Listing 76, and running either

latexindent.pl myenv.tex -l myenv-noAdd3.yaml
latexindent.pl myenv.tex -l myenv-noAdd4.yaml

we obtain the output given in Listing 77.

Listing 75 myenv-noAdd3.yaml
noAdditionalIndent:
    myenv: 0
Listing 76 myenv-noAdd4.yaml
noAdditionalIndent:
    myenv: 
        body: 0
Listing 77 myenv.tex output (using either Listing 75 or Listing 76)
\begin{outer}
	\begin{myenv}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}

Let’s now allow myenv to have some optional and mandatory arguments, as in Listing 78.

Listing 78 myenv-args.tex
\begin{outer}
\begin{myenv}[%
  optional argument text
        optional argument text]%
  { mandatory argument text
 mandatory argument text}
  body of environment
body of environment
     body of environment
\end{myenv}
\end{outer}

Upon running

latexindent.pl -l=myenv-noAdd1.yaml myenv-args.tex

we obtain the output shown in Listing 79; note that the optional argument, mandatory argument and body all have received no additional indent. This is because, when noAdditionalIndent is specified in ‘scalar’ form (as in Listing 72), then all parts of the environment (body, optional and mandatory arguments) are assumed to want no additional indent.

Listing 79 myenv-args.tex using Listing 72
\begin{outer}
	\begin{myenv}[%
	optional argument text
	optional argument text]%
	{ mandatory argument text
	mandatory argument text}
	body of environment
	body of environment
	body of environment
	\end{myenv}
\end{outer}

We may customise noAdditionalIndent for optional and mandatory arguments of the myenv environment, as shown in, for example, Listing 80 and Listing 81.

Listing 80 myenv-noAdd5.yaml
noAdditionalIndent:
    myenv: 
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
Listing 81 myenv-noAdd6.yaml
noAdditionalIndent:
    myenv: 
        body: 0
        optionalArguments: 0
        mandatoryArguments: 1

Upon running

latexindent.pl myenv.tex -l myenv-noAdd5.yaml
latexindent.pl myenv.tex -l myenv-noAdd6.yaml

we obtain the respective outputs given in Listing 82 and Listing 83. Note that in Listing 82 the text for the optional argument has not received any additional indentation, and that in Listing 83 the mandatory argument has not received any additional indentation; in both cases, the body has not received any additional indentation.

Listing 82 myenv-args.tex using Listing 80
\begin{outer}
	\begin{myenv}[%
		optional argument text
		optional argument text]%
		{ mandatory argument text
			mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}
Listing 83 myenv-args.tex using Listing 81
\begin{outer}
	\begin{myenv}[%
			optional argument text
			optional argument text]%
		{ mandatory argument text
		mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}

indentRules: fields

We may also specify indentation rules for environment code blocks using the indentRules field; see, for example, Listing 84 and Listing 85.

Listing 84 myenv-rules1.yaml
indentRules:
    myenv: "   "
Listing 85 myenv-rules2.yaml
indentRules:
    myenv: 
        body: "   "

On applying either of the following commands,

latexindent.pl myenv.tex -l myenv-rules1.yaml
latexindent.pl myenv.tex -l myenv-rules2.yaml

we obtain the output given in Listing 86; note in particular that the environment myenv has received one tab (from the outer environment) plus three spaces from Listing 84 or Listing 85.

Listing 86 myenv.tex output (using either Listing 84 or Listing 85)
\begin{outer}
	\begin{myenv}
	   body of environment
	   body of environment
	   body of environment
	\end{myenv}
\end{outer}

If you specify a field in indentRules using anything other than horizontal space, it will be ignored.

Returning to the example in Listing 78 that contains optional and mandatory arguments. Upon using Listing 84 as in

latexindent.pl myenv-args.tex -l=myenv-rules1.yaml

we obtain the output in Listing 87; note that the body, optional argument and mandatory argument of myenv have all received the same customised indentation.

Listing 87 myenv-args.tex using Listing 84
\begin{outer}
	\begin{myenv}[%
	      optional argument text
	      optional argument text]%
	   { mandatory argument text
	      mandatory argument text}
	   body of environment
	   body of environment
	   body of environment
	\end{myenv}
\end{outer}

You can specify different indentation rules for the different features using, for example, Listing 88 and Listing 89

Listing 88 myenv-rules3.yaml
indentRules:
    myenv: 
        body: "   "
        optionalArguments: " "
Listing 89 myenv-rules4.yaml
indentRules:
    myenv: 
        body: "   "
        mandatoryArguments: "\t\t"

After running

latexindent.pl myenv-args.tex -l myenv-rules3.yaml
latexindent.pl myenv-args.tex -l myenv-rules4.yaml

then we obtain the respective outputs given in Listing 90 and Listing 91.

Listing 90 myenv-args.tex using Listing 88
\begin{outer}
	\begin{myenv}[%
	    optional argument text
	    optional argument text]%
	   { mandatory argument text
		   mandatory argument text}
	   body of environment
	   body of environment
	   body of environment
	\end{myenv}
\end{outer}
Listing 91 myenv-args.tex using Listing 89
\begin{outer}
	\begin{myenv}[%
		   optional argument text
		   optional argument text]%
	   { mandatory argument text
			   mandatory argument text}
	   body of environment
	   body of environment
	   body of environment
	\end{myenv}
\end{outer}

Note that in Listing 90, the optional argument has only received a single space of indentation, while the mandatory argument has received the default (tab) indentation; the environment body has received three spaces of indentation.

In Listing 91, the optional argument has received the default (tab) indentation, the mandatory argument has received two tabs of indentation, and the body has received three spaces of indentation.

noAdditionalIndentGlobal: fields

Listing 92 noAdditionalIndentGlobal
280
281
noAdditionalIndentGlobal:
    environments: 0

Assuming that your environment name is not found within neither noAdditionalIndent nor indentRules, the next place that latexindent.pl will look is noAdditionalIndentGlobal, and in particular for the environments key (see Listing 92). Let’s say that you change the value of environments to 1 in Listing 92, and that you run

latexindent.pl myenv-args.tex -l env-noAdditionalGlobal.yaml
latexindent.pl myenv-args.tex -l myenv-rules1.yaml,env-noAdditionalGlobal.yaml

The respective output from these two commands are in Listing 93 and Listing 94; in Listing 93 notice that both environments receive no additional indentation but that the arguments of myenv still do receive indentation. In Listing 94 notice that the outer environment does not receive additional indentation, but because of the settings from myenv-rules1.yaml (in Listing 84), the myenv environment still does receive indentation.

Listing 93 myenv-args.tex using Listing 92
\begin{outer}
\begin{myenv}[%
	optional argument text
	optional argument text]%
{ mandatory argument text
	mandatory argument text}
body of environment
body of environment
body of environment
\end{myenv}
\end{outer}
Listing 94 myenv-args.tex using Listing 92 and Listing 84
\begin{outer}
\begin{myenv}[%
      optional argument text
      optional argument text]%
   { mandatory argument text
      mandatory argument text}
   body of environment
   body of environment
   body of environment
\end{myenv}
\end{outer}

In fact, noAdditionalIndentGlobal also contains keys that control the indentation of optional and mandatory arguments; on referencing Listing 95 and Listing 96

Listing 95 opt-args-no-add-glob.yaml
noAdditionalIndentGlobal:
    optionalArguments: 1
Listing 96 mand-args-no-add-glob.yaml
noAdditionalIndentGlobal:
    mandatoryArguments: 1

we may run the commands

latexindent.pl  myenv-args.tex -local opt-args-no-add-glob.yaml
latexindent.pl  myenv-args.tex -local mand-args-no-add-glob.yaml

which produces the respective outputs given in Listing 97 and Listing 98. Notice that in Listing 97 the optional argument has not received any additional indentation, and in Listing 98 the mandatory argument has not received any additional indentation.

Listing 97 myenv-args.tex using Listing 95
\begin{outer}
	\begin{myenv}[%
		optional argument text
		optional argument text]%
		{ mandatory argument text
			mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}
Listing 98 myenv-args.tex using Listing 96
\begin{outer}
	\begin{myenv}[%
			optional argument text
			optional argument text]%
		{ mandatory argument text
		mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}

indentRulesGlobal: fields

Listing 99 indentRulesGlobal
296
297
indentRulesGlobal:
    environments: 0

The final check that latexindent.pl will make is to look for indentRulesGlobal as detailed in Listing 99; if you change the environments field to anything involving horizontal space, say " ", and then run the following commands

latexindent.pl  myenv-args.tex -l env-indentRules.yaml
latexindent.pl  myenv-args.tex -l myenv-rules1.yaml,env-indentRules.yaml

then the respective output is shown in Listing 100 and Listing 101. Note that in Listing 100, both the environment blocks have received a single-space indentation, whereas in Listing 101 the outer environment has received single-space indentation (specified by indentRulesGlobal), but myenv has received "   ", as specified by the particular indentRules for myenv Listing 84.

Listing 100 myenv-args.tex using Listing 99
\begin{outer}
 \begin{myenv}[%
	  optional argument text
	  optional argument text]%
  { mandatory argument text
	  mandatory argument text}
  body of environment
  body of environment
  body of environment
 \end{myenv}
\end{outer}
Listing 101 myenv-args.tex using Listing 84 and Listing 99
\begin{outer}
 \begin{myenv}[%
       optional argument text
       optional argument text]%
    { mandatory argument text
       mandatory argument text}
    body of environment
    body of environment
    body of environment
 \end{myenv}
\end{outer}

You can specify indentRulesGlobal for both optional and mandatory arguments, as detailed in Listing 102 and Listing 103

Listing 102 opt-args-indent-rules-glob.yaml
indentRulesGlobal:
    optionalArguments: "\t\t"
Listing 103 mand-args-indent-rules-glob.yaml
indentRulesGlobal:
    mandatoryArguments: "\t\t"

Upon running the following commands

latexindent.pl  myenv-args.tex -local opt-args-indent-rules-glob.yaml
latexindent.pl  myenv-args.tex -local mand-args-indent-rules-glob.yaml

we obtain the respective outputs in Listing 104 and Listing 105. Note that the optional argument in Listing 104 has received two tabs worth of indentation, while the mandatory argument has done so in Listing 105.

Listing 104 myenv-args.tex using Listing 102
\begin{outer}
	\begin{myenv}[%
				optional argument text
				optional argument text]%
		{ mandatory argument text
			mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}
Listing 105 myenv-args.tex using Listing 103
\begin{outer}
	\begin{myenv}[%
			optional argument text
			optional argument text]%
		{ mandatory argument text
				mandatory argument text}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}

5.2.2. Environments with items

With reference to Listing 50 and Listing 53, some commands may contain item commands; for the purposes of this discussion, we will use the code from Listing 51.

Assuming that you’ve populated itemNames with the name of your item, you can put the item name into noAdditionalIndent as in Listing 106, although a more efficient approach may be to change the relevant field in itemNames to 0. Similarly, you can customise the indentation that your item receives using indentRules, as in Listing 107

Listing 106 item-noAdd1.yaml
noAdditionalIndent:
    item: 1
# itemNames:
#   item: 0
Listing 107 item-rules1.yaml
indentRules:
    item: " "

Upon running the following commands

latexindent.pl items1.tex -local item-noAdd1.yaml
latexindent.pl items1.tex -local item-rules1.yaml

the respective outputs are given in Listing 108 and Listing 109; note that in Listing 108 that the text after each item has not received any additional indentation, and in Listing 109, the text after each item has received a single space of indentation, specified by Listing 107.

Listing 108 items1.tex using Listing 106
\begin{itemize}
	\item some text here
	some more text here
	some more text here
	\item another item
	some more text here
\end{itemize}
Listing 109 items1.tex using Listing 107
\begin{itemize}
	\item some text here
	 some more text here
	 some more text here
	\item another item
	 some more text here
\end{itemize}

Alternatively, you might like to populate noAdditionalIndentGlobal or indentRulesGlobal using the items key, as demonstrated in Listing 110 and Listing 111. Note that there is a need to ‘reset/remove’ the item field from indentRules in both cases (see the hierarchy description given on ) as the item command is a member of indentRules by default.

Listing 110 items-noAdditionalGlobal.yaml
indentRules:
    item: 0
noAdditionalIndentGlobal:
    items: 1
Listing 111 items-indentRulesGlobal.yaml
indentRules:
    item: 0
indentRulesGlobal:
    items: " "

Upon running the following commands,

latexindent.pl items1.tex -local items-noAdditionalGlobal.yaml
latexindent.pl items1.tex -local items-indentRulesGlobal.yaml

the respective outputs from Listing 108 and Listing 109 are obtained; note, however, that all such item commands without their own individual noAdditionalIndent or indentRules settings would behave as in these listings.

5.2.3. Commands with arguments

Let’s begin with the simple example in Listing 112; when latexindent.pl operates on this file, the default output is shown in Listing 113. [4]

Listing 112 mycommand.tex
\mycommand
{
mand arg text
mand arg text}
[
opt arg text
opt arg text
]
Listing 113 mycommand.tex default output
\mycommand
{
	mand arg text
	mand arg text}
[
	opt arg text
	opt arg text
]

As in the environment-based case (see Listing 72 and Listing 73) we may specify noAdditionalIndent either in ‘scalar’ form, or in ‘field’ form, as shown in Listing 114 and Listing 115

Listing 114 mycommand-noAdd1.yaml
noAdditionalIndent:
    mycommand: 1
Listing 115 mycommand-noAdd2.yaml
noAdditionalIndent:
    mycommand: 
        body: 1

After running the following commands,

latexindent.pl mycommand.tex -l mycommand-noAdd1.yaml
latexindent.pl mycommand.tex -l mycommand-noAdd2.yaml

we receive the respective output given in Listing 116 and Listing 117

Listing 116 mycommand.tex using Listing 114
\mycommand
{
mand arg text
mand arg text}
[
opt arg text
opt arg text
]
Listing 117 mycommand.tex using Listing 115
\mycommand
{
	mand arg text
	mand arg text}
[
	opt arg text
	opt arg text
]

Note that in Listing 116 that the ‘body’, optional argument and mandatory argument have all received no additional indentation, while in Listing 117, only the ‘body’ has not received any additional indentation. We define the ‘body’ of a command as any lines following the command name that include its optional or mandatory arguments.

We may further customise noAdditionalIndent for mycommand as we did in Listing 80 and Listing 81; explicit examples are given in Listing 118 and Listing 119.

Listing 118 mycommand-noAdd3.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
Listing 119 mycommand-noAdd4.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 0
        mandatoryArguments: 1

After running the following commands,

latexindent.pl mycommand.tex -l mycommand-noAdd3.yaml
latexindent.pl mycommand.tex -l mycommand-noAdd4.yaml

we receive the respective output given in Listing 120 and Listing 121.

Listing 120 mycommand.tex using Listing 118
\mycommand
{
	mand arg text
	mand arg text}
[
opt arg text
opt arg text
]
Listing 121 mycommand.tex using Listing 119
\mycommand
{
mand arg text
mand arg text}
[
	opt arg text
	opt arg text
]

Attentive readers will note that the body of mycommand in both Listing 120 and Listing 121 has received no additional indent, even though body is explicitly set to 0 in both Listing 118 and Listing 119. This is because, by default, noAdditionalIndentGlobal for commands is set to 1 by default; this can be easily fixed as in Listing 122 and Listing 123.

Listing 122 mycommand-noAdd5.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
noAdditionalIndentGlobal:
    commands: 0
Listing 123 mycommand-noAdd6.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 0
        mandatoryArguments: 1
noAdditionalIndentGlobal:
    commands: 0

After running the following commands,

latexindent.pl mycommand.tex -l mycommand-noAdd5.yaml
latexindent.pl mycommand.tex -l mycommand-noAdd6.yaml

we receive the respective output given in Listing 124 and Listing 125.

Listing 124 mycommand.tex using Listing 122
\mycommand
	{
		mand arg text
		mand arg text}
	[
	opt arg text
	opt arg text
	]
Listing 125 mycommand.tex using Listing 123
\mycommand
	{
	mand arg text
	mand arg text}
	[
		opt arg text
		opt arg text
	]

Both indentRules and indentRulesGlobal can be adjusted as they were for environment code blocks, as in Listing 88 and Listing 89 and Listing 99 and Listing 102 and Listing 103.

5.2.4. ifelsefi code blocks

Let’s use the simple example shown in Listing 126; when latexindent.pl operates on this file, the output as in Listing 127; note that the body of each of the \if statements have been indented, and that the \else statement has been accounted for correctly.

Listing 126 ifelsefi1.tex
\ifodd\radius
\ifnum\radius<14
\pgfmathparse{100-(\radius)*4};
\else
\pgfmathparse{200-(\radius)*3};
\fi\fi
Listing 127 ifelsefi1.tex default output
\ifodd\radius
	\ifnum\radius<14
		\pgfmathparse{100-(\radius)*4};
	\else
		\pgfmathparse{200-(\radius)*3};
	\fi\fi

It is recommended to specify noAdditionalIndent and indentRules in the ‘scalar’ form only for these type of code blocks, although the ‘field’ form would work, assuming that body was specified. Examples are shown in Listing 128 and Listing 129.

Listing 128 ifnum-noAdd.yaml
noAdditionalIndent:
    ifnum: 1
Listing 129 ifnum-indent-rules.yaml
indentRules:
    ifnum: "  "

After running the following commands,

latexindent.pl ifelsefi1.tex -local ifnum-noAdd.yaml
latexindent.pl ifelsefi1.tex -l ifnum-indent-rules.yaml

we receive the respective output given in Listing 130 and Listing 131; note that in Listing 130, the ifnum code block has not received any additional indentation, while in Listing 131, the ifnum code block has received one tab and two spaces of indentation.

Listing 130 ifelsefi1.tex using Listing 128
\ifodd\radius
	\ifnum\radius<14
	\pgfmathparse{100-(\radius)*4};
	\else
	\pgfmathparse{200-(\radius)*3};
	\fi\fi
Listing 131 ifelsefi1.tex using Listing 129
\ifodd\radius
	\ifnum\radius<14
	  \pgfmathparse{100-(\radius)*4};
	\else
	  \pgfmathparse{200-(\radius)*3};
	\fi\fi

We may specify noAdditionalIndentGlobal and indentRulesGlobal as in Listing 132 and Listing 133.

Listing 132 ifelsefi-noAdd-glob.yaml
noAdditionalIndentGlobal:
    ifElseFi: 1
Listing 133 ifelsefi-indent-rules-global.yaml
indentRulesGlobal:
    ifElseFi: " "

Upon running the following commands

latexindent.pl ifelsefi1.tex -local ifelsefi-noAdd-glob.yaml
latexindent.pl ifelsefi1.tex -l ifelsefi-indent-rules-global.yaml

we receive the outputs in Listing 134 and Listing 135; notice that in Listing 134 neither of the ifelsefi code blocks have received indentation, while in Listing 135 both code blocks have received a single space of indentation.

Listing 134 ifelsefi1.tex using Listing 132
\ifodd\radius
\ifnum\radius<14
\pgfmathparse{100-(\radius)*4};
\else
\pgfmathparse{200-(\radius)*3};
\fi\fi
Listing 135 ifelsefi1.tex using Listing 133
\ifodd\radius
 \ifnum\radius<14
  \pgfmathparse{100-(\radius)*4};
 \else
  \pgfmathparse{200-(\radius)*3};
 \fi\fi

5.2.5. specialBeginEnd code blocks

Let’s use the example from Listing 55 which has default output shown in Listing 56.

It is recommended to specify noAdditionalIndent and indentRules in the ‘scalar’ form for these type of code blocks, although the ‘field’ form would work, assuming that body was specified. Examples are shown in Listing 136 and Listing 137.

Listing 136 displayMath-noAdd.yaml
noAdditionalIndent:
    displayMath: 1
Listing 137 displayMath-indent-rules.yaml
indentRules:
    displayMath: "\t\t\t"

After running the following commands,

latexindent.pl special1.tex -local displayMath-noAdd.yaml
latexindent.pl special1.tex -l displayMath-indent-rules.yaml

we receive the respective output given in Listing 138 and Listing 139; note that in Listing 138, the displayMath code block has not received any additional indentation, while in Listing 139, the displayMath code block has received three tabs worth of indentation.

Listing 138 special1.tex using Listing 136
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
	g(x)=f(2x)
$
Listing 139 special1.tex using Listing 137
The function $f$ has formula
\[
			f(x)=x^2.
\]
If you like splitting dollars,
$
	g(x)=f(2x)
$

We may specify noAdditionalIndentGlobal and indentRulesGlobal as in Listing 140 and Listing 141.

Listing 140 special-noAdd-glob.yaml
noAdditionalIndentGlobal:
    specialBeginEnd: 1
Listing 141 special-indent-rules-global.yaml
indentRulesGlobal:
    specialBeginEnd: " "

Upon running the following commands

latexindent.pl special1.tex -local special-noAdd-glob.yaml
latexindent.pl special1.tex -l special-indent-rules-global.yaml

we receive the outputs in Listing 142 and Listing 143; notice that in Listing 142 neither of the special code blocks have received indentation, while in Listing 143 both code blocks have received a single space of indentation.

Listing 142 special1.tex using Listing 140
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
g(x)=f(2x)
$
Listing 143 special1.tex using Listing 141
The function $f$ has formula
\[
 f(x)=x^2.
\]
If you like splitting dollars,
$
 g(x)=f(2x)
$

5.2.6. afterHeading code blocks

Let’s use the example Listing 144 for demonstration throughout this . As discussed on , by default latexindent.pl will not add indentation after headings.

Listing 144 headings2.tex
\paragraph{paragraph 
title}
paragraph text
paragraph text

On using the YAML file in Listing 146 by running the command

latexindent.pl headings2.tex -l headings3.yaml

we obtain the output in Listing 145. Note that the argument of paragraph has received (default) indentation, and that the body after the heading statement has received (default) indentation.

Listing 145 headings2.tex using Listing 146
\paragraph{paragraph
		title}
	paragraph text
	paragraph text
Listing 146 headings3.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1

If we specify noAdditionalIndent as in Listing 148 and run the command

latexindent.pl headings2.tex -l headings4.yaml

then we receive the output in Listing 147. Note that the arguments and the body after the heading of paragraph has received no additional indentation, because we have specified noAdditionalIndent in scalar form.

Listing 147 headings2.tex using Listing 148
\paragraph{paragraph
title}
paragraph text
paragraph text
Listing 148 headings4.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndent:
    paragraph: 1

Similarly, if we specify indentRules as in Listing 150 and run analogous commands to those above, we receive the output in Listing 149; note that the body, mandatory argument and content after the heading of paragraph have all received three tabs worth of indentation.

Listing 149 headings2.tex using Listing 150
\paragraph{paragraph
									title}
			paragraph text
			paragraph text
Listing 150 headings5.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRules:
    paragraph: "\t\t\t"

We may, instead, specify noAdditionalIndent in ‘field’ form, as in Listing 152 which gives the output in Listing 151.

Listing 151 headings2.tex using Listing 152
\paragraph{paragraph
	title}
paragraph text
paragraph text
Listing 152 headings6.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndent:
    paragraph: 
        body: 0
        mandatoryArguments: 0
        afterHeading: 1

Analogously, we may specify indentRules as in Listing 154 which gives the output in Listing 153; note that mandatory argument text has only received a single space of indentation, while the body after the heading has received three tabs worth of indentation.

Listing 153 headings2.tex using Listing 154
\paragraph{paragraph
			 title}
			paragraph text
			paragraph text
Listing 154 headings7.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRules:
    paragraph: 
        mandatoryArguments: " "
        afterHeading: "\t\t\t"

Finally, let’s consider noAdditionalIndentGlobal and indentRulesGlobal shown in Listing 156 and Listing 158 respectively, with respective output in Listing 155 and Listing 157. Note that in Listing 156 the mandatory argument of paragraph has received a (default) tab’s worth of indentation, while the body after the heading has received no additional indentation. Similarly, in Listing 157, the argument has received both a (default) tab plus two spaces of indentation (from the global rule specified in Listing 158), and the remaining body after paragraph has received just two spaces of indentation.

Listing 155 headings2.tex using Listing 156
\paragraph{paragraph
	title}
paragraph text
paragraph text
Listing 156 headings8.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndentGlobal:
    afterHeading: 1
Listing 157 headings2.tex using Listing 158
\paragraph{paragraph
	  title}
  paragraph text
  paragraph text
Listing 158 headings9.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRulesGlobal:
    afterHeading: "  "

5.2.7. The remaining code blocks

Referencing the different types of code blocks in Table 2, we have a few code blocks yet to cover; these are very similar to the commands code block type covered comprehensively in Section 5.2.3, but a small discussion defining these remaining code blocks is necessary.

keyEqualsValuesBracesBrackets

latexindent.pl defines this type of code block by the following criteria:

  • it must immediately follow either { OR [ OR , with comments and blank lines allowed;
  • then it has a name made up of the characters detailed in Table 2;
  • then an \(=\) symbol;
  • then at least one set of curly braces or square brackets (comments and line breaks allowed throughout).

An example is shown in Listing 159, with the default output given in Listing 160.

Listing 159 pgfkeys1.tex
\pgfkeys{/tikz/.cd,
start coordinate/.initial={0,
\vertfactor},
}
Listing 160 pgfkeys1.tex default output
\pgfkeys{/tikz/.cd,
	start coordinate/.initial={0,
			\vertfactor},
}

In Listing 160, note that the maximum indentation is three tabs, and these come from:

  • the \pgfkeys command’s mandatory argument;
  • the start coordinate/.initial key’s mandatory argument;
  • the start coordinate/.initial key’s body, which is defined as any lines following the name of the key that include its arguments. This is the part controlled by the body field for noAdditionalIndent and friends from .

namedGroupingBracesBrackets

This type of code block is mostly motivated by tikz-based code; we define this code block as follows:

  • it must immediately follow either horizontal space OR one or more line breaks OR { OR [ OR $ OR ) OR (;
  • the name may contain the characters detailed in Table 2;
  • then at least one set of curly braces or square brackets (comments and line breaks allowed throughout).

A simple example is given in Listing 161, with default output in Listing 162.

Listing 161 child1.tex
\coordinate
child[grow=down]{
edge from parent [antiparticle]
node [above=3pt] {$C$}
}
Listing 162 child1.tex default output
\coordinate
child[grow=down]{
		edge from parent [antiparticle]
		node [above=3pt] {$C$}
	}

In particular, latexindent.pl considers child, parent and node all to be namedGroupingBracesBrackets [5]. Referencing Listing 162, note that the maximum indentation is two tabs, and these come from:

  • the child’s mandatory argument;
  • the child’s body, which is defined as any lines following the name of the namedGroupingBracesBrackets that include its arguments. This is the part controlled by the body field for noAdditionalIndent and friends from .

UnNamedGroupingBracesBrackets

occur in a variety of situations; specifically, we define this type of code block as satisfying the following criteria:

  • it must immediately follow either { OR [ OR , OR & OR ) OR ( OR $;
  • then at least one set of curly braces or square brackets (comments and line breaks allowed throughout).

An example is shown in Listing 163 with default output give in Listing 164.

Listing 163 psforeach1.tex
\psforeach{\row}{%
{
{3,2.8,2.7,3,3.1}},%
{2.8,1,1.2,2,3},%
}
Listing 164 psforeach1.tex default output
\psforeach{\row}{%
	{
			{3,2.8,2.7,3,3.1}},%
	{2.8,1,1.2,2,3},%
}

Referencing Listing 164, there are three sets of unnamed braces. Note also that the maximum value of indentation is three tabs, and these come from:

  • the \psforeach command’s mandatory argument;
  • the first un-named braces mandatory argument;
  • the first un-named braces body, which we define as any lines following the first opening { or [ that defined the code block. This is the part controlled by the body field for noAdditionalIndent and friends from .

Users wishing to customise the mandatory and/or optional arguments on a per-name basis for the UnNamedGroupingBracesBrackets should use always-un-named.

filecontents

code blocks behave just as environments, except that neither arguments nor items are sought.

5.2.8. Summary

Having considered all of the different types of code blocks, the functions of the fields given in Listing 165 and Listing 166 should now make sense.

Listing 165 noAdditionalIndentGlobal
280
281
282
283
284
285
286
287
288
289
290
291
292
noAdditionalIndentGlobal:
    environments: 0
    commands: 1
    optionalArguments: 0
    mandatoryArguments: 0
    ifElseFi: 0
    items: 0
    keyEqualsValuesBracesBrackets: 0
    namedGroupingBracesBrackets: 0
    UnNamedGroupingBracesBrackets: 0
    specialBeginEnd: 0
    afterHeading: 0
    filecontents: 0
Listing 166 indentRulesGlobal
296
297
298
299
300
301
302
303
304
305
306
307
308
indentRulesGlobal:
    environments: 0
    commands: 0
    optionalArguments: 0
    mandatoryArguments: 0
    ifElseFi: 0
    items: 0
    keyEqualsValuesBracesBrackets: 0
    namedGroupingBracesBrackets: 0
    UnNamedGroupingBracesBrackets: 0
    specialBeginEnd: 0
    afterHeading: 0
    filecontents: 0

5.3. Commands and the strings between their arguments

The command code blocks will always look for optional (square bracketed) and mandatory (curly braced) arguments which can contain comments, line breaks and ‘beamer’ commands <.*?> between them. There are switches that can allow them to contain other strings, which we discuss next.

commandCodeBlocks: fields

The commandCodeBlocks field *commandCodeBlocks contains a few switches detailed in Listing 167.

Listing 167 commandCodeBlocks
311
312
313
314
315
316
317
318
319
320
321
commandCodeBlocks:
    roundParenthesesAllowed: 1
    stringsAllowedBetweenArguments:
        node: 1
        at: 1
        to: 1
        decoration: 1
        ++: 1
        --: 1
    commandNameSpecial:
        @ifnextchar[: 1

roundParenthesesAllowed: 0|1

The need for this field was mostly motivated by commands found in code used to generate images in PSTricks and tikz; for example, let’s consider the code given in Listing 168.

Listing 168 pstricks1.tex
\defFunction[algebraic]{torus}(u,v)
{(2+cos(u))*cos(v+\Pi)}
{(2+cos(u))*sin(v+\Pi)}
{sin(u)}
Listing 169 pstricks1 default output
\defFunction[algebraic]{torus}(u,v)
{(2+cos(u))*cos(v+\Pi)}
{(2+cos(u))*sin(v+\Pi)}
{sin(u)}

Notice that the \defFunction command has an optional argument, followed by a mandatory argument, followed by a round-parenthesis argument, \((u,v)\).

By default, because roundParenthesesAllowed is set to \(1\) in Listing 167, then latexindent.pl will allow round parenthesis between optional and mandatory arguments. In the case of the code in Listing 168, latexindent.pl finds all the arguments of defFunction, both before and after (u,v).

The default output from running latexindent.pl on Listing 168 actually leaves it unchanged (see Listing 169); note in particular, this is because of noAdditionalIndentGlobal as discussed on .

Upon using the YAML settings in Listing 171, and running the command

latexindent.pl pstricks1.tex -l noRoundParentheses.yaml

we obtain the output given in Listing 170.

Listing 170 pstricks1.tex using Listing 171
\defFunction[algebraic]{torus}(u,v)
{(2+cos(u))*cos(v+\Pi)}
	{(2+cos(u))*sin(v+\Pi)}
	{sin(u)}
Listing 171 noRoundParentheses.yaml
commandCodeBlocks:
    roundParenthesesAllowed: 0

Notice the difference between Listing 169 and Listing 170; in particular, in Listing 170, because round parentheses are not allowed, latexindent.pl finds that the \defFunction command finishes at the first opening round parenthesis. As such, the remaining braced, mandatory, arguments are found to be UnNamedGroupingBracesBrackets (see Table 2) which, by default, assume indentation for their body, and hence the tabbed indentation in Listing 170.

Let’s explore this using the YAML given in Listing 173 and run the command

latexindent.pl pstricks1.tex -l defFunction.yaml

then the output is as in Listing 172.

Listing 172 pstricks1.tex using Listing 173
\defFunction[algebraic]{torus}(u,v)
 {(2+cos(u))*cos(v+\Pi)}
 {(2+cos(u))*sin(v+\Pi)}
 {sin(u)}
Listing 173 defFunction.yaml
indentRules:
    defFunction: 
        body: " "

Notice in Listing 172 that the body of the defFunction command i.e, the subsequent lines containing arguments after the command name, have received the single space of indentation specified by Listing 173.

stringsAllowedBetweenArguments: fields

tikz users may well specify code such as that given in Listing 174; processing this code using latexindent.pl gives the default output in Listing 175.

Listing 174 tikz-node1.tex
\draw[thin] 
(c) to[in=110,out=-90] 
++(0,-0.5cm) 
node[below,align=left,scale=0.5]
Listing 175 tikz-node1 default output
\draw[thin]
(c) to[in=110,out=-90]
++(0,-0.5cm)
node[below,align=left,scale=0.5]

With reference to Listing 167, we see that the strings

to, node, ++

are all allowed to appear between arguments, as they are each set to \(1\); importantly, you are encouraged to add further names to this field as necessary. This means that when latexindent.pl processes Listing 174, it consumes:

  • the optional argument [thin]
  • the round-bracketed argument (c) because roundParenthesesAllowed is \(1\) by default
  • the string to (specified in stringsAllowedBetweenArguments)
  • the optional argument [in=110,out=-90]
  • the string ++ (specified in stringsAllowedBetweenArguments)
  • the round-bracketed argument (0,-0.5cm) because roundParenthesesAllowed is \(1\) by default
  • the string node (specified in stringsAllowedBetweenArguments)
  • the optional argument [below,align=left,scale=0.5]

We can explore this further, for example using Listing 177 and running the command

latexindent.pl tikz-node1.tex -l draw.yaml

we receive the output given in Listing 176.

Listing 176 tikz-node1.tex using Listing 177
\draw[thin]
  (c) to[in=110,out=-90]
  ++(0,-0.5cm)
  node[below,align=left,scale=0.5]
Listing 177 draw.yaml
indentRules:
    draw: 
        body: "  "

Notice that each line after the \draw command (its ‘body’) in Listing 176 has been given the appropriate two-spaces worth of indentation specified in Listing 177.

Let’s compare this with the output from using the YAML settings in Listing 179, and running the command

latexindent.pl tikz-node1.tex -l no-to.yaml

given in Listing 178.

Listing 178 tikz-node1.tex using Listing 179
\draw[thin]
(c) to[in=110,out=-90]
++(0,-0.5cm)
node[below,align=left,scale=0.5]
Listing 179 no-to.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
        to: 0

In this case, latexindent.pl sees that:

  • the \draw command finishes after the (c) as (stringsAllowedBetweenArguments has to set to \(0\))
  • it finds a namedGroupingBracesBrackets called to (see Table 2) with argument [in=110,out=-90]
  • it finds another namedGroupingBracesBrackets but this time called node with argument [below,align=left,scale=0.5]

commandNameSpecial: fields

There are some special command names that do not fit within the names recognized by latexindent.pl, the first one of which is \@ifnextchar[. From the perspective of latexindent.pl, the whole of the text \@ifnextchar[ is is a command, because it is immediately followed by sets of mandatory arguments. However, without the commandNameSpecial field, latexindent.pl would not be able to label it as such, because the [ is, necessarily, not matched by a closing ].

For example, consider the sample file in Listing 180, which has default output in Listing 181.

Listing 180 ifnextchar.tex
\parbox{
\@ifnextchar[{arg 1}{arg 2}
}
Listing 181 ifnextchar.tex default output
\parbox{
	\@ifnextchar[{arg 1}{arg 2}
}

Notice that in Listing 181 the parbox command has been able to indent its body, because latexindent.pl has successfully found the command \@ifnextchar first; the pattern-matching of latexindent.pl starts from the inner most <thing> and works outwards, discussed in more detail on . For demonstration, we can compare this output with that given in Listing 182 in which the settings from Listing 183 have dictated that \@ifnextchar[ command should not be searched for specially; as such, the parbox command has been unable to indent its body successfully, because the \@ifnextchar[ command has not been found.

Listing 182 ifnextchar.tex using Listing 183
\parbox{
\@ifnextchar[{arg 1}{arg 2}
}
Listing 183 no-ifnextchar.yaml
commandCodeBlocks:
    commandNameSpecial:
        @ifnextchar[: 0

“Log4perl Perl Module.” 2017. Accessed September 24. http://search.cpan.org/~mschilli/Log-Log4perl-1.49/lib/Log/Log4perl.pm.

“Text:Tabs Perl Module.” 2017. Accessed July 6. http://search.cpan.org/~muir/Text-Tabs+Wrap-2013.0523/lib.old/Text/Tabs.pm.

Voßkuhle, Michel. 2013. “Remove Trailing White Space.” November 10. https://github.com/cmhughes/latexindent.pl/pull/12.

[1]Throughout this manual, listings shown with line numbers represent code taken directly from defaultSettings.yaml.
[2]Previously this only activated if alignDoubleBackSlash was set to 0.
[3]There is a slight difference in interface for this field when comparing Version 2.2 to Version 3.0; see Section 9.4 for details.
[4]The command code blocks have quite a few subtleties, described in Section 5.3.
[5]You may like to verify this by using the -tt option and checking indent.log!