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.

For most of the settings in defaultSettings.yaml that are specified as integers, then we understand 0 to represent ‘off’ and 1 to represent ‘on’. For fields that allow values other than 0 or 1, it is hoped that the specific context and associated commentary should make it clear which values are allowed.

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 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.

Listing 52 fileExtensionPreference
47fileExtensionPreference:
48  .tex: 1
49  .sty: 2
50  .cls: 3
51  .bib: 4

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

5.1. Backup and log file preferences

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 53. 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 53 logFilePreferences
 90logFilePreferences:
 91  showEveryYamlRead: 1
 92  showAmalgamatedSettings: 0
 93  showDecorationStartCodeBlockTrace: 0
 94  showDecorationFinishCodeBlockTrace: 0
 95  endLogFileWith: '--------------'
 96  showGitHubInfoFooter: 1
 97  Dumper:
 98    Terse: 1
 99    Indent: 1
100    Useqq: 1
101    Deparse: 1
102    Quotekeys: 0
103    Sortkeys: 1
104    Pair: " => "

When either of the trace modes (see page page:traceswitch) 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 12.9.

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.

Note: latexindent.pl no longer uses the log4perl module to handle the creation of the logfile.

Some of the options for Perl’s Dumper module can be specified in Listing 53; see (“Data::Dumper Module” n.d.) and (“Data Dumper Demonstration” n.d.) for more information. These options will mostly be helpful for those calling latexindent.pl with the -tt option described in Section 3.2.

5.2. Verbatim code blocks

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 54.

Listing 54 verbatimEnvironments
108verbatimEnvironments:
109  verbatim: 1
110  lstlisting: 1
111  minted: 1
Listing 55 verbatimCommands
114verbatimCommands:
115  verb: 1
116  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.

You can, optionally, specify the verbatim field using the name field which takes a regular expression as its argument; thank you to (XuehaiPan 2021) for contributing this feature.

Example 10

For demonstration, then assuming that your file contains the environments latexcode, latexcode*, pythoncode and pythoncode*, then the listings given in Listing 56 and Listing 57 are equivalent.

Listing 56 nameAsRegex1.yaml
verbatimEnvironments:
    latexcode: 1
    latexcode*: 1
    pythoncode: 1
    pythoncode*: 1
Listing 57 nameAsRegex2.yaml
verbatimEnvironments:
    nameAsRegex:
      name: '\w+code\*?'
      lookForThis: 1

With reference to Listing 57:

  • the name field as specified here means any word followed by the word code, optionally followed by *;

  • we have used nameAsRegex to identify this field, but you can use any description you like;

  • the lookForThis field is optional, and can take the values 0 (off) or 1 (on); by default, it is assumed to be 1 (on).

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).

With reference to Listing 55, by default latexindent.pl looks for \verb immediately followed by another character, and then it takes the body as anything up to the next occurrence of the character; this means that, for example, \verb!x+3! is treated as a verbatimCommands.

You can, optionally, specify the verbatimCommands field using the name field which takes a regular expression as its argument; thank you to (XuehaiPan 2021) for contributing this feature.

Example 11

For demonstration, then assuming that your file contains the commands verbinline, myinline then the listings given in Listing 58 and Listing 59 are equivalent.

Listing 58 nameAsRegex3.yaml
verbatimCommands:
    verbinline: 1
    myinline: 1
Listing 59 nameAsRegex4.yaml
verbatimCommands:
    nameAsRegex:
      name: '\w+inline'
      lookForThis: 1

With reference to Listing 59:

  • the name field as specified here means any word followed by the word inline;

  • we have used nameAsRegex to identify this field, but you can use any description you like;

  • the lookForThis field is optional, and can take the values 0 (off) or 1 (on); by default, it is assumed to be 1 (on).

noIndentBlock:fields

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 60.

Listing 60 noIndentBlock
121noIndentBlock:
122  noindent: 1
123  cmhtest: 1

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 61 for example.

Listing 61 noIndentBlock.tex
% \begin{noindent}
some before text
        this code
                won't
     be touched
                    by
             latexindent.pl!
some after text 
% \end{noindent}

Important note: it is assumed that the noindent block statements specified in this way appear on their own line.

Example 12

The noIndentBlock fields can also be specified in terms of begin and end fields. We use the code in Listing 62 to demonstrate this feature.

Listing 62 noIndentBlock1.tex
some before text
        this code
                won't
     be touched
                    by
             latexindent.pl!
some after text 

The settings given in Listing 63 and Listing 64 are equivalent:

Listing 63 noindent1.yaml
noIndentBlock:
    demo:
        begin: 'some\hbefore'
        body: '.*?'
        end: 'some\hafter\htext'
        lookForThis: 1
Listing 64 noindent2.yaml
noIndentBlock:
    demo:
        begin: 'some\hbefore'
        end: 'some\hafter\htext'
Listing 65 noindent3.yaml
noIndentBlock:
    demo:
        begin: 'some\hbefore'
        body: '.*?'
        end: 'some\hafter\htext'
        lookForThis: 0

Upon running the commands

latexindent.pl -l noindent1.yaml noindent1
latexindent.pl -l noindent2.yaml noindent1

then we receive the output given in Listing 66.

Listing 66 noIndentBlock1.tex using Listing 63 or Listing 64
some before text
        this code
                won't
     be touched
                    by
             latexindent.pl!
some after text

The begin, body and end fields for noIndentBlock are all regular expressions. If the body field is not specified, then it takes a default value of .*? which is written explicitly in Listing 63. In this context, we interpret .*? in words as the fewest number of characters (possibly none) until the ‘end’ field is reached.

The lookForThis field is optional, and can take the values 0 (off) or 1 (on); by default, it is assumed to be 1 (on).

Example 13

Using Listing 65 demonstrates setting lookForThis to 0 (off); running the command

latexindent.pl -l noindent3.yaml noindent1

gives the output in Listing 67.

Listing 67 noIndentBlock1.tex using Listing 65
some before text
this code
won't
be touched
by
latexindent.pl!
some after text

We will demonstrate this feature later in the documentation in Listing 610.

You can, optionally, specify the noIndentBlock field using the name field which takes a regular expression as its argument; thank you to (XuehaiPan 2021) for contributing this feature.

Example 14

For demonstration, then assuming that your file contains the environments testnoindent, testnoindent* then the listings given in Listing 68 and Listing 69 are equivalent.

Listing 68 nameAsRegex5.yaml
noIndentBlock:
    mytest:
      begin: '\\begin\{testnoindent\*?\}'
      end: '\\end\{testnoindent\*?\}'
Listing 69 nameAsRegex6.yaml
noIndentBlock:
    nameAsRegex:
      name: '\w+noindent\*?'
      lookForThis: 1

With reference to Listing 69:

  • the name field as specified here means any word followed by the word noindent, optionally followed by *;

  • we have used nameAsRegex to identify this field, but you can use any description you like;

  • the lookForThis field is optional, and can take the values 0 (off) or 1 (on); by default, it is assumed to be 1 (on).

5.3. filecontents and preamble

fileContentsEnvironments:field

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 70. The behaviour of latexindent.pl on these environments is determined by their location (preamble or not), and the value indentPreamble, discussed next.

Listing 70 fileContentsEnvironments
127fileContentsEnvironments:
128  filecontents: 1
129  filecontents*: 1
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

Not all files contain preamble; for example, sty, cls and bib files typically do not. Referencing Listing 71, 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.

Listing 71 lookForPreamble
135lookForPreamble:
136  .tex: 1
137  .sty: 0
138  .cls: 0
139  .bib: 0
140  STDIN: 1
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 72.

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

5.4. Indentation and horizontal space

defaultIndent:horizontal space

This is the default indentation used in the absence of other details for the code block with which we are working. The default value is \t which means a tab; we will explore customisation beyond defaultIndent in Section 5.8.

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

removeTrailingWhitespace:fields

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

Listing 73 removeTrailingWhitespace
153removeTrailingWhitespace:
154  beforeProcessing: 0
155  afterProcessing: 1
Listing 74 removeTrailingWhitespace (alt)
removeTrailingWhitespace: 1

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 74.

5.5. Aligning at delimiters

lookForAlignDelims:fields

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

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

Specifying code blocks in this field instructs latexindent.pl to try and align each column by its alignment delimiters. It does have some limitations (discussed further in Section 10), but in many cases it will produce results such as those in Listing 76 and Listing 77; running the command

latexindent.pl tabular1.tex

gives the output given in Listing 77.

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

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 60).

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 78 is for you.

