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,
users can (in Normal mode) press
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
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.
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
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
, we obtain
which, I hope you’ll agree, is a lot nicer to look at.
Here’s another example- a fairly standard
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
, we obtain the following
How does it work?
The script loops through the input file, and checks for matches of the form
. 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
; 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
, or any other type that you specify, then the block will be stored for processing in the subroutine
. 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
The script will also match commands such as
that may split their braces across lines, provided that the opening brace starts on the same line as the command,
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
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
file ever produced.
How do you use the script?
If you’re on .*nix then you can run it from the command line using
and if you want to output to a file, then you can use
Of course, you could make it executable (
) and put it with your other executable files- I use
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.
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 🙂
Amazing script, Chris!
Thanks Paulo 🙂 And thanks for the encouragement along the way 🙂
Very useful script Chris. It’s really awesome.
Thanks Harish! Thanks for helping find bugs too 🙂
git mv liscense.txt license.txt
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?
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.