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

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 559 fineTuning
427fineTuning:
428  environments:
429    name: [a-zA-Z@\*0-9_\\]+
430  items:
431    itemRegEx: \\(?:item|myitem)
432  ifElseFi:
433    name: (?!@?if[a-zA-Z@]*?\{)@?if[a-zA-Z@]*
434    elseOrRegEx: \\(?:else|or)
435  commands:
436    name: [+a-zA-Z@*0-9_:]+
437  namedGroupingBracesBrackets:
438    name: [0-9\.a-zA-Z@\*><]+
439  keyEqualsValuesBracesBrackets:
440    name: [a-zA-Z@\*0-9_\/.:\#-]+[a-zA-Z@\*0-9_\/.\h:\#-]*
441  arguments:
442    between: |-                               
443      (?x)                                    
444      (?:                                     
445        [_^*#0-9(),+-]                        
446        |                                     
447        (?:node|at|to|decoration)             
448        |                                     
449        (?:\([^)]*\))                         
450      )                                       
451  trailingComments:
452    notPrecededBy: (?<!\\)
453    afterComment: .*?
454  lookForAlignDelimsDefaults:
455    delims: 1
456    alignDoubleBackSlash: 1
457    spacesBeforeDoubleBackSlash: 1
458    multiColumnGrouping: 0
459    alignRowsWithoutMaxDelims: 1
460    spacesBeforeAmpersand: 1
461    spacesAfterAmpersand: 1
462    justification: left
463    alignFinalDoubleBackSlash: 0
464    dontMeasure: 0
465    delimiterRegEx: (?<!\\)(&)
466    delimiterJustification: left
467    lookForChildCodeBlocks: 1
468    alignContentAfterDoubleBackSlash: 0
469    spacesAfterDoubleBackSlash: 1
470    doubleBackSlash: \\\\(?:\h*\[\h*[0-9.]+\h*[a-zA-Z]+\h*\])?
471  modifyLineBreaks:                                        
472    comma: ','
473    betterFullStop: |-
474      (?x)                                # ignore spaces in the below
475      (?:                                 #
476        \.\)                              # .) 
477        (?!\h*[a-z])                      # not *followed by* a-z
478      )                                   #
479      |                                   # OR
480      (?:                                 #
481        (?<!                              # not *preceded by*
482          (?:                             #
483            (?:[eE]\.[gG])                # e.g OR E.g OR e.G OR E.G
484            |                             #
485            (?:[iI]\.[eE])                # i.e OR I.e OR i.E OR I.E
486            |                             #
487            (?:etc)                       # etc
488            |                             #
489            (?:[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
490          )                               #
491        )                                 #
492      )                                   # 
493      \.                                  # .
494      (?!                                 # not *followed by*
495        (?:                               #
496          [a-zA-Z0-9-~,]                  #
497          |                               #
498          \),                             # ),
499          |                               #
500          \)\.                            # ).
501        )                                 #
502      )                                   #

The fields given in Listing 559 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 559:

  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 modifyLineBreaks field refers to fine tuning settings detailed in Section 4. In particular:

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

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

Warning

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

7.1. fineTuning trailing comments

Example 161

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

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

We will compare the settings given in Listing 561 and Listing 562.

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

removeTrailingWhitespace:
    beforeProcessing: 1
Listing 562 href2.yaml
fineTuning:
    trailingComments:
      notPrecededBy: '(?:(?<!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 563 and Listing 564.

Listing 563 finetuning4.tex using Listing 561
some before text \href{Handbooksome after text%20for%30Spoken%40document.pdf}{my document}
Listing 564 finetuning4.tex using Listing 562
some before text \href{Handbook%20for%30Spoken%40document.pdf}{my document} some after text

We note that in:

  • Listing 563 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 564 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 162

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

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

then we receive the same output given in Listing 564.

Listing 565 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 565, 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 163

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

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

Using the settings in Listing 568 and running the command

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

gives the output in Listing 567.

Listing 567 finetuning5-mod1.tex
\chapter{chapter text} % 123
	chapter text
	\section{section text} % 456
		section text
	% end
% end
Listing 568 fine-tuning3.yaml
fineTuning:
  trailingComments:
    notPrecededBy: (?<!\\)
    afterComment: (?!(?:\hend)).*?
  commands:
    name: |-
      (?x)
       (?!(?:begin|end|chapter|section))
       [+a-zA-Z@*0-9_:]+

specialBeginEnd:
 - name: customHeading
   begin: \\(?:chapter|section)
   end: \%\h+end
   nested: 1

The settings in Listing 568 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.

7.2. fineTuning environments

Example 164

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

We begin with the file in Listing 569.

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

Using the settings in Listing 571 and running the command

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

gives the output in Listing 570.

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

fineTuning:
  environments:
    begin: |-
      (?x)                      # environment 
        \\begin\{               # regex
          (?<ENVNAME>           # NON default
           [a-zA-Z@\*0-9_\\]+   #
          )                     #
        \}\s*\\label\{[^}]+?\}  #
    end: \\end\{\g{ENVNAME}\}   # note the capture group name

By using the settings in Listing 571 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 571, unless both begin and end are specified, then the default value of name will be used.

7.3. fineTuning itemsRegex

In Listing 129 we demonstrated the default indentation after items. You can customise the itemsRegex in the fineTuning, which we demonstrate next.

Example 165

We begin with the code in Listing 572 and use the settings in Listing 573. Upon running

latexindent.pl -l ft-itemsRegex items2-o=+-mod1

we receive the output in Listing 574.

Listing 572 items2.tex
\begin{myenv}
\cmh custom item 
and after text
\cmh custom item 
and after text
\end{myenv}
Listing 573 ft-itemsRegex.yaml
indentAfterItems:
  myenv: 1
fineTuning:
  items:
    itemRegEx: \\(?:item|cmh)
indentRules:
  cmh: "     "
Listing 574 items2-mod1.tex
\begin{myenv}
	\cmh custom item
	     and after text
	\cmh custom item
	     and after text
\end{myenv}

7.4. fineTuning arguments

The strings allowed between arguments for commands, namedGroupingBracesBrackets, keyEqualsValuesBracesBrackets and UnNamedGroupingBracesBrackets are controlled by fineTuning. We demonstrate with an example next.

Example 166

We begin with the code in Listing 575 and use the settings in Listing 576. Upon running

latexindent.pl -l ft-args beamer1-o=+-mod1

we receive the output in Listing 577.

Listing 575 beamer1.tex
\cmh<+->{
first arg}
{
second arg}
Listing 576 ft-args.yaml
fineTuning:
  arguments:
    between: |-                               
      (?x)                                    
      (?:                                     
        [_^*#0-9(),+-]                        
        |                                     
        (?:node|at|to|decoration)             
        |                                     
        (?:\([^)]*\))                         
        |             # NEW BIT                        
        (?:<[^>]+>)   # NEW BIT                      
      )                                       
Listing 577 beamer1-mod1.tex
\cmh<+->{
	first arg}
{
	second arg}

7.5. fineTuning ifElseFi

We can fine tune the elseOrRegEx for ifElseFi blocks as we demonstrate next.

Example 167

We begin with the code in Listing 578 and use the settings in Listing 579. Upon running

latexindent.pl -l ft-ifelsefi ft-ifelsefi-o=+-mod1

we receive the output in Listing 580.

Listing 578 ft-ifelsefi.tex
\if
if body
\cmh
other body
\fi
Listing 579 ft-ifelsefi.yaml
fineTuning:
  ifElseFi:
    elseOrRegEx: \\(?:else|or|cmh)
Listing 580 ft-ifelsefi-mod1.tex
\if
	if body
\cmh
	other body
\fi

7.6. fineTuning lookForAlignDelims

As detailed in Section 3.5 there is a basic and an advanced way to specify the entries in lookForAlignDelims; any entries not specified explicitly, will be read from the default values specified in fineTuning.

As an example, the settings in Listing 581 and Listing 582 and Listing 583 are equivalent.

Listing 581 align1.yaml
lookForAlignDelims:
  align: 1
Listing 582 align2.yaml
lookForAlignDelims:
  align: 
    spacesBeforeDoubleBackSlash: 1
Listing 583 align3.yaml
lookForAlignDelims:
  align: 1

fineTuning:
  lookForAlignDelimsDefaults:
    alignDoubleBackSlash: 1

7.7. fineTuning using -y switch

Example 168

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

Listing 584 finetuning3.tex
We go; you see: this sentence \cite{tex:stackexchange} finishes here.
Listing 585 finetuning3.tex using -y switch
We go;
you see:
this sentence \cite{tex:stackexchange} finishes here.

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