9. Fine tuning

latexindent.pl operates by looking for the code blocks detailed in Table 2. The fine tuning of the details of such code blocks is controlled by the fineTuning field, detailed in Listing 594.

This field is for those that would like to peek under the bonnet/hood and make some fine tuning to latexindent.pl’s operating.

Warning

Making changes to the fine tuning may have significant consequences for your indentation scheme, proceed with caution!

Listing 594 fineTuning
630fineTuning:
631  environments:
632    name: [a-zA-Z@\*0-9_\\]+
633  ifElseFi:
634    name: (?!@?if[a-zA-Z@]*?\{)@?if[a-zA-Z@]*?
635  commands:
636    name: [+a-zA-Z@\*0-9_\:]+?
637  items:
638    canBeFollowedBy: (?:\[[^]]*?\])|(?:<[^>]*?>)
639  keyEqualsValuesBracesBrackets:
640    name: [a-zA-Z@\*0-9_\/.:\#-]+[a-zA-Z@\*0-9_\/.\h\{\}:\#-]*?
641    follow: (?:(?<!\\)\{)|,|(?:(?<!\\)\[)
642  namedGroupingBracesBrackets:
643    name: [0-9\.a-zA-Z@\*><]+?
644    follow: \h|\R|\{|\[|\$|\)|\(
645  UnNamedGroupingBracesBrackets:
646    follow: \{|\[|,|&|\)|\(|\$
647  arguments:
648    before: (?:#\d\h*;?,?\/?)+|\<.*?\>
649    between: _|\^|\*
650  trailingComments:
651    notPreceededBy: (?<!\\)
652    afterComment: .*?
653  modifyLineBreaks:
654    doubleBackSlash: \\\\(?:\h*\[\h*\d+\h*[a-zA-Z]+\h*\])?
655    comma: ','
656    betterFullStop: |-
657      (?x)                                # ignore spaces in the below
658      (?:                                 #
659        \.\)                              # .) 
660        (?!\h*[a-z])                      # not *followed by* a-z
661      )                                   #
662      |                                   # OR
663      (?:                                 #
664        (?<!                              # not *preceded by*
665          (?:                             #
666            (?:[eE]\.[gG])                # e.g OR E.g OR e.G OR E.G
667            |                             #
668            (?:[iI]\.[eE])                # i.e OR I.e OR i.E OR I.E
669            |                             #
670            (?:etc)                       # etc
671            |                             #
672            (?:[wW]\.[rR]\.[tT])          # w.r.t OR W.r.t OR w.R.t OR w.r.T OR W.R.t OR W.r.T OR w.R.T OR W.R.T
673          )                               #
674        )                                 #
675      )                                   # 
676      \.                                  # .
677      (?!                                 # not *followed by*
678        (?:                               #
679          [a-zA-Z0-9-~,]                  #
680          |                               #
681          \),                             # ),
682          |                               #
683          \)\.                            # ).
684        )                                 #
685      )                                   #

The fields given in Listing 594 are all regular expressions. This manual is not intended to be a tutorial on regular expressions; you might like to read, for example, (Friedl, n.d.) for a detailed covering of the topic.

We make the following comments with reference to Listing 594:

  1. the environments:name field details that the name of an environment can contain:

    1. a-z lower case letters

    2. A-Z upper case letters

    3. @ the @ ’letter’

    4. \* stars

    5. 0-9 numbers

    6. _ underscores

    7. \ backslashes

    The + at the end means at least one of the above characters.

  2. the ifElseFi:name field:

    1. @? means that it can possibly begin with @

    2. followed by if

    3. followed by 0 or more characters from a-z, A-Z and @

    4. the ? the end means non-greedy, which means ‘stop the match as soon as possible’

  3. the keyEqualsValuesBracesBrackets contains some interesting syntax:

    1. | means ‘or’

    2. (?:(?<!\\)\{) the (?:...) uses a non-capturing group – you don’t necessarily need to worry about what this means, but just know that for the fineTuning feature you should only ever use non-capturing groups, and not capturing groups, which are simply (...)

    3. (?<!\\)\{) means a { but it can not be immediately preceded by a \

  4. in the arguments:before field

    1. \d\h* means a digit (i.e. a number), followed by 0 or more horizontal spaces

    2. ;?,? means possibly a semi-colon, and possibly a comma

    3. \<.*?\> is designed for ’beamer’-type commands; the .*? means anything in between <...>

  5. the modifyLineBreaks field refers to fine tuning settings detailed in Section 6. In particular:

    1. betterFullStop is in relation to the one sentence per line routine, detailed in Section 6.2

    2. doubleBackSlash is in relation to the DBSStartsOnOwnLine and DBSFinishesWithLineBreak polyswitches surrounding double backslashes, see Section 6.3.2

    3. comma is in relation to the CommaStartsOnOwnLine and CommaFinishesWithLineBreak polyswitches surrounding commas in optional and mandatory arguments; see Table 3

It is not obvious from Listing 594, but each of the follow, before and between fields allow trailing comments, line breaks, and horizontal spaces between each character.

Warning

For the fineTuning feature you should only ever use non-capturing groups, such as (?:...) and not capturing groups, which are (...)

Example 164

As a demonstration, consider the file given in Listing 595, together with its default output using the command

latexindent.pl finetuning1.tex

is given in Listing 596.

Listing 595 finetuning1.tex
\mycommand{
    \rule{G -> +H[-G]CL}
    \rule{H -> -G[+H]CL}
    \rule{g -> +h[-g]cL}
    \rule{h -> -g[+h]cL}
}
Listing 596 finetuning1.tex default
\mycommand{
\rule{G -> +H[-G]CL}
\rule{H -> -G[+H]CL}
\rule{g -> +h[-g]cL}
\rule{h -> -g[+h]cL}
}

It’s clear from Listing 596 that the indentation scheme has not worked as expected. We can fine tune the indentation scheme by employing the settings given in Listing 598 and running the command

latexindent.pl finetuning1.tex -l=fine-tuning1.yaml

and the associated (desired) output is given in Listing 597.

Listing 597 finetuning1.tex using Listing 598
\mycommand{
	\rule{G -> +H[-G]CL}
	\rule{H -> -G[+H]CL}
	\rule{g -> +h[-g]cL}
	\rule{h -> -g[+h]cL}
}
Listing 598 finetuning1.yaml
fineTuning:
    arguments:
      between: '_|\^|\*|\->|\-|\+|h|H|g|G'
Example 165

Let’s have another demonstration; consider the file given in Listing 599, together with its default output using the command

latexindent.pl finetuning2.tex

is given in Listing 600.

Listing 599 finetuning2.tex
@misc{ wikilatex,
author = "{Wikipedia contributors}",
title = "LaTeX --- {Wikipedia}{,}",
note = "[Online; accessed 3-March-2020]"
}
Listing 600 finetuning2.tex default
@misc{ wikilatex,
author = "{Wikipedia contributors}",
title = "LaTeX --- {Wikipedia}{,}",
note = "[Online; accessed 3-March-2020]"
}

It’s clear from Listing 600 that the indentation scheme has not worked as expected. We can fine tune the indentation scheme by employing the settings given in Listing 602 and running the command

latexindent.pl finetuning2.tex -l=fine-tuning2.yaml

and the associated (desired) output is given in Listing 601.

Listing 601 finetuning2.tex using Listing 602
@misc{ wikilatex,
	author = "{Wikipedia contributors}",
	title = "LaTeX --- {Wikipedia}{,}",
	note = "[Online; accessed 3-March-2020]"
}
Listing 602 finetuning2.yaml
fineTuning:
    NamedGroupingBracesBrackets:
      follow: '\h|\R|\{|\[|\$|\)|\(|"'
    UnNamedGroupingBracesBrackets: 
      follow: '\{|\[|,|&|\)|\(|\$|"'
    arguments:
      between: '_|\^|\*|---'

In particular, note that the settings in Listing 602 specify that NamedGroupingBracesBrackets and UnNamedGroupingBracesBrackets can follow " and that we allow --- between arguments.

Example 166

You can tweak the fineTuning using the -y switch, but to be sure to use quotes appropriately. For example, starting with the code in Listing 603 and running the following command

latexindent.pl -m -y='modifyLineBreaks:oneSentencePerLine:manipulateSentences: 1, modifyLineBreaks:oneSentencePerLine:sentencesBeginWith:a-z: 1, fineTuning:modifyLineBreaks:betterFullStop: "(?:\.|;|:(?![a-z]))|(?:(?<!(?:(?:e\.g)|(?:i\.e)|(?:etc))))\.(?!(?:[a-z]|[A-Z]|\-|~|\,|[0-9]))"' issue-243.tex -o=+-mod1

gives the output shown in Listing 604.

Listing 603 finetuning3.tex
We go; you see: this sentence \cite{tex:stackexchange} finishes here.
Listing 604 finetuning3.tex using -y switch
We go;
you see:
this sentence \cite{tex:stackexchange} finishes here.
Example 167

We can tweak the fineTuning for how trailing comments are classified. For motivation, let’s consider the code given in Listing 605

Listing 605 finetuning4.tex
some before text
 \href{Handbook%20for%30Spoken%40document.pdf}{my document}
some after text 

We will compare the settings given in Listing 606 and Listing 607.

Listing 606 href1.yaml
modifyLineBreaks:
    textWrapOptions:
        columns: -1
        blocksEndBefore:
           verbatim: 0
        blocksFollow:
           verbatim: 0

removeTrailingWhitespace:
    beforeProcessing: 1
Listing 607 href2.yaml
fineTuning:
    trailingComments:
      notPreceededBy: '(?:(?<!Handbook)(?<!for)(?<!Spoken))'

modifyLineBreaks:
    textWrapOptions:
        columns: -1
        blocksEndBefore:
           verbatim: 0
        blocksFollow:
           verbatim: 0

removeTrailingWhitespace:
    beforeProcessing: 1

Upon running the following commands

latexindent.pl -m finetuning4.tex -o=+-mod1 -l=href1
latexindent.pl -m finetuning4.tex -o=+-mod2 -l=href2

we receive the respective output in Listing 608 and Listing 609.

Listing 608 finetuning4.tex using Listing 606
some before text \href{Handbooksome after text%20for%30Spoken%40document.pdf}{my document}
Listing 609 finetuning4.tex using Listing 607
some before text \href{Handbook%20for%30Spoken%40document.pdf}{my document} some after text

We note that in:

  • Listing 608 the trailing comments are assumed to be everything following the first comment symbol, which has meant that everything following it has been moved to the end of the line; this is undesirable, clearly!

  • Listing 609 has fine-tuned the trailing comment matching, and says that % cannot be immediately preceded by the words ‘Handbook’, ‘for’ or ‘Spoken’, which means that none of the % symbols have been treated as trailing comments, and the output is desirable.

Example 168

Another approach to this situation, which does not use fineTuning, is to use noIndentBlock which we discussed in Listing 60; using the settings in Listing 610 and running the command

latexindent.pl -m finetuning4.tex -o=+-mod3 -l=href3

then we receive the same output given in Listing 609.

Listing 610 href3.yaml
modifyLineBreaks:
    textWrapOptions:
        columns: -1
        blocksEndBefore:
           verbatim: 0
        blocksFollow:
           verbatim: 0

noIndentBlock:
    href:
        begin: '\\href\{[^}]*?\}\{'
        body: '[^}]*?'
        end: '\}'

With reference to the body field in Listing 610, we note that the body field can be interpreted as: the fewest number of zero or more characters that are not right braces. This is an example of character class.

Example 169

We can use the fineTuning field to assist in the formatting of bibliography files.

Starting with the file in Listing 611 and running the command

latexindent.pl bib1.tex -o=+-mod1

gives the output in Listing 612.

Listing 611 bib1.bib
@online{paulo,
title="arararule,indent.yaml",
author="PauloCereda",
date={2013-05-23},
urldate={2021-03-19},
keywords={contributor},}
Listing 612 bib1-mod1.bib
@online{paulo,
	title="arararule,indent.yaml",
	author="PauloCereda",
	date={2013-05-23},
	urldate={2021-03-19},
	keywords={contributor},}

Let’s assume that we would like to format the output so as to align the = symbols. Using the settings in Listing 614 and running the command

latexindent.pl bib1.bib -l bibsettings1.yaml -o=+-mod2

gives the output in Listing 613.

Listing 613 bib1.bib using Listing 614
@online{paulo,
	title    = "arararule,indent.yaml",
	author   = "PauloCereda",
	date     = {2013-05-23},
	urldate  = {2021-03-19},
	keywords = {contributor},}
Listing 614 bibsettings1.yaml
lookForAlignDelims:
   online: 
      delimiterRegEx: '(=)'

fineTuning:
    keyEqualsValuesBracesBrackets:
      follow: '(?:(?<!\\)\{)|(?:(?<!\\)\[)'
    UnNamedGroupingBracesBrackets: 
      follow: '\{|\[|,|&|\)|\(|\$|='

Some notes about Listing 614:

  • we have populated the lookForAlignDelims field with the online command, and have used the delimiterRegEx, discussed in Section 5.5.4;

  • we have tweaked the keyEqualsValuesBracesBrackets code block so that it will not be found following a comma; this means that, in contrast to the default behaviour, the lines such as date={2013-05-23}, will not be treated as key-equals-value braces;

  • the adjustment to keyEqualsValuesBracesBrackets necessitates the associated change to the UnNamedGroupingBracesBrackets field so that they will be searched for following = symbols.

Example 170

We can build upon Listing 614 for slightly more complicated bibliography files.

Starting with the file in Listing 615 and running the command

latexindent.pl bib2.bib -l bibsettings1.yaml -o=+-mod1

gives the output in Listing 616.

Listing 615 bib2.bib
@online{cmh:videodemo,
title="Videodemonstrationofpl.latexindentonyoutube",
url="https://www.youtube.com/watch?v=wo38aaH2F4E&spfreload=10",
urldate={2017-02-21},
}
Listing 616 bib2-mod1.bib
@online{cmh:videodemo,
	title   = "Videodemonstrationofpl.latexindentonyoutube",
	url     = "https://www.youtube.com/watch?v               = wo38aaH2F4E&spfreload = 10",
	urldate = {2017-02-21},
}

The output in Listing 616 is not ideal, as the = symbol within the url field has been incorrectly used as an alignment delimiter.

We address this by tweaking the delimiterRegEx field in Listing 617.

Listing 617 bibsettings2.yaml
lookForAlignDelims:
   online: 
      delimiterRegEx: '(?<!v)(?<!spfreload)(=)'

Upon running the command

latexindent.pl bib2.bib -l bibsettings1.yaml,bibsettings2.yaml -o=+-mod2

we receive the desired output in Listing 618.

Listing 618 bib2-mod2.bib
@online{cmh:videodemo,
	title   = "Videodemonstrationofpl.latexindentonyoutube",
	url     = "https://www.youtube.com/watch?v=wo38aaH2F4E&spfreload=10",
	urldate = {2017-02-21},
}

With reference to Listing 617 we note that the delimiterRegEx has been adjusted so that = symbols are used as the delimiter, but only when they are not preceded by either v or spfreload.

Example 171

We can use the fineTuning settings to tweak how latexindent.pl finds trailing comments. We begin with the file in Listing 619

Listing 619 finetuning5.tex
\chapter{chapter text} % 123
chapter text
\section{section text} % 456
section text
% end
% end

Using the settings in Listing 621 and running the command

latexindent.pl finetuning5.tex -l=fine-tuning3.yaml

gives the output in Listing 620.

Listing 620 finetuning5-mod1.tex
\chapter{chapter text} % 123
	chapter text
	\section{section text} % 456
		section text
	% end
% end
Listing 621 finetuning3.yaml
fineTuning:
    trailingComments:
      notPreceededBy: (?<!\\)
      afterComment: (?!(?:\hend)).*?

specialBeginEnd:
  customSection:
    begin: \\(?:section|chapter)
    end: \%\h+end
  specialBeforeCommand: 1

The settings in Listing 621 detail that trailing comments can not be followed by a single space, and then the text ‘end’. This means that the specialBeginEnd routine will be able to find the pattern % end as the end part. The trailing comments 123 and 456 are still treated as trailing comments.

Example 172

We can use the fineTuning settings to tweak how latexindent.pl finds environments.

We begin with the file in Listing 622.

Listing 622 finetuning6.tex
\begin{myenv}\label{mylabel}The body of my environment...\end{myenv}

Using the settings in Listing 624 and running the command

latexindent.pl finetuning6.tex -m -l=fine-tuning4.yaml

gives the output in Listing 623.

Listing 623 finetuning6-mod1.tex
\begin{myenv}\label{mylabel}
	The body of my environment...
\end{myenv}
Listing 624 fine-tuning4.yaml
modifyLineBreaks:
   environments:
       BodyStartsOnOwnLine: 1
       EndStartsOnOwnLine: 1

fineTuning:
  environments:
    begin: \\begin\{([a-zA-Z@\*0-9_\\]+)\}\s*\\label\{[^}]+?\}
    end: \\end\{\2\}

By using the settings in Listing 624 it means that the default poly-switch location of BodyStartsOnOwnLine for environments (denoted ♥ in Table 3) has been overwritten so that it is after the label command.

Referencing Listing 624, unless both begin and end are specified, then the default value of name will be used.

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