A perl script for indenting .tex files

As LaTeX users we are confident that the output of our documents will almost always be beautiful. Best practices also dictate that we try to construct our code to be as robust and portable as possible; one of the things that sometimes gets overlooked, especially when working on larger documents, is the somewhat-tedious task of indenting source code, and aligning delimiter tabs.

Of course, some editors do this kind of thing for us; for example,

vim

users can (in Normal mode)  press

gg=G

which will indent the code automagically (although this action doesn’t align the delimiter tabs); I’m sure it can be done in other editors too. I had also read LaTeX code sniffer and or beautifier but found the linked Perl script didn’t behave as I wanted it to.

So, I found that I was interested in taking my own approach that I could ‘easily’ customize, which is why I wrote the Perl Script

indent.plx

which can be found at https://github.com/cmhughes/latexindent.plx. Note that you should click on “indent.plx” and then download it by clicking on the “Raw” button.

Demonstration

We’ll talk about how it works a little later, but first here’s a visual demonstration of what it does. Let’s say that we have a block of code that uses alignment delimiters, something like the

align

, or

tabular

environment that we know and love. Some typical source code might look like the following:

 

 

 

 

 

Of course, if we’re working on a small document (or posting an answer to tex exchange) and had a fair bit of time, then we might take the time to align all of the &, but it’s not usually a good use of our time.  If we’re working on a larger document, perhaps a chapter file that has around 10,000 lines, then taking care of such alignment is extremely tedious and probably not very worthwhile, especially early in the editing process.

After running the above code through

indent.plx

, we obtain

which, I hope you’ll agree, is a lot nicer to look at.

Here’s another example- a fairly standard

TikZ

picture; this example demonstrates that nested environments indent as we wish. First of all, here’s the code we start with (ugh!)

and after running it through

indent.plx

, we obtain the following

How does it work?

The script loops through the input file, and checks for matches of the form

\begin{.*}

and

\end{.*}

. If it finds a match, then it will (by default) add a level of indentation for the block within the environment. If there are environments that you don’t wish to have indented, then you can specify them at the beginning of

indent.plx

; furthermore, if you have a special rule for indentation of a certain environment (perhaps double tab? or a single space?) you can specify that as well.

If the environment matches one that has alignment delimiters, such as

tabular

,

align

, or any other type that you specify, then the block will be stored for processing in the subroutine

format_block

. This subroutine loops through the rows, splits each row at the

&

and measures the size of the column. This allows it to output to a formatted string using

sprintf

.

The script will also match commands such as

\parbox{}

that may split their braces across lines, provided that the opening brace starts on the same line as the command,

\parbox{...

and the finishing brace finishes on its own line.

The script is mainly designed for ‘chapter’ files; by default it will not operate on the preamble.

Is this script for you?

Possibly 🙂 Hopefully. But maybe not. Whenever you’re working with a script that modifies a text file, you should be very careful. Before you try it out on your important documents, try it on the file

sampleBEFORE.tex

and see what you think. Inspect the code, and see if my (what I hope is fairly orthodox) style fits with yours. If it does, then take it for a spin on one of you own files- but please always make a back up first! The script does work in a lot of situations, but there are others when it may fail, I don’t claim that it will work for every

.tex

file ever produced.

How do you use the script?

If you’re on .*nix then you can run it from the command line using

perl indent.plx myfile.tex

and if you want to output to a file, then you can use

perl indent.plx myfile.tex> outputfile.tex

.

Of course, you could make it executable (

chmod +x indent.plx

) and put it with your other executable files- I use

/usr/local/bin

but other choices are available.

Windows users need a Perl installation. Paulo’s excellent answer to How to make the rmligs script available globally on windows will be helpful.

Moving forward

As a huge fan of open source material, I encourage anyone and everyone to dive in and make improvements. If it’s useful enough that anyone would like to collaborate and improve the script, I’d be very interested in doing so. For the moment, let’s communicate through the chat here on tex exchange.

I hope it’s useful; if it’s not directly useful, I hope that perhaps it gives you an idea of how you might make it useful, or create something of your own 🙂

Final disclaimer: I don’t claim to be a Perl expert- I’m sure that the code could be improved 🙂

8 thoughts

  1. 1) We have some entity-trouble in “perl indent.plx myfile.tex> outputfile.tex.”
    2) per indent.plx foo.tex > foo.tex results in an empty foo.tex — I assume that’s because doing so violates basic rules of command line behavior?

  2. Any possibility or interest in making this available for processing stdin? I ask as this seems like it would be useful to use as a ‘user command’ type thing in some editors, just on selected text.

Leave a Reply to Peeter Joot Cancel reply

Your email address will not be published. Required fields are marked *