Listing 78 lookForAlignDelims (advanced)
158lookForAlignDelims:
159  tabular:
160    delims: 1
161    alignDoubleBackSlash: 1
162    spacesBeforeDoubleBackSlash: 1
163    multiColumnGrouping: 0
164    alignRowsWithoutMaxDelims: 1
165    spacesBeforeAmpersand: 1
166    spacesAfterAmpersand: 1
167    justification: left
168    alignFinalDoubleBackSlash: 0
169    dontMeasure: 0
170    delimiterRegEx: (?<!\\)(&)
171    delimiterJustification: left
172    lookForChildCodeBlocks: 1
173    alignContentAfterDoubleBackSlash: 0
174    spacesAfterDoubleBackSlash: 1
175  tabularx:
176    delims: 1

Note that you can use a mixture of the basic and advanced form: in Listing 78 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 75. 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, specifies the number (integer \(\geq\) 0) of spaces to be inserted before \\ (default: 1);

  • 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 delimiters 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);

  • alignFinalDoubleBackSlash optionally specifies if the final double backslash should be used for alignment (default: 0);

  • dontMeasure optionally specifies if user-specified cells, rows or the largest entries should not be measured (default: 0);

  • delimiterRegEx optionally specifies the pattern matching to be used for the alignment delimiter (default: (?<!\\)(&)*);

  • delimiterJustification optionally specifies the justification for the alignment delimiters (default: left); note that this feature is only useful if you have delimiters of different lengths in the same column, discussed in Section 5.5.4;

  • lookForChildCodeBlocks optionally instructs latexindent.pl to search for child code blocks or not (default: 1), discussed in Section 5.5.5;

  • alignContentAfterDoubleBackSlash optionally instructs latexindent.pl to align content after double back slash (default: 0), discussed in Section 5.5.6;

  • spacesAfterDoubleBackSlash optionally specifies the number (integer \(\geq\) 0) of spaces to be placed after the double back slash when alignContentAfterDoubleBackSlash is active; demonstrated in Section 5.5.6.

Example 15

We will explore most of these features using the file tabular2.tex in Listing 79 (which contains a \multicolumn command), and the YAML files in Listing 80Listing 86; we will explore alignFinalDoubleBackSlash in Listing 107; the dontMeasure feature will be described in Section 5.5.3, and delimiterRegEx in Section 5.5.4.

Listing 79 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 80 tabular2.yaml
lookForAlignDelims:
   tabular: 
      multiColumnGrouping: 1
Listing 81 tabular3.yaml
lookForAlignDelims:
   tabular: 
      alignRowsWithoutMaxDelims: 0
Listing 82 tabular4.yaml
lookForAlignDelims:
   tabular: 
      spacesBeforeAmpersand: 4
Listing 83 tabular5.yaml
lookForAlignDelims:
   tabular: 
      spacesAfterAmpersand: 4
Listing 84 tabular6.yaml
lookForAlignDelims:
   tabular: 
      alignDoubleBackSlash: 0
Listing 85 tabular7.yaml
lookForAlignDelims:
   tabular: 
      spacesBeforeDoubleBackSlash: 0
Listing 86 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 87Listing 94.

Listing 87 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 88 tabular2.tex using Listing 80
\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 89 tabular2.tex using Listing 81
\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 90 tabular2.tex using Listing 80 and Listing 82
\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 91 tabular2.tex using Listing 80 and Listing 83
\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 92 tabular2.tex using Listing 80 and Listing 84
\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 93 tabular2.tex using Listing 80 and Listing 85
\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 94 tabular2.tex using Listing 80 and Listing 86
\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 87 and Listing 88 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 87 the columns have been aligned at the ampersand;

  • in Listing 88 the \multicolumn command has grouped the \(2\) columns beneath and above it, because multiColumnGrouping is set to \(1\) in Listing 80;

  • in Listing 89 rows 3 and 6 have not been aligned at the ampersand, because alignRowsWithoutMaxDelims has been to set to \(0\) in Listing 81; however, the \\ have still been aligned;

  • in Listing 90 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 91 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 92 the \\ have not been aligned, because alignDoubleBackSlash is set to 0, otherwise the output is the same as Listing 88;

  • in Listing 93 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 88;

  • in Listing 94 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 80.

5.5.1. lookForAlignDelims: spacesBeforeAmpersand

The spacesBeforeAmpersand can be specified in a few different ways. The basic form is demonstrated in Listing 82, but we can customise the behaviour further by specifying if we would like this value to change if it encounters a leading blank column; that is, when the first column contains only zero-width entries. We refer to this as the advanced form.

Example 16

We demonstrate this feature in relation to Listing 95; upon running the following command

latexindent.pl aligned1.tex -o=+-default

then we receive the default output given in Listing 96.

Listing 95 aligned1.tex
\begin{aligned}
& a & b, \\
& c & d.
\end{aligned}
Listing 96 aligned1-default.tex
\begin{aligned}
	 & a & b, \\
	 & c & d.
\end{aligned}

The settings in Listing 97Listing 100 are all equivlanent; we have used the not-yet discussed noAdditionalIndent field (see Section 5.8) which will assist in the demonstration in what follows.

Listing 97 sba1.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 1
Listing 98 sba2.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand: 1
Listing 99 sba3.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand:
        default: 1
Listing 100 sba4.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand:
        leadingBlankColumn: 1

Upon running the following commands

latexindent.pl aligned1.tex -l sba1.yaml
latexindent.pl aligned1.tex -l sba2.yaml
latexindent.pl aligned1.tex -l sba3.yaml
latexindent.pl aligned1.tex -l sba4.yaml

then we receive the (same) output given in Listing 101; we note that there is one space before each ampersand.

Listing 101 aligned1-mod1.tex
\begin{aligned}
 & a & b, \\
 & c & d.
\end{aligned}

We note in particular:

  • Listing 97 demonstrates the basic form for lookForAlignDelims; in this case, the default values are specified as in Listing 78;

  • Listing 98 demonstrates the advanced form for lookForAlignDelims and specified spacesBeforeAmpersand. The default value is 1;

  • Listing 99 demonstrates the new advanced way to specify spacesBeforeAmpersand, and for us to set the default value that sets the number of spaces before ampersands which are not in leading blank columns. The default value is 1.

    We note that leadingBlankColumn has not been specified in Listing 99, and it will inherit the value from default;

  • Listing 100 demonstrates spaces to be used before amperands for leading blank columns. We note that default has not been specified, and it will be set to 1 by default.

Example 17

We can customise the space before the ampersand in the leading blank column of Listing 101 by using either of Listing 102 and Listing 103, which are equivalent.

Listing 102 sba5.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand:
        leadingBlankColumn: 0
Listing 103 sba6.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand:
        leadingBlankColumn: 0
        default: 1

Upon running

latexindent.pl aligned1.tex -l sba5.yaml
latexindent.pl aligned1.tex -l sba6.yaml

then we receive the (same) output given in Listing 104. We note that the space before the ampersand in the leading blank column has been set to 0 by Listing 103.

We can demonstrated this feature further using the settings in Listing 106 which give the output in Listing 105.

Listing 104 aligned1-mod5.tex
\begin{aligned}
& a & b, \\
& c & d.
\end{aligned}
Listing 105 aligned1.tex using Listing 106
\begin{aligned}
   & a& b, \\
   & c& d.
\end{aligned}
Listing 106 sba7.yaml
noAdditionalIndent:
  aligned: 1
lookForAlignDelims:
   aligned: 
      spacesBeforeAmpersand:
        leadingBlankColumn: 3
        default: 0

5.5.2. lookForAlignDelims: alignFinalDoubleBackSlash

There may be times when a line of a code block contains more than \\, and in which case, you may want the final double backslash to be aligned.

Example 18

We explore the alignFinalDoubleBackSlash feature by using the file in Listing 107. Upon running the following commands

latexindent.pl tabular4.tex -o=+-default
latexindent.pl tabular4.tex -o=+-FDBS -y="lookForAlignDelims:tabular:alignFinalDoubleBackSlash:1"

then we receive the respective outputs given in Listing 108 and Listing 109.

Listing 107 tabular4.tex
\begin{tabular}{lc}
    Name & \shortstack{Hi \\ Lo} \\
    Foo  & Bar            \\
\end{tabular}
Listing 108 tabular4-default.tex
\begin{tabular}{lc}
	Name & \shortstack{Hi \\ Lo} \\
	Foo  & Bar            \\
\end{tabular}
Listing 109 tabular4-FDBS.tex
\begin{tabular}{lc}
	Name & \shortstack{Hi \\ Lo} \\
	Foo  & Bar                   \\
\end{tabular}

We note that in:

  • Listing 108, by default, the first set of double back slashes in the first row of the tabular environment have been used for alignment;

  • Listing 109, the final set of double backslashes in the first row have been used, because we specified alignFinalDoubleBackSlash as 1.

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 page yaml:specialBeginEnd).

Example 19

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 110 and Listing 111 are achievable by default.

Listing 110 matrix1.tex
\matrix [
	1&2   &3\\
4&5&6]{
7&8   &9\\
10&11&12
}
Listing 111 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 112; the default output is shown in Listing 113. 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 112 align-block.tex
%* \begin{tabular}
   1 & 2 & 3 & 4 \\
   5 &   & 6 &   \\
  %* \end{tabular}
Listing 113 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.8), these comment-marked blocks are considered environments.

5.5.3. lookForAlignDelims: the dontMeasure feature

The lookForAlignDelims field can, optionally, receive the dontMeasure option which can be specified in a few different ways.

Example 20

We will explore this feature in relation to the code given in Listing 114; the default output is shown in Listing 115.

Listing 114 tabular-DM.tex
\begin{tabular}{cccc}
  aaaaaa&bbbbb&ccc&dd\\
  11&2&33&4\\
  5&66&7&8
\end{tabular}
Listing 115 tabular-DM.tex default output
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11     & 2     & 33  & 4  \\
	5      & 66    & 7   & 8
\end{tabular}

The dontMeasure field can be specified as largest, and in which case, the largest element will not be measured; with reference to the YAML file given in Listing 117, we can run the command

latexindent.pl tabular-DM.tex -l=dontMeasure1.yaml

and receive the output given in Listing 116.

Listing 116 tabular-DM.tex using Listing 117
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11 & 2  & 33 & 4          \\
	5  & 66 & 7  & 8
\end{tabular}
Listing 117 dontMeasure1.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure: largest

We note that the largest column entries have not contributed to the measuring routine.

Example 21

The dontMeasure field can also be specified in the form demonstrated in Listing 119. On running the following commands,

latexindent.pl tabular-DM.tex -l=dontMeasure2.yaml

we receive the output in Listing 118.

Listing 118 tabular-DM.tex using Listing 119 or Listing 121
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11 & 2  & 33 & 4          \\
	5  & 66 & 7  & 8
\end{tabular}
Listing 119 dontMeasure2.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure:
        - aaaaaa
        - bbbbb
        - ccc
        - dd

We note that in Listing 119 we have specified entries not to be measured, one entry per line.

Example 22

The dontMeasure field can also be specified in the forms demonstrated in Listing 121 and Listing 122. Upon running the commands

latexindent.pl tabular-DM.tex -l=dontMeasure3.yaml
latexindent.pl tabular-DM.tex -l=dontMeasure4.yaml

we receive the output given in Listing 120

Listing 120 tabular-DM.tex using Listing 121 or Listing 121
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11 & 2  & 33 & 4          \\
	5  & 66 & 7  & 8
\end{tabular}
Listing 121 dontMeasure3.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure:
        - 
          this: aaaaaa
          applyTo: cell
        - 
          this: bbbbb
        - ccc
        - dd
Listing 122 dontMeasure4.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure:
        - 
          regex: [a-z]
          applyTo: cell

We note that in:

  • Listing 121 we have specified entries not to be measured, each one has a string in the this field, together with an optional specification of applyTo as cell;

  • Listing 122 we have specified entries not to be measured as a regular expression using the regex field, together with an optional specification of applyTo as cell field, together with an optional specification of applyTo as cell.

In both cases, the default value of applyTo is cell, and does not need to be specified.

Example 23

We may also specify the applyTo field as row, a demonstration of which is given in Listing 124; upon running

latexindent.pl tabular-DM.tex -l=dontMeasure5.yaml

we receive the output in Listing 123.

Listing 123 tabular-DM.tex using Listing 124
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11 & 2  & 33 & 4          \\
	5  & 66 & 7  & 8
\end{tabular}
Listing 124 dontMeasure5.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure:
        - 
          this: aaaaaa&bbbbb&ccc&dd\\
          applyTo: row
Example 24

Finally, the applyTo field can be specified as row, together with a regex expression. For example, for the settings given in Listing 126, upon running

latexindent.pl tabular-DM.tex -l=dontMeasure6.yaml

we receive the output in Listing 125.

Listing 125 tabular-DM.tex using Listing 126
\begin{tabular}{cccc}
	aaaaaa & bbbbb & ccc & dd \\
	11 & 2  & 33 & 4          \\
	5  & 66 & 7  & 8
\end{tabular}
Listing 126 dontMeasure6.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure:
        - 
          regex: [a-z]
          applyTo: row

5.5.4. lookForAlignDelims: the delimiterRegEx and delimiterJustification feature

The delimiter alignment will, by default, align code blocks at the ampersand character. The behaviour is controlled by the delimiterRegEx field within lookForAlignDelims; the default value is (?<!\\)(&)*, which can be read as: an ampersand, as long as it is not immediately preceded by a backslash.

Warning

Important: note the ‘capturing’ parenthesis in the (&) which are necessary; if you intend to customise this field, then be sure to include them appropriately.

Example 25

We demonstrate how to customise this with respect to the code given in Listing 127; the default output from latexindent.pl is given in Listing 128.

Listing 127 tabbing.tex
\begin{tabbing}
    aa \=   bb \= cc \= dd \= ee \\
    \>2\> 1 \> 7 \> 3 \\
    \>3 \> 2\>8\> 3 \\
    \>4 \>2 \\
\end{tabbing}
Listing 128 tabbing.tex default output
\begin{tabbing}
	aa \=   bb \= cc \= dd \= ee \\
	\>2\> 1 \> 7 \> 3 \\
	\>3 \> 2\>8\> 3 \\
	\>4 \>2 \\
\end{tabbing}

Let’s say that we wish to align the code at either the \= or \>. We employ the settings given in Listing 130 and run the command

latexindent.pl tabbing.tex -l=delimiterRegEx1.yaml

to receive the output given in Listing 129.

Listing 129 tabbing.tex using Listing 130
\begin{tabbing}
	aa \= bb \= cc \= dd \= ee \\
	   \> 2  \> 1  \> 7  \> 3  \\
	   \> 3  \> 2  \> 8  \> 3  \\
	   \> 4  \> 2              \\
\end{tabbing}
Listing 130 delimiterRegEx1.yaml
lookForAlignDelims:
   tabbing: 
    delimiterRegEx: '(\\(?:=|>))'

We note that:

  • in Listing 129 the code has been aligned, as intended, at both the \= and \>;

  • in Listing 130 we have heeded the warning and captured the expression using grouping parenthesis, specified a backslash using \\ and said that it must be followed by either = or >.

Example 26

We can explore delimiterRegEx a little further using the settings in Listing 132 and run the command

latexindent.pl tabbing.tex -l=delimiterRegEx2.yaml

to receive the output given in Listing 131.

Listing 131 tabbing.tex using Listing 132
\begin{tabbing}
	aa \=   bb \= cc \= dd \= ee \\
	 \> 2 \> 1 \> 7 \> 3         \\
	 \> 3 \> 2 \> 8 \> 3         \\
	 \> 4 \> 2                   \\
\end{tabbing}
Listing 132 delimiterRegEx2.yaml
lookForAlignDelims:
   tabbing: 
    delimiterRegEx: '(\\>)'

We note that only the \> have been aligned.

Example 27

Of course, the other lookForAlignDelims options can be used alongside the delimiterRegEx; regardless of the type of delimiter being used (ampersand or anything else), the fields from Listing 78 remain the same; for example, using the settings in Listing 134, and running

latexindent.pl tabbing.tex -l=delimiterRegEx3.yaml

to receive the output given in Listing 133.

Listing 133 tabbing.tex using Listing 134
\begin{tabbing}
	aa\=bb\=cc\=dd\=ee \\
	  \>2 \>1 \>7 \>3  \\
	  \>3 \>2 \>8 \>3  \\
	  \>4 \>2          \\
\end{tabbing}
Listing 134 delimiterRegEx3.yaml
lookForAlignDelims:
   tabbing: 
    delimiterRegEx: '(\\(?:=|>))'
    spacesBeforeAmpersand: 0
    spacesAfterAmpersand: 0
Example 28

It is possible that delimiters specified within delimiterRegEx can be of different lengths. Consider the file in Listing 135, and associated YAML in Listing 137. Note that the Listing 137 specifies the option for the delimiter to be either # or \>, which are different lengths. Upon running the command

latexindent.pl tabbing1.tex -l=delimiterRegEx4.yaml -o=+-mod4

we receive the output in Listing 136.

Listing 135 tabbing1.tex
\begin{tabbing}
    1#22\>333\\
    xxx#aaa#yyyyy\\
    .##&\\
\end{tabbing}
Listing 136 tabbing1-mod4.tex
\begin{tabbing}
	1   # 22  \> 333   \\
	xxx # aaa #  yyyyy \\
	.   #     #  &     \\
\end{tabbing}
Listing 137 delimiterRegEx4.yaml
lookForAlignDelims:
   tabbing: 
    delimiterRegEx: '(#|\\>)'
Example 29

You can set the delimiter justification as either left (default) or right, which will only have effect when delimiters in the same column have different lengths. Using the settings in Listing 139 and running the command

latexindent.pl tabbing1.tex -l=delimiterRegEx5.yaml -o=+-mod5

gives the output in Listing 138.

Listing 138 tabbing1-mod5.tex
\begin{tabbing}
	1   # 22  \> 333   \\
	xxx # aaa  # yyyyy \\
	.   #      # &     \\
\end{tabbing}
Listing 139 delimiterRegEx5.yaml
lookForAlignDelims:
   tabbing: 
    delimiterRegEx: '(#|\\>)'
    delimiterJustification: right

Note that in Listing 138 the second set of delimiters have been right aligned – it is quite subtle!

5.5.5. lookForAlignDelims: lookForChildCodeBlocks

There may be scenarios in which you would prefer to instruct latexindent.pl not to search for child blocks; in which case setting lookForChildCodeBlocks to 0 may be a good way to proceed.

Example 30

Using the settings from Listing 117 on the file in Listing 140 and running the command

latexindent.pl tabular-DM-1.tex -l=dontMeasure1.yaml -o=+-mod1

gives the output in Listing 141.

Listing 140 tabular-DM-1.tex
\begin{tabular}{cc}
1&2\only<2->{\\
3&4}
\end{tabular}
Listing 141 tabular-DM-1-mod1.tex
\begin{tabular}{cc}
	1 & 2\only<2->{ \\
		3 & 4}
\end{tabular}

We can improve the output from Listing 141 by employing the settings in Listing 143

latexindent.pl tabular-DM-1.tex -l=dontMeasure1a.yaml -o=+-mod1a

which gives the output in Listing 143.

Listing 142 tabular-DM-1-mod1a.tex
\begin{tabular}{cc}
	1 & 2\only<2->{ \\
	3 & 4}
\end{tabular}
Listing 143 dontMeasure1a.yaml
lookForAlignDelims:
   tabular: 
      dontMeasure: largest
      lookForChildCodeBlocks: 0

5.5.6. lookForAlignDelims: alignContentAfterDoubleBackSlash

You can instruct latexindent to align content after the double back slash. See also Section 6.3.2.

Example 31

We consider the file in Listing 144, and the default output given in Listing 145.

Listing 144 tabular5.tex
\begin{tabular}{cc}
  1 & 2
  \\ aa & bbb
  \\ ccc&ddd
\end{tabular}
Listing 145 tabular5-default.tex
\begin{tabular}{cc}
	1 & 2
	\\ aa & bbb
	\\ ccc&ddd
\end{tabular}

Using the settings given in Listing 147 and running

latexindent.pl -s tabular5.tex -l alignContentAfterDBS1 -o=+-mod1

gives the output in Listing 146.

Listing 146 tabular5-mod1.tex
\begin{tabular}{cc}
	   1   & 2
	\\ aa  & bbb
	\\ ccc & ddd
\end{tabular}
Listing 147 alignContentAfterDBS1.yaml
lookForAlignDelims:
   tabular:
      alignContentAfterDoubleBackSlash: 1
Example 32

When using the alignContentAfterDoubleBackSlash feature, then you can also specify how many spaces to insert after the double backslash; the default is 1. Starting from Listing 144 and using the the settings given in Listing 149

latexindent.pl -s tabular5.tex -l alignContentAfterDBS2 -o=+-mod2

gives the output in Listing 148.

Listing 148 tabular5-mod2.tex
\begin{tabular}{cc}
	     1   & 2
	\\   aa  & bbb
	\\   ccc & ddd
\end{tabular}
Listing 149 alignContentAfterDBS2.yaml
lookForAlignDelims:
   tabular:
      alignContentAfterDoubleBackSlash: 1
      spacesAfterDoubleBackSlash: 3

5.6. Indent after items, specials and headings

indentAfterItems:fields

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 151 and Listing 152

Listing 150 indentAfterItems
241indentAfterItems:
242  itemize: 1
243  itemize*: 1
244  enumerate: 1
245  enumerate*: 1
246  description: 1
247  description*: 1
248  list: 1
Listing 151 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 152 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
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 45
in particular

.)

Listing 153 itemNames
254itemNames:
255  item: 1
256  myitem: 1
specialBeginEnd:fields

The fields specified

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 154 shows the default settings of specialBeginEnd.

Listing 154 specialBeginEnd
260specialBeginEnd:
261  displayMath:
262    begin: (?<!\\)\\\[            # \[ but *not* \\[
263    end: \\\]                     # \]
264    lookForThis: 1
265  inlineMath:
266    begin: (?<!\$)(?<!\\)\$(?!\$) # $ but *not* \$ or $$
267    body: [^$]*?                  # anything *except* $
268    end: (?<!\\)\$(?!\$)          # $ but *not* \$ or $$
269    lookForThis: 1
270  displayMathTeX:
271    begin: \$\$                   # $$
272    end: \$\$                     # $$
273    lookForThis: 1
274  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.

Example 33

A demonstration of the before-and-after results are shown in Listing 155 and Listing 156; explicitly, running the command

latexindent.pl special1.tex -o=+-default

gives the output given in Listing 156.

Listing 155 special1.tex before
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
g(x)=f(2x)
$
Listing 156 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.

Example 34

For example, consider the file shown in Listing 157.

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

Now consider the YAML files shown in Listing 158 and Listing 159

Listing 158 specialsLeftRight.yaml
specialBeginEnd:
    leftRightSquare:
        begin: '\\left\['
        end: '\\right\]'
        lookForThis: 1
Listing 159 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 160 and Listing 161.

Listing 160 specialLR.tex using Listing 158
\begin{equation}
	\left[
		\sqrt{
			a+b
		}
		\right]
\end{equation}
Listing 161 specialLR.tex using Listing 158 and Listing 159
\begin{equation}
	\left[
		\sqrt{
			a+b
		}
	\right]
\end{equation}

Notice that in:

  • Listing 160 the \left has been treated as a command, with one optional argument;

  • Listing 161 the specialBeginEnd pattern in Listing 158 has been obeyed because Listing 159 specifies that the specialBeginEnd should be sought before commands.

You can, optionally, specify the middle field for anything that you specify in specialBeginEnd.

Example 35

For example, let’s consider the .tex file in Listing 162.

Listing 162 special2.tex
\If
something 0
\ElsIf 
something 1 
\ElsIf
something 2 
\ElsIf
something 3
\Else
something 4
\EndIf

Upon saving the YAML settings in Listing 164 and Listing 166 and running the commands

latexindent.pl special2.tex -l=middle
latexindent.pl special2.tex -l=middle1

then we obtain the output given in Listing 163 and Listing 165.

Listing 163 special2.tex using Listing 164
\If
	something 0
\ElsIf
	something 1
\ElsIf
	something 2
\ElsIf
	something 3
	\Else
	something 4
\EndIf
Listing 164 middle.yaml
specialBeginEnd:
    If:
        begin: '\\If'
        middle: '\\ElsIf'
        end: '\\EndIf'
        lookForThis: 1
Listing 165 special2.tex using Listing 166
\If
	something 0
\ElsIf
	something 1
\ElsIf
	something 2
\ElsIf
	something 3
\Else
	something 4
\EndIf
Listing 166 middle1.yaml
specialBeginEnd:
    If:
        begin: '\\If'
        middle: 
          - '\\ElsIf'
          - '\\Else'
        end: '\\EndIf'
        lookForThis: 1

We note that:

  • in Listing 163 the bodies of each of the Elsif statements have been indented appropriately;

  • the Else statement has not been indented appropriately in Listing 163 – read on!

  • we have specified multiple settings for the middle field using the syntax demonstrated in Listing 166 so that the body of the Else statement has been indented appropriately in Listing 165.

You may need these fields in your own YAML files (see Section 4.2), if you use popular algorithm packages such as algorithms, algorithm2e or algpseudocode, etc.

Example 36

For example, let’s consider the .tex file in Listing 167.

Listing 167 specialAlgo.tex
\For{$n = 1, \dots, 10$}
\State body
\EndFor
\FOR{for 1}
\FOR{for 2}
\FOR{for 3}
\STATE{some statement.}
\ENDFOR
\ENDFOR
\ENDFOR
\If{$quality\ge 9$}
\State $a\gets perfect$
\ElsIf{$quality\ge 7$}
\State $a\gets good$
\Else
\While{$i\le n$}
\State $i\gets i+1$
\EndWhile
\EndIf
\ForAll{$n \in \{1, \dots, 10\}$}
\State body
\Loop
\State body
\EndLoop
\State $i\gets 1$
\Repeat
\State $i\gets i+1$
\Until{$i>n$}
\EndFor
\Function{Euclid}{$a,b$}\Comment{The g.c.d. of a and b}
\While{$r\not=0$}\Comment{We have the answer if r is 0}
\State $r\gets a\bmod b$
\EndWhile
\State \textbf{return} $b$\Comment{The gcd is b}
\EndFunction

Upon saving the YAML settings in Listing 169 and running the command

latexindent.pl -l=algo.yaml specialAlgo.tex

then we obtain the output given in Listing 168.

Listing 168 specialAlgo.tex using Listing 169
\For{$n = 1, \dots, 10$}
	\State body
\EndFor
\FOR{for 1}
	\FOR{for 2}
		\FOR{for 3}
			\STATE{some statement.}
		\ENDFOR
	\ENDFOR
\ENDFOR
\If{$quality\ge 9$}
	\State $a\gets perfect$
\ElsIf{$quality\ge 7$}
	\State $a\gets good$
\Else
	\While{$i\le n$}
		\State $i\gets i+1$
	\EndWhile
\EndIf
\ForAll{$n \in \{1, \dots, 10\}$}
	\State body
	\Loop
		\State body
	\EndLoop
	\State $i\gets 1$
	\Repeat
		\State $i\gets i+1$
	\Until{$i>n$}
\EndFor
\Function{Euclid}{$a,b$}\Comment{The g.c.d. of a and b}
	\While{$r\not=0$}\Comment{We have the answer if r is 0}
		\State $r\gets a\bmod b$
	\EndWhile
	\State \textbf{return} $b$\Comment{The gcd is b}
\EndFunction
Listing 169 algo.yaml
specialBeginEnd:
  ForStatement:
    begin: \\For\{[^}]+?\}
    end: \\EndFor
  FORStatement:
    begin: \\FOR\{[^}]+?\}
    end: \\ENDFOR
  WhileStatement:
    begin: \\While\{[^}]+?\}
    end: \\EndWhile
  WHILEStatement:
    begin: \\WHILE\{[^}]+?\}
    end: \\ENDWHILE
  ForAllStatement:
    begin: \\ForAll\{[^}]+?\}
    end: \\EndFor
  LoopStatement:
    begin: \\Loop
    end: \\EndLoop
  RepeatStatement:
    begin: \\Repeat
    end: \\Until\{[^}]+?\}
  ProcedureStatement:
    begin: \\Procedure\{[^}]+?\}\{[^}]+?\}
    end: \\EndProcedure
  FunctionStatement:
    begin: \\Function\{[^}]+?\}\{[^}]+?\}
    end: \\EndFunction
  IfStatement:
    begin: \\If\{[^}]+?\}
    middle:
      - \\Else
      - \\ElsIf\{[^}]+?\}
    end: \\EndIf
  IFStatement:
    begin: \\IF\{[^}]+?\}
    middle:
      - \\ELSE
      - \\ELSIF\{[^}]+?\}
    end: \\ENDIF
  specialBeforeCommand: 1

You may specify fields in specialBeginEnd to be treated as verbatim code blocks by changing lookForThis to be verbatim.

Example 37

For example, beginning with the code in Listing 170 and the YAML in Listing 171, and running

latexindent.pl special3.tex -l=special-verb1

then the output in Listing 170 is unchanged.

Listing 170 special3.tex and output using Listing 171
\[
  special code 
blocks
    can be
  treated
    as verbatim\]
Listing 171 special-verb1.yaml
specialBeginEnd:
    displayMath:
        lookForThis: verbatim

We can combine the specialBeginEnd with the lookForAlignDelims feature.

Example 38

We begin with the code in Listing 172.

Listing 172 special-align.tex
\begin{tikzpicture}
  \path (A) edge node {0,1,L}(B)
  edge node {1,1,R} (C)
  (B) edge [loop above]node {1,1,L}(B)
  edge node {0,1,L}(C)
  (C) edge node {0,1,L}(D)
  edge [bend left]node {1,0,R}(E)
  (D) edge[loop below] node {1,1,R}(D)
  edge node {0,1,R}(A)
  (E) edge[bend left] node {1,0,R} (A);
\end{tikzpicture}

Let’s assume that our goal is to align the code at the edge and node text; we employ the code given in Listing 174 and run the command

latexindent.pl special-align.tex -l edge-node1.yaml -o=+-mod1

to receive the output in Listing 173.

Listing 173 special-align.tex using Listing 174
\begin{tikzpicture}
	\path (A) edge              node {0,1,L}(B)
	          edge              node {1,1,R} (C)
	      (B) edge [loop above] node {1,1,L}(B)
	          edge              node {0,1,L}(C)
	      (C) edge              node {0,1,L}(D)
	          edge [bend left]  node {1,0,R}(E)
	      (D) edge [loop below] node {1,1,R}(D)
	          edge              node {0,1,R}(A)
	      (E) edge [bend left]  node {1,0,R} (A);
\end{tikzpicture}
Listing 174 edge-node1.yaml
specialBeginEnd:
    path:
        begin: '\\path'
        end: ';'
        lookForThis: 1
    specialBeforeCommand: 1

lookForAlignDelims:
   path: 
      delimiterRegEx: '(edge|node)'

The output in Listing 173 is not quite ideal. We can tweak the settings within Listing 174 in order to improve the output; in particular, we employ the code in Listing 176 and run the command

latexindent.pl special-align.tex -l edge-node2.yaml -o=+-mod2

to receive the output in Listing 175.

Listing 175 special-align.tex using Listing 176
\begin{tikzpicture}
	\path (A) edge              node {0,1,L} (B)
	          edge              node {1,1,R} (C)
	      (B) edge [loop above] node {1,1,L} (B)
	          edge              node {0,1,L} (C)
	      (C) edge              node {0,1,L} (D)
	          edge [bend left]  node {1,0,R} (E)
	      (D) edge [loop below] node {1,1,R} (D)
	          edge              node {0,1,R} (A)
	      (E) edge [bend left]  node {1,0,R} (A);
\end{tikzpicture}
Listing 176 edge-node2.yaml
specialBeginEnd:
    path:
        begin: '\\path'
        end: ';'
    specialBeforeCommand: 1

lookForAlignDelims:
   path: 
      delimiterRegEx: '(edge|node\h*\{[0-9,A-Z]+\})'

The lookForThis field can be considered optional; by default, it is assumed to be 1, which is demonstrated in Listing 176.

Referencing Listing 154 we see that each of the specialBeginEnd fields can optionally accept the body field. If the body field is omitted, then latexindent.pl uses a value that means

anything except one of the begin statements from specialBeginEnd.

In general, it is usually not necessary to specify the body field, but let’s detail an example just for reference.

Example 39

We begin with the example in Listing 177

Listing 177 special-body.tex
$
a
+
(
b + c
-
(
    d
)
)
=
e
$
and
$
f + g = h
$

Using the settings in Listing 179 and running the command

latexindent.pl special-body.tex -l=special-body1.yaml

gives the output in Listing 178.

Listing 178 special-body.tex using Listing 179
$
  a
  +
  (
    b + c
    -
    (
      d
    )
  )
  =
  e
$
and
$
  f + g = h
$
Listing 179 special-body1.yaml
defaultIndent: "  "
specialBeginEnd:
  specialBeforeCommand: 1
  parentheses:
    begin: \(
    end: \)

We note that the output in Listing 178 is as we would expect, even without the body field specified.

Another option (purely for reference) that leaves the output in Listing 178 unchanged is shown in Listing 180.

Listing 180 special-body2.yaml
defaultIndent: "  "
specialBeginEnd:
  specialBeforeCommand: 1
  parentheses:
    begin: \(
    body: [^()]*?
    end: \)

The body field in Listing 180 means anything except ( or ).

indentAfterHeadings:fields

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. 2

Listing 181 indentAfterHeadings
284indentAfterHeadings:
285  part:
286    indentAfterThisHeading: 0
287    level: 1
288  chapter:
289    indentAfterThisHeading: 0
290    level: 2
291  section:
292    indentAfterThisHeading: 0
293    level: 3

The default settings do not place indentation after a heading, but you can easily switch them on by changing indentAfterThisHeading from 0 to 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.8); you will find the default indentRules contains chapter: " " which tells latexindent.pl simply to use a space character after chapter headings (once indent is set to 1 for chapter).

Example 40

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

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

If you run the command

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

then you should receive the output given in Listing 184.

Listing 184 headings1.tex using Listing 183
\subsection{subsection title}
	subsection text
	subsection text
	\paragraph{paragraph title}
		paragraph text
		paragraph text
	\paragraph{paragraph title}
		paragraph text
		paragraph text
Listing 185 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 183 so that the paragraph level is 1; after running

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

you should receive the code given in Listing 185; 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” n.d.), and is off by default.

Example 41

For example, consider the example shown in Listing 186 together with the default output shown in Listing 187.

Listing 186 mult-nested.tex
\begin{one}
one
\begin{two}
    two
\begin{three}
     three 
\begin{four}
       four
\end{four}
\end{three}
\end{two}
\end{one}
Listing 187 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}
Example 42

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

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

You should receive the output shown in Listing 188.

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

Comparing the output in Listing 187 and Listing 188 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 54) or noIndentBlock (see Listing 60).

5.7. 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

0-9\.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 150 and Listing 153

\begin{enumerate}  \item ...\end{enumerate}

specialBeginEnd

User specified, see Listing 154

\[  ...\]

afterHeading

User specified, see Listing 181

\chapter{title}  ...\section{title}

filecontents

User specified, see Listing 70

\begin{filecontents}...\end{filecontents}

We will refer to these code blocks in what follows. Note that the fine tuning of the definition of the code blocks detailed in Table 2 is discussed in Section 9.

5.8. noAdditionalIndent and indentRules

latexindent.pl operates on files by looking for code blocks, as detailed in Section 5.7; 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.8.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 190.

Listing 190 myenv.tex
\begin{outer}
\begin{myenv}
  body of environment
body of environment
     body of environment
\end{myenv}
\end{outer}
noAdditionalIndent:fields
Example 43

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

Listing 191 myenv-noAdd1.yaml
noAdditionalIndent:
    myenv: 1
Listing 192 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 193; note in particular that the environment myenv has not received any additional indentation, but that the outer environment has still received indentation.

Listing 193 myenv.tex output (using either Listing 191 or Listing 192)
\begin{outer}
	\begin{myenv}
	body of environment
	body of environment
	body of environment
	\end{myenv}
\end{outer}
Example 44

Upon changing the YAML files to those shown in Listing 194 and Listing 195, 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 196.

Listing 194 myenv-noAdd3.yaml
noAdditionalIndent:
    myenv: 0
Listing 195 myenv-noAdd4.yaml
noAdditionalIndent:
    myenv: 
        body: 0
Listing 196 myenv.tex output (using either Listing 194 or Listing 195)
\begin{outer}
	\begin{myenv}
		body of environment
		body of environment
		body of environment
	\end{myenv}
\end{outer}
Example 45

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

Listing 197 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 198; 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 191), then all parts of the environment (body, optional and mandatory arguments) are assumed to want no additional indent.

Listing 198 myenv-args.tex using Listing 191
\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}
Example 46

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

Listing 199 myenv-noAdd5.yaml
noAdditionalIndent:
    myenv: 
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
Listing 200 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 201 and Listing 202. Note that in Listing 201 the text for the optional argument has not received any additional indentation, and that in Listing 202 the mandatory argument has not received any additional indentation; in both cases, the body has not received any additional indentation.

Listing 201 myenv-args.tex using Listing 199
\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 202 myenv-args.tex using Listing 200
\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
Example 47

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

Listing 203 myenv-rules1.yaml
indentRules:
    myenv: "   "
Listing 204 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 205; note in particular that the environment myenv has received one tab (from the outer environment) plus three spaces from Listing 203 or Listing 204.

Listing 205 myenv.tex output (using either Listing 203 or Listing 204)
\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.

Example 48

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

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

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

Listing 206 myenv-args.tex using Listing 203
\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}
Example 49

You can specify different indentation rules for the different features using, for example, Listing 207 and Listing 208

Listing 207 myenv-rules3.yaml
indentRules:
    myenv: 
        body: "   "
        optionalArguments: " "
Listing 208 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 209 and Listing 210.

Listing 209 myenv-args.tex using Listing 207
\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 210 myenv-args.tex using Listing 208
\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 209, 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 210, 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

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 211).

Listing 211 noAdditionalIndentGlobal
342noAdditionalIndentGlobal:
343  environments: 0                   # 0/1
Example 50

Let’s say that you change the value of environments to 1 in Listing 211, 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 212 and Listing 213; in Listing 212 notice that both environments receive no additional indentation but that the arguments of myenv still do receive indentation. In Listing 213 notice that the outer environment does not receive additional indentation, but because of the settings from myenv-rules1.yaml (in Listing 203), the myenv environment still does receive indentation.

Listing 212 myenv-args.tex using Listing 211
\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 213 myenv-args.tex using Listing 211 and Listing 203
\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}
Example 51

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

Listing 214 opt-args-no-add-glob.yaml
noAdditionalIndentGlobal:
    optionalArguments: 1
Listing 215 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 216 and Listing 217. Notice that in Listing 216 the optional argument has not received any additional indentation, and in Listing 217 the mandatory argument has not received any additional indentation.

Listing 216 myenv-args.tex using Listing 214
\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 217 myenv-args.tex using Listing 215
\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

The final check that latexindent.pl will make is to look for indentRulesGlobal as detailed in Listing 218.

Listing 218 indentRulesGlobal
358indentRulesGlobal:
359  environments: 0                   # 0/h-space
Example 52

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 219 and Listing 220. Note that in Listing 219, both the environment blocks have received a single-space indentation, whereas in Listing 220 the outer environment has received single-space indentation (specified by indentRulesGlobal), but myenv has received "   ", as specified by the particular indentRules for myenv Listing 203.

Listing 219 myenv-args.tex using Listing 218
\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 220 myenv-args.tex using Listing 203 and Listing 218
\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}
Example 53

You can specify indentRulesGlobal for both optional and mandatory arguments, as detailed in Listing 221 and Listing 222

Listing 221 opt-args-indent-rules-glob.yaml
indentRulesGlobal:
    optionalArguments: "\t\t"
Listing 222 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 223 and Listing 224. Note that the optional argument in Listing 223 has received two tabs worth of indentation, while the mandatory argument has done so in Listing 224.

Listing 223 myenv-args.tex using Listing 221
\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 224 myenv-args.tex using Listing 222
\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.8.2. Environments with items

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

Assuming that you’ve populated itemNames with the name of your item, you can put the item name into noAdditionalIndent as in Listing 225, although a more efficient approach may be to change the relevant field in itemNames to 0.

Example 54

Similarly, you can customise the indentation that your item receives using indentRules, as in Listing 226

Listing 225 item-noAdd1.yaml
noAdditionalIndent:
    item: 1
# itemNames:
#   item: 0
Listing 226 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 227 and Listing 228; note that in Listing 227 that the text after each item has not received any additional indentation, and in Listing 228, the text after each item has received a single space of indentation, specified by Listing 226.

Listing 227 items1.tex using Listing 225
\begin{itemize}
	\item some text here
	some more text here
	some more text here
	\item another item
	some more text here
\end{itemize}
Listing 228 items1.tex using Listing 226
\begin{itemize}
	\item some text here
	 some more text here
	 some more text here
	\item another item
	 some more text here
\end{itemize}
Example 55

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

Listing 229 items-noAdditionalGlobal.yaml
indentRules:
    item: 0
noAdditionalIndentGlobal:
    items: 1
Listing 230 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 227 and Listing 228 are obtained; note, however, that all such item commands without their own individual noAdditionalIndent or indentRules settings would behave as in these listings.

5.8.3. Commands with arguments

Example 56

Let’s begin with the simple example in Listing 231; when latexindent.pl operates on this file, the default output is shown in Listing 232. 3

Listing 231 mycommand.tex
\mycommand
{
mand arg text
mand arg text}
[
opt arg text
opt arg text
]
Listing 232 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 191 and Listing 192) we may specify noAdditionalIndent either in ‘scalar’ form, or in ‘field’ form, as shown in Listing 233 and Listing 234

Listing 233 mycommand-noAdd1.yaml
noAdditionalIndent:
    mycommand: 1
Listing 234 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 235 and Listing 236

Listing 235 mycommand.tex using Listing 233
\mycommand
{
mand arg text
mand arg text}
[
opt arg text
opt arg text
]
Listing 236 mycommand.tex using Listing 234
\mycommand
{
	mand arg text
	mand arg text}
[
	opt arg text
	opt arg text
]

Note that in Listing 235 that the ‘body’, optional argument and mandatory argument have all received no additional indentation, while in Listing 236, 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.

Example 57

We may further customise noAdditionalIndent for mycommand as we did in Listing 199 and Listing 200; explicit examples are given in Listing 237 and Listing 238.

Listing 237 mycommand-noAdd3.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
Listing 238 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 239 and Listing 240.

Listing 239 mycommand.tex using Listing 237
\mycommand
{
	mand arg text
	mand arg text}
[
opt arg text
opt arg text
]
Listing 240 mycommand.tex using Listing 238
\mycommand
{
mand arg text
mand arg text}
[
	opt arg text
	opt arg text
]
Example 58

Attentive readers will note that the body of mycommand in both Listing 239 and Listing 240 has received no additional indent, even though body is explicitly set to 0 in both Listing 237 and Listing 238. This is because, by default, noAdditionalIndentGlobal for commands is set to 1 by default; this can be easily fixed as in Listing 241 and Listing 242.

Listing 241 mycommand-noAdd5.yaml
noAdditionalIndent:
    mycommand:
        body: 0
        optionalArguments: 1
        mandatoryArguments: 0
noAdditionalIndentGlobal:
    commands: 0
Listing 242 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 243 and Listing 244.

Listing 243 mycommand.tex using Listing 241
\mycommand
	{
		mand arg text
		mand arg text}
	[
	opt arg text
	opt arg text
	]
Listing 244 mycommand.tex using Listing 242
\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 207 and Listing 208 and Listing 218 and Listing 221 and Listing 222.

5.8.4. ifelsefi code blocks

Example 59

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

Listing 245 ifelsefi1.tex
\ifodd\radius
\ifnum\radius<14
\pgfmathparse{100-(\radius)*4};
\else
\pgfmathparse{200-(\radius)*3};
\fi\fi
Listing 246 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 247 and Listing 248.

Listing 247 ifnum-noAdd.yaml
noAdditionalIndent:
    ifnum: 1
Listing 248 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 249 and Listing 250; note that in Listing 249, the ifnum code block has not received any additional indentation, while in Listing 250, the ifnum code block has received one tab and two spaces of indentation.

Listing 249 ifelsefi1.tex using Listing 247
\ifodd\radius
	\ifnum\radius<14
	\pgfmathparse{100-(\radius)*4};
	\else
	\pgfmathparse{200-(\radius)*3};
	\fi\fi
Listing 250 ifelsefi1.tex using Listing 248
\ifodd\radius
	\ifnum\radius<14
	  \pgfmathparse{100-(\radius)*4};
	\else
	  \pgfmathparse{200-(\radius)*3};
	\fi\fi
Example 60

We may specify noAdditionalIndentGlobal and indentRulesGlobal as in Listing 251 and Listing 252.

Listing 251 ifelsefi-noAdd-glob.yaml
noAdditionalIndentGlobal:
    ifElseFi: 1
Listing 252 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 253 and Listing 254; notice that in Listing 253 neither of the ifelsefi code blocks have received indentation, while in Listing 254 both code blocks have received a single space of indentation.

Listing 253 ifelsefi1.tex using Listing 251
\ifodd\radius
\ifnum\radius<14
\pgfmathparse{100-(\radius)*4};
\else
\pgfmathparse{200-(\radius)*3};
\fi\fi
Listing 254 ifelsefi1.tex using Listing 252
\ifodd\radius
 \ifnum\radius<14
  \pgfmathparse{100-(\radius)*4};
 \else
  \pgfmathparse{200-(\radius)*3};
 \fi\fi
Example 61

We can further explore the treatment of ifElseFi code blocks in Listing 255, and the associated default output given in Listing 256; note, in particular, that the bodies of each of the ‘or statements’ have been indented.

Listing 255 ifelsefi2.tex
\ifcase#1
zero%
\or
one%
\or
two%
\or
three%
\else
default
\fi
Listing 256 ifelsefi2.tex default output
\ifcase#1
	zero%
\or
	one%
\or
	two%
\or
	three%
\else
	default
\fi

5.8.5. specialBeginEnd code blocks

Let’s use the example from Listing 155 which has default output shown in Listing 156.

Example 62

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 257 and Listing 258.

Listing 257 displayMath-noAdd.yaml
noAdditionalIndent:
    displayMath: 1
Listing 258 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 259 and Listing 260; note that in Listing 259, the displayMath code block has not received any additional indentation, while in Listing 260, the displayMath code block has received three tabs worth of indentation.

Listing 259 special1.tex using Listing 257
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
	g(x)=f(2x)
$
Listing 260 special1.tex using Listing 258
The function $f$ has formula
\[
			f(x)=x^2.
\]
If you like splitting dollars,
$
	g(x)=f(2x)
$
Example 63

We may specify noAdditionalIndentGlobal and indentRulesGlobal as in Listing 261 and Listing 262.

Listing 261 special-noAdd-glob.yaml
noAdditionalIndentGlobal:
    specialBeginEnd: 1
Listing 262 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 263 and Listing 264; notice that in Listing 263 neither of the special code blocks have received indentation, while in Listing 264 both code blocks have received a single space of indentation.

Listing 263 special1.tex using Listing 261
The function $f$ has formula
\[
f(x)=x^2.
\]
If you like splitting dollars,
$
g(x)=f(2x)
$
Listing 264 special1.tex using Listing 262
The function $f$ has formula
\[
 f(x)=x^2.
\]
If you like splitting dollars,
$
 g(x)=f(2x)
$

5.8.6. afterHeading code blocks

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

Listing 265 headings2.tex
\paragraph{paragraph 
title}
paragraph text
paragraph text
Example 64

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

latexindent.pl headings2.tex -l headings3.yaml

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

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

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

latexindent.pl headings2.tex -l headings4.yaml

then we receive the output in Listing 268. 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 268 headings2.tex using Listing 269
\paragraph{paragraph
title}
paragraph text
paragraph text
Listing 269 headings4.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndent:
    paragraph: 1
Example 65

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

Listing 270 headings2.tex using Listing 271
\paragraph{paragraph
									title}
			paragraph text
			paragraph text
Listing 271 headings5.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRules:
    paragraph: "\t\t\t"
Example 66

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

Listing 272 headings2.tex using Listing 273
\paragraph{paragraph
	title}
paragraph text
paragraph text
Listing 273 headings6.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndent:
    paragraph: 
        body: 0
        mandatoryArguments: 0
        afterHeading: 1
Example 67

Analogously, we may specify indentRules as in Listing 275 which gives the output in Listing 274; 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 274 headings2.tex using Listing 275
\paragraph{paragraph
			 title}
			paragraph text
			paragraph text
Listing 275 headings7.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRules:
    paragraph: 
        mandatoryArguments: " "
        afterHeading: "\t\t\t"
Example 68

Finally, let’s consider noAdditionalIndentGlobal and indentRulesGlobal shown in Listing 277 and Listing 279 respectively, with respective output in Listing 276 and Listing 278. Note that in Listing 277 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 278, the argument has received both a (default) tab plus two spaces of indentation (from the global rule specified in Listing 279), and the remaining body after paragraph has received just two spaces of indentation.

Listing 276 headings2.tex using Listing 277
\paragraph{paragraph
	title}
paragraph text
paragraph text
Listing 277 headings8.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
noAdditionalIndentGlobal:
    afterHeading: 1
Listing 278 headings2.tex using Listing 279
\paragraph{paragraph
	  title}
  paragraph text
  paragraph text
Listing 279 headings9.yaml
indentAfterHeadings:
    paragraph:
       indentAfterThisHeading: 1
       level: 1
indentRulesGlobal:
    afterHeading: "  "

5.8.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.8.3, but a small discussion defining these remaining code blocks is necessary.

5.8.7.1. 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).

See the keyEqualsValuesBracesBrackets: follow and keyEqualsValuesBracesBrackets: name fields of the fine tuning section in Listing 594

Example 69

An example is shown in Listing 280, with the default output given in Listing 281.

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

In Listing 281, 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 page sec:noadd-indent-rules.

5.8.7.2. 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).

See the NamedGroupingBracesBrackets: follow and NamedGroupingBracesBrackets: name fields of the fine tuning section in Listing 594

Example 70

A simple example is given in Listing 282, with default output in Listing 283.

Listing 282 child1.tex
\coordinate
child[grow=down]{
edge from parent [antiparticle]
node [above=3pt] {$C$}
}
Listing 283 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 4. Referencing Listing 283, 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 page sec:noadd-indent-rules.

5.8.7.3. 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).

See the UnNamedGroupingBracesBrackets: follow field of the fine tuning section in Listing 594

Example 71

An example is shown in Listing 284 with default output give in Listing 285.

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

Referencing Listing 285, 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 page sec:noadd-indent-rules.

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

5.8.7.4. filecontents

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

5.8.8. Summary

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

Listing 286 noAdditionalIndentGlobal
342noAdditionalIndentGlobal:
343  environments: 0                   # 0/1
344  commands: 1                       # 0/1
345  optionalArguments: 0              # 0/1
346  mandatoryArguments: 0             # 0/1
347  ifElseFi: 0                       # 0/1
348  items: 0                          # 0/1
349  keyEqualsValuesBracesBrackets: 0  # 0/1
350  namedGroupingBracesBrackets: 0    # 0/1
351  UnNamedGroupingBracesBrackets: 0  # 0/1
352  specialBeginEnd: 0                # 0/1
353  afterHeading: 0                   # 0/1
354  filecontents: 0                   # 0/1
Listing 287 indentRulesGlobal
358indentRulesGlobal:
359  environments: 0                   # 0/h-space
360  commands: 0                       # 0/h-space
361  optionalArguments: 0              # 0/h-space
362  mandatoryArguments: 0             # 0/h-space
363  ifElseFi: 0                       # 0/h-space
364  items: 0                          # 0/h-space
365  keyEqualsValuesBracesBrackets: 0  # 0/h-space
366  namedGroupingBracesBrackets: 0    # 0/h-space
367  UnNamedGroupingBracesBrackets: 0  # 0/h-space
368  specialBeginEnd: 0                # 0/h-space
369  afterHeading: 0                   # 0/h-space
370  filecontents: 0                   # 0/h-space

5.9. 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 contains a few switches detailed in Listing 288.

Listing 288 commandCodeBlocks
373commandCodeBlocks:
374  roundParenthesesAllowed: 1
375  stringsAllowedBetweenArguments:
376    - amalgamate: 1
377    - node
378    - at
379    - to
380    - decoration
381    - \+\+
382    - \-\-
383    - \#\#\d
384  commandNameSpecial:
385    - amalgamate: 1
386    - '@ifnextchar\['
387
388# change dos line breaks into unix
roundParenthesesAllowed:0|1
Example 72

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 289.

Listing 289 pstricks1.tex
\defFunction[algebraic]{torus}(u,v)
{(2+cos(u))*cos(v+\Pi)}
{(2+cos(u))*sin(v+\Pi)}
{sin(u)}
Listing 290 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 288, then latexindent.pl will allow round parenthesis between optional and mandatory arguments. In the case of the code in Listing 289, latexindent.pl finds all the arguments of defFunction, both before and after (u,v).

The default output from running latexindent.pl on Listing 289 actually leaves it unchanged (see Listing 290); note in particular, this is because of noAdditionalIndentGlobal as discussed on page page:command:noAddGlobal.

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

latexindent.pl pstricks1.tex -l noRoundParentheses.yaml

we obtain the output given in Listing 291.

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

Notice the difference between Listing 290 and Listing 291; in particular, in Listing 291, 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 291.

Example 73

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

latexindent.pl pstricks1.tex -l defFunction.yaml

then the output is as in Listing 293.

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

Notice in Listing 293 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 294.

stringsAllowedBetweenArguments:fields
Example 74

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

Listing 295 tikz-node1.tex
\draw[thin] 
(c) to[in=110,out=-90] 
++(0,-0.5cm) 
node[below,align=left,scale=0.5]
Listing 296 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 288, we see that the strings

to, node, ++

are all allowed to appear between arguments; importantly, you are encouraged to add further names to this field as necessary. This means that when latexindent.pl processes Listing 295, 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]

Example 75

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

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

we receive the output given in Listing 297.

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

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

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

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

given in Listing 299.

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

In this case, latexindent.pl sees that:

  • the \draw command finishes after the (c), as stringsAllowedBetweenArguments has been set to \(0\) so there are no strings allowed between arguments;

  • 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]

Referencing Listing 288, , we see that the first field in the stringsAllowedBetweenArguments is amalgamate and is set to 1 by default. This is for users who wish to specify their settings in multiple YAML files. For example, by using the settings in either Listing 301 or:numref:lst:amalgamate-demo1 is equivalent to using the settings in Listing 303.

Listing 301 amalgamate-demo.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
      - 'more'
      - 'strings'
      - 'here'
Listing 302 amalgamate-demo1.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
      - 
        amalgamate: 1
      - 'more'
      - 'strings'
      - 'here'
Listing 303 amalgamate-demo2.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
      - 
        amalgamate: 1
      - 'node'
      - 'at'
      - 'to'
      - 'decoration'
      - '\+\+'
      - '\-\-'
      - 'more'
      - 'strings'
      - 'here'

We specify amalgamate to be set to 0 and in which case any settings loaded prior to those specified, including the default, will be overwritten. For example, using the settings in Listing 304 means that only the strings specified in that field will be used.

Listing 304 amalgamate-demo3.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
      - 
        amalgamate: 0
      - 'further'
      - 'settings'

It is important to note that the amalgamate field, if used, must be in the first field, and specified using the syntax given in Listing 302 and Listing 303 and Listing 304.

Example 76

We may explore this feature further with the code in Listing 305, whose default output is given in Listing 306.

Listing 305 for-each.tex
\foreach \x/\y in {0/1,1/2}{
body of foreach
}
Listing 306 for-each default output
\foreach \x/\y in {0/1,1/2}{
		body of foreach
	}

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

latexindent.pl for-each.tex -l foreach.yaml

given in Listing 307.

Listing 307 for-each.tex using Listing 308
\foreach \x/\y in {0/1,1/2}{
	body of foreach
}
Listing 308 foreach.yaml
commandCodeBlocks:
    stringsAllowedBetweenArguments:
      - 
        amalgamate: 0
      - '\\x\/\\y'
      - 'in'

You might like to compare the output given in Listing 306 and Listing 307. Note,in particular, in Listing 306 that the foreach command has not included any of the subsequent strings, and that the braces have been treated as a namedGroupingBracesBrackets. In Listing 307 the foreach command has been allowed to have \x/\y and in between arguments because of the settings given in Listing 308.

commandNameSpecial:fields

There are some special command names that do not fit within the names recognised by latexindent.pl, the first one of which is \@ifnextchar[. From the perspective of latexindent.pl, the whole of the text \@ifnextchar[ 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 ].

Example 77

For example, consider the sample file in Listing 309, which has default output in Listing 310.

Listing 309 ifnextchar.tex
\parbox{
\@ifnextchar[{arg 1}{arg 2}
}
Listing 310 ifnextchar.tex default output
\parbox{
	\@ifnextchar[{arg 1}{arg 2}
}

Notice that in Listing 310 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 page page:phases.

For demonstration, we can compare this output with that given in Listing 311 in which the settings from Listing 312 have dictated that no special command names, including the \@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 311 ifnextchar.tex using Listing 312
\parbox{
\@ifnextchar[{arg 1}{arg 2}
}
Listing 312 no-ifnextchar.yaml
commandCodeBlocks:
    commandNameSpecial: 0

The amalgamate field can be used for commandNameSpecial, just as for stringsAllowedBetweenArguments. The same condition holds as stated previously, which we state again here:

Warning

It is important to note that the amalgamate field, if used, in either commandNameSpecial or stringsAllowedBetweenArguments must be in the first field, and specified using the syntax given in Listing 302 and Listing 303 and Listing 304.

“Data Dumper Demonstration.” n.d. Accessed June 18, 2021. https://stackoverflow.com/questions/7466825/how-do-you-sort-the-output-of-datadumper.

Data::Dumper Module.” n.d. Accessed June 18, 2021. https://perldoc.perl.org/Data::Dumper.

“Text::Tabs Perl Module.” n.d. Accessed July 6, 2017. 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, 2013. https://github.com/cmhughes/latexindent.pl/pull/12.

XuehaiPan. 2021. “Verbatim Block Upgrade.” October 3, 2021. https://github.com/cmhughes/latexindent.pl/pull/290.

1

Throughout this manual, listings shown with line numbers represent code taken directly from defaultSettings.yaml.

2

There is a slight difference in interface for this field when comparing Version 2.2 to Version 3.0; see Section 12.12 for details.

3

The command code blocks have quite a few subtleties, described in Section 5.9.

4

You may like to verify this by using the -tt option and checking indent.log!