summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/latexindent/latexindent.pl
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-02-24 22:07:42 +0000
committerKarl Berry <karl@freefriends.org>2017-02-24 22:07:42 +0000
commit990e60c6ed4437e5b632b7c9acf7f2237bbda871 (patch)
tree4dc9ea04f5fa46cc8ac59faa8dd62e4f8bc6835b /Master/texmf-dist/scripts/latexindent/latexindent.pl
parent2e70942b44a972908c3180dd7a3c68be51afc466 (diff)
latexindent (23feb17)
git-svn-id: svn://tug.org/texlive/trunk@43326 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/latexindent/latexindent.pl')
-rwxr-xr-xMaster/texmf-dist/scripts/latexindent/latexindent.pl2132
1 files changed, 27 insertions, 2105 deletions
diff --git a/Master/texmf-dist/scripts/latexindent/latexindent.pl b/Master/texmf-dist/scripts/latexindent/latexindent.pl
index cdd979a8ccf..06adc58a1b8 100755
--- a/Master/texmf-dist/scripts/latexindent/latexindent.pl
+++ b/Master/texmf-dist/scripts/latexindent/latexindent.pl
@@ -11,57 +11,34 @@
#
# See http://www.gnu.org/licenses/.
#
-# For details of how to use this file, please see readme.txt
+# Chris Hughes, 2017
+#
+# For all communication, please visit: https://github.com/cmhughes/latexindent.pl
-# load packages/modules: assume strict and warnings are part of every perl distribution
use strict;
use warnings;
+use FindBin; # help find defaultSettings.yaml
+use Getopt::Long; # to get the switches/options/flags
-# list of modules
-my @listOfModules = ('FindBin','YAML::Tiny','File::Copy','File::Basename','Getopt::Long','File::HomeDir');
-
-# check the other modules are available
-foreach my $moduleName (@listOfModules) {
- # references:
- # http://stackoverflow.com/questions/251694/how-can-i-check-if-i-have-a-perl-module-before-using-it
- # http://stackoverflow.com/questions/1917261/how-can-i-dynamically-include-perl-modules-without-using-eval
- eval {
- (my $file = $moduleName) =~ s|::|/|g;
- require $file . '.pm';
- $moduleName->import();
- 1;
- } or die "$moduleName Perl Module not currently installed; please install the module, and then try running latexindent.pl again; exiting";
-}
-
-# now that we have confirmed the modules are available, load them
-use FindBin; # help find defaultSettings.yaml
-use YAML::Tiny; # interpret defaultSettings.yaml and other potential settings files
-use File::Copy; # to copy the original file to backup (if overwrite option set)
-use File::Basename; # to get the filename and directory path
-use Getopt::Long; # to get the switches/options/flags
-use File::HomeDir; # to get users home directory, regardless of OS
+# use lib to make sure that @INC contains the latexindent directory
+use lib $FindBin::RealBin;
+use LatexIndent::Document;
# get the options
-my $overwrite;
-my $outputToFile;
-my $silentMode;
-my $tracingMode;
-my $tracingModeVeryDetailed;
-my $readLocalSettings=0;
-my $onlyDefault;
-my $showhelp;
-my $cruftDirectory;
+my %switches = (readLocalSettings=>0);
GetOptions (
- "overwrite|w"=>\$overwrite,
-"outputfile|o"=>\$outputToFile,
-"silent|s"=>\$silentMode,
-"trace|t"=>\$tracingMode,
-"ttrace|tt"=>\$tracingModeVeryDetailed,
-"local|l:s"=>\$readLocalSettings,
-"onlydefault|d"=>\$onlyDefault,
-"help|h"=>\$showhelp,
-"cruft|c=s"=>\$cruftDirectory,
+ "silent|s"=>\$switches{silentMode},
+ "trace|t"=>\$switches{trace},
+ "ttrace|tt"=>\$switches{ttrace},
+ "local|l:s"=>\$switches{readLocalSettings},
+ "onlydefault|d"=>\$switches{onlyDefault},
+ "overwrite|w"=>\$switches{overwrite},
+ "outputfile|o=s"=>\$switches{outputToFile},
+ "modifylinebreaks|m"=>\$switches{modifyLineBreaks},
+ "logfile|g=s"=>\$switches{logFileName},
+ "help|h"=>\$switches{showhelp},
+ "cruft|c=s"=>\$switches{cruftDirectory},
);
# check local settings doesn't interfer with reading the file;
@@ -74,20 +51,9 @@ GetOptions (
#
# In such circumstances, we correct the mistake by assuming that
# the only argument is the file to be indented, and place it in @ARGV
-if($readLocalSettings and scalar(@ARGV) < 1) {
- push(@ARGV,$readLocalSettings);
- $readLocalSettings = '';
-}
-
-# this can also happen if the script is called as
-#
-# latexindent.pl -o -l myfile.tex outputfile.tex
-#
-# in which case, the GetOptions routine mistakes myfile.tex
-# as the optional parameter to the l flag.
-if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) {
- unshift(@ARGV,$readLocalSettings);
- $readLocalSettings = '';
+if($switches{readLocalSettings} and scalar(@ARGV) < 1) {
+ push(@ARGV,$switches{readLocalSettings});
+ $switches{readLocalSettings} = '';
}
# default value of readLocalSettings
@@ -95,2054 +61,10 @@ if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) {
# latexindent -l myfile.tex
#
# means that we wish to use localSettings.yaml
-if(defined($readLocalSettings) and ($readLocalSettings eq '')){
- $readLocalSettings = 'localSettings.yaml';
-}
-
-# detailed tracing mode also implies regular tracing mode
-$tracingMode = $tracingModeVeryDetailed ? 1 : $tracingMode;
-
-# version number
-my $versionNumber = "2.2";
-
-# Check the number of input arguments- if it is 0 then simply
-# display the list of options (like a manual)
-if(scalar(@ARGV) < 1 or $showhelp) {
- print <<ENDQUOTE
-latexindent.pl version $versionNumber
-usage: latexindent.pl [options] [file][.tex]
- -h, --help
- help (see the documentation for detailed instructions and examples)
- -o, --outputfile
- output to another file; sample usage
- latexindent.pl -o myfile.tex outputfile.tex
- -w, --overwrite
- overwrite the current file- a backup will be made, but still be careful
- -s, --silent
- silent mode- no output will be given to the terminal
- -t, --trace
- tracing mode- verbose information given to the log file
- -l, --local[=myyaml.yaml]
- use localSettings.yaml (assuming it exists in the directory of your file);
- alternatively, use myyaml.yaml, if it exists
- -d, --onlydefault
- ONLY use defaultSettings.yaml, ignore ALL user files
- -c, --cruft=<cruft directory>
- used to specify the location of backup files and indent.log
-ENDQUOTE
- ;
- exit(2);
-}
-
-# set up default for cruftDirectory using the one from the input file,
-# unless it has been specified using -c="/some/directory"
-$cruftDirectory=dirname $ARGV[0] unless(defined($cruftDirectory));
-
-die "Could not find directory $cruftDirectory\nExiting, no indentation done." if(!(-d $cruftDirectory));
-
-# we'll be outputting to the logfile and to standard output
-my $logfile;
-my $out = *STDOUT;
-
-# open the log file
-open($logfile,">","$cruftDirectory/indent.log") or die "Can't open indent.log";
-
-# output time to log file
-my $time = localtime();
-print $logfile $time;
-
-# output version to log file
-print $logfile <<ENDQUOTE
-
-$FindBin::Script version $versionNumber, a script to indent .tex files
-$FindBin::Script lives here: $FindBin::RealBin/
-
-ENDQUOTE
-;
-
-# latexindent.exe is a standalone executable, and caches
-# the required perl modules onto the users system; they will
-# only be displayed if the user specifies the trace option
-if($FindBin::Script eq 'latexindent.exe' and !$tracingMode ) {
-print $logfile <<ENDQUOTE
-$FindBin::Script is a standalone script and caches the required perl modules
-onto your system. If you'd like to see their location in your log file, indent.log,
-call the script with the tracing option, e.g latexindent.exe -t myfile.tex
-
-ENDQUOTE
-;
-}
-
-# output location of modules
-if($FindBin::Script eq 'latexindent.pl' or ($FindBin::Script eq 'latexindent.exe' and $tracingMode )) {
- print $logfile "Modules are being loaded from the following directories:\n ";
- foreach my $moduleName (@listOfModules) {
- (my $file = $moduleName) =~ s|::|/|g;
- require $file . '.pm';
- print $logfile "\t",$INC{$file .'.pm'},"\n";
- }
-}
-
-# a quick options check
-if($outputToFile and $overwrite) {
- print $logfile <<ENDQUOTE
-
-WARNING:
-\t You have called latexindent.pl with both -o and -w
-\t -o (output to file) will take priority, and -w (over write) will be ignored
-
-ENDQUOTE
-;
- $overwrite = 0;
-}
-
-# can't call the script with MORE THAN 2 files
-if(scalar(@ARGV)>2) {
- for my $fh ($out,$logfile) {print $fh <<ENDQUOTE
-
-ERROR:
-\t You're calling latexindent.pl with more than two file names
-\t The script can take at MOST two file names, but you
-\t need to call it with the -o switch; for example
-
-\t latexindent.pl -o originalfile.tex outputfile.tex
-
-No indentation done :(
-Exiting...
-ENDQUOTE
- };
- exit(2);
-}
-
-# don't call the script with 2 files unless the -o flag is active
-if(!$outputToFile and scalar(@ARGV)==2)
-{
-for my $fh ($out,$logfile) {
-print $fh <<ENDQUOTE
-
-ERROR:
-\t You're calling latexindent.pl with two file names, but not the -o flag.
-\t Did you mean to use the -o flag ?
-
-No indentation done :(
-Exiting...
-ENDQUOTE
-};
- exit(2);
-}
-
-# if the script is called with the -o switch, then check that
-# a second file is present in the call, e.g
-# latexindent.pl -o myfile.tex output.tex
-if($outputToFile and scalar(@ARGV)==1) {
- for my $fh ($out,$logfile) {print $fh <<ENDQUOTE
-ERROR: When using the -o flag you need to call latexindent.pl with 2 arguments
-
-latexindent.pl -o "$ARGV[0]" [needs another name here]
-
-No indentation done :(
-Exiting...
-ENDQUOTE
-};
- exit(2);
+if(defined($switches{readLocalSettings}) and ($switches{readLocalSettings} eq '')){
+ $switches{readLocalSettings} = 'localSettings.yaml';
}
-# yaml work
-print $logfile "YAML files:\n";
-
-# Read in defaultSettings.YAML file
-my $defaultSettings = YAML::Tiny->new;
-
-# Open defaultSettings.yaml
-$defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" );
-print $logfile "\tReading defaultSettings.yaml from $FindBin::RealBin/defaultSettings.yaml\n\n" if($defaultSettings);
-
-# if latexindent.exe is invoked from TeXLive, then defaultSettings.yaml won't be in
-# the same directory as it; we need to navigate to it
-if(!$defaultSettings) {
- $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml");
- print $logfile "\tReading defaultSettings.yaml (2nd attempt, TeXLive, Windows) from $FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml\n\n" if($defaultSettings);
-}
-
-# if both of the above attempts have failed, we need to exit
-if(!$defaultSettings) {
- for my $fh ($out,$logfile) {
- print $fh <<ENDQUOTE
- ERROR There seems to be a yaml formatting error in defaultSettings.yaml
- Please check it for mistakes- you can find a working version at https://github.com/cmhughes/latexindent.pl
- if you would like to overwrite your current version
-
- Exiting, no indendation done.
-ENDQUOTE
-};
- exit(2);
-}
-
-# the MASTER settings will initially be from defaultSettings.yaml
-# and we update them with USER settings (if any) below
-my %masterSettings = %{$defaultSettings->[0]};
-
-# empty array to store the paths
-my @absPaths;
-
-# scalar to read user settings
-my $userSettings;
-
-# get information about user settings- first check if indentconfig.yaml exists
-my $indentconfig = File::HomeDir->my_home . "/indentconfig.yaml";
-# if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml
-$indentconfig = File::HomeDir->my_home . "/.indentconfig.yaml" if(! -e $indentconfig);
-
-if ( -e $indentconfig and !$onlyDefault ) {
- print $logfile "\tReading path information from $indentconfig\n";
- # if both indentconfig.yaml and .indentconfig.yaml exist
- if ( -e File::HomeDir->my_home . "/indentconfig.yaml" and -e File::HomeDir->my_home . "/.indentconfig.yaml") {
- print $logfile File::HomeDir->my_home,"/.indentconfig.yaml has been found, but $indentconfig takes priority\n";
- } elsif ( -e File::HomeDir->my_home . "/indentconfig.yaml" ) {
- print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/.indentconfig.yaml can be used\n";
-
- } elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) {
- print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/indentconfig.yaml can be used\n";
- }
-
- # read the absolute paths from indentconfig.yaml
- $userSettings = YAML::Tiny->read( "$indentconfig" );
-
- # integrity check
- if($userSettings) {
- print $logfile "\t",Dump \%{$userSettings->[0]};
- print $logfile "\n";
- @absPaths = @{$userSettings->[0]->{paths}};
- } else {
- print $logfile <<ENDQUOTE
-WARNING: $indentconfig
- contains some invalid .yaml formatting- unable to read from it.
- No user settings loaded.
-ENDQUOTE
-;
- }
-} else {
- if($onlyDefault) {
- print $logfile "\tOnly default settings requested, not reading USER settings from $indentconfig\n";
- print $logfile "\tIgnoring $readLocalSettings\n" if($readLocalSettings);
- $readLocalSettings = 0;
- } else {
- # give the user instructions on where to put indentconfig.yaml or .indentconfig.yaml
- print $logfile "\tHome directory is ",File::HomeDir->my_home,"\n";
- print $logfile "\tTo specify user settings you would put indentconfig.yaml here: \n\t",File::HomeDir->my_home,"/indentconfig.yaml\n\n";
- print $logfile "\tAlternatively, you can use the hidden file .indentconfig.yaml as: \n\t",File::HomeDir->my_home,"/.indentconfig.yaml\n\n";
- }
-}
-
-# get information about LOCAL settings, assuming that $readLocalSettings exists
-my $directoryName = dirname $ARGV[0];
-
-# add local settings to the paths, if appropriate
-if ( (-e "$directoryName/$readLocalSettings") and $readLocalSettings and !(-z "$directoryName/$readLocalSettings")) {
- print $logfile "\tAdding $directoryName/$readLocalSettings to paths\n\n";
- push(@absPaths,"$directoryName/$readLocalSettings");
-} elsif ( !(-e "$directoryName/$readLocalSettings") and $readLocalSettings) {
- print $logfile "\tWARNING yaml file not found: \n\t$directoryName/$readLocalSettings not found\n";
- print $logfile "\t\tcarrying on without it.\n";
-}
-
-# read in the settings from each file
-foreach my $settings (@absPaths) {
- # check that the settings file exists and that it isn't empty
- if (-e $settings and !(-z $settings)) {
- print $logfile "\tReading USER settings from $settings\n";
- $userSettings = YAML::Tiny->read( "$settings" );
-
- # if we can read userSettings
- if($userSettings) {
- # update the MASTER setttings to include updates from the userSettings
- while(my($userKey, $userValue) = each %{$userSettings->[0]}) {
- # the update approach is slightly different for hashes vs scalars/arrays
- if (ref($userValue) eq "HASH") {
- while(my ($userKeyFromHash,$userValueFromHash) = each %{$userSettings->[0]{$userKey}}) {
- $masterSettings{$userKey}{$userKeyFromHash} = $userValueFromHash;
- }
- } else {
- $masterSettings{$userKey} = $userValue;
- }
- }
- # output settings to $logfile
- if($masterSettings{logFilePreferences}{showEveryYamlRead}){
- print $logfile Dump \%{$userSettings->[0]};
- print $logfile "\n";
- } else {
- print $logfile "\t\tNot showing settings in the log file, see showEveryYamlRead.\n";
- }
- } else {
- # otherwise print a warning that we can not read userSettings.yaml
- print $logfile "WARNING\n\t$settings \n\t contains invalid yaml format- not reading from it\n";
- }
- } else {
- # otherwise keep going, but put a warning in the log file
- print $logfile "\nWARNING\n\t",File::HomeDir->my_home,"/indentconfig.yaml\n";
- if (-z $settings) {
- print $logfile "\tspecifies $settings \n\tbut this file is EMPTY- not reading from it\n\n"
- } else {
- print $logfile "\tspecifies $settings \n\tbut this file does not exist- unable to read settings from this file\n\n"
- }
- }
-}
-
-# some people may wish to see showAlmagamatedSettings
-# which details the overall state of the settings modified
-# from the default in various user files
-if($masterSettings{logFilePreferences}{showAlmagamatedSettings}){
- print $logfile "Almagamated/overall settings to be used:\n";
- print $logfile Dump \%masterSettings ;
-}
-
-# scalar variables
-my $defaultIndent = $masterSettings{defaultIndent};
-my $alwaysLookforSplitBraces = $masterSettings{alwaysLookforSplitBraces};
-my $alwaysLookforSplitBrackets = $masterSettings{alwaysLookforSplitBrackets};
-my $backupExtension = $masterSettings{backupExtension};
-my $indentPreamble = $masterSettings{indentPreamble};
-my $onlyOneBackUp = $masterSettings{onlyOneBackUp};
-my $maxNumberOfBackUps = $masterSettings{maxNumberOfBackUps};
-my $removeTrailingWhitespace = $masterSettings{removeTrailingWhitespace};
-my $cycleThroughBackUps = $masterSettings{cycleThroughBackUps};
-
-# hash variables
-my %lookForAlignDelims= %{$masterSettings{lookForAlignDelims}};
-my %indentRules= %{$masterSettings{indentRules}};
-my %verbatimEnvironments= %{$masterSettings{verbatimEnvironments}};
-my %noIndentBlock= %{$masterSettings{noIndentBlock}};
-my %checkunmatched= %{$masterSettings{checkunmatched}};
-my %checkunmatchedELSE= %{$masterSettings{checkunmatchedELSE}};
-my %checkunmatchedbracket= %{$masterSettings{checkunmatchedbracket}};
-my %noAdditionalIndent= %{$masterSettings{noAdditionalIndent}};
-my %indentAfterHeadings= %{$masterSettings{indentAfterHeadings}};
-my %indentAfterItems= %{$masterSettings{indentAfterItems}};
-my %itemNames= %{$masterSettings{itemNames}};
-my %constructIfElseFi= %{$masterSettings{constructIfElseFi}};
-my %fileExtensionPreference= %{$masterSettings{fileExtensionPreference}};
-my %fileContentsEnvironments= %{$masterSettings{fileContentsEnvironments}};
-
-# original name of file
-my $fileName = $ARGV[0];
-
-# sort the file extensions by preference
-my @fileExtensions = sort { $fileExtensionPreference{$a} <=> $fileExtensionPreference{$b} } keys(%fileExtensionPreference);
-
-# get the base file name, allowing for different extensions (possibly no extension)
-my ($dir, $name, $ext) = fileparse($fileName, @fileExtensions);
-
-# quick check to make sure given file type is supported
-if( -e $ARGV[0] and !$ext ){
-for my $fh ($out,$logfile) {print $fh <<ENDQUOTE
-The file $ARGV[0] exists , but the extension does not correspond to any given in fileExtensionPreference;
-consinder updating fileExtensionPreference.
-
-Exiting, no indentation done.
-ENDQUOTE
-};
-exit(2);
-}
-
-# if no extension, search according to fileExtensionPreference
-if (!$ext) {
- print $logfile "File extension work:\n";
- print $logfile "\tlatexindent called to act upon $fileName with an, as yet, unrecognised file extension;\n";
- print $logfile "\tsearching for file with an extension in the following order (see fileExtensionPreference):\n\t\t";
- print $logfile join("\n\t\t",@fileExtensions),"\n";
- my $fileFound = 0;
- # loop through the known file extensions (see @fileExtensions)
- foreach my $fileExt (@fileExtensions ){
- if ( -e $fileName.$fileExt ) {
- print $logfile "\t",$fileName,$fileExt," found!\n";
- $fileName .= $fileExt;
- print $logfile "\tUpdated $ARGV[0] to ",$fileName,"\n";
- $fileFound = 1;
- last;
- }
- }
- unless($fileFound){
- print $logfile "\tI couldn't find a match for $ARGV[0] in fileExtensionPreference (see defaultSettings.yaml)\n";
- foreach my $fileExt (@fileExtensions ){
- print $logfile "\t\tI searched for $ARGV[0]$fileExt\n";
- }
- print $logfile "\tbut couldn't find any of them.\n";
- print $logfile "\tConsider updating fileExtensionPreference. \nError: Exiting, no indendation done.";
- die "I couldn't find a match for $ARGV[0] in fileExtensionPreference.\nExiting, no indendation done.\n"
- }
- } else {
- # if the file has a recognised extension, check that the file exists
- unless( -e $ARGV[0] ){
- print $logfile "Error: I couldn't find $ARGV[0], are you sure it exists?. No indentation done. \nExiting.\n";
- die "Error: I couldn't find $ARGV[0], are you sure it exists?. Exiting.\n" ;
- }
- }
-
-# if we want to over write the current file create a backup first
-if ($overwrite) {
- print $logfile "\nBackup procedure:\n";
- # cruft directory
- print $logfile "\tDirectory for backup files and indent.log: $cruftDirectory\n\n";
-
- my $backupFile;
-
- # backup file name is the base name
- $backupFile = basename($fileName,@fileExtensions);
-
- # add the user's backup directory to the backup path
- $backupFile = "$cruftDirectory/$backupFile";
-
- # if both ($onlyOneBackUp and $maxNumberOfBackUps) then we have
- # a conflict- er on the side of caution and turn off onlyOneBackUp
- if($onlyOneBackUp and $maxNumberOfBackUps>1) {
- print $logfile "\t WARNING: onlyOneBackUp=$onlyOneBackUp and maxNumberOfBackUps: $maxNumberOfBackUps\n";
- print $logfile "\t\t setting onlyOneBackUp=0 which will allow you to reach $maxNumberOfBackUps back ups\n";
- $onlyOneBackUp = 0;
- }
-
- # if the user has specified that $maxNumberOfBackUps = 1 then
- # they only want one backup
- if($maxNumberOfBackUps==1) {
- $onlyOneBackUp=1 ;
- print $logfile "\t FYI: you set maxNumberOfBackUps=1, so I'm setting onlyOneBackUp: 1 \n";
- } elsif($maxNumberOfBackUps<=0 and !$onlyOneBackUp) {
- $onlyOneBackUp=0 ;
- $maxNumberOfBackUps=-1;
- }
-
- # if onlyOneBackUp is set, then the backup file will
- # be overwritten each time
- if($onlyOneBackUp) {
- $backupFile .= $backupExtension;
- print $logfile "\tcopying $fileName to $backupFile\n";
- print $logfile "\t$backupFile was overwritten\n\n" if (-e $backupFile);
- } else {
- # start with a backup file .bak0 (or whatever $backupExtension is present)
- my $backupCounter = 0;
- $backupFile .= $backupExtension.$backupCounter;
-
- # if it exists, then keep going: .bak0, .bak1, ...
- while (-e $backupFile or $maxNumberOfBackUps>1) {
- if($backupCounter==$maxNumberOfBackUps) {
- print $logfile "\t maxNumberOfBackUps reached ($maxNumberOfBackUps)\n";
-
- # some users may wish to cycle through back up files, e.g:
- # copy myfile.bak1 to myfile.bak0
- # copy myfile.bak2 to myfile.bak1
- # copy myfile.bak3 to myfile.bak2
- #
- # current back up is stored in myfile.bak4
- if($cycleThroughBackUps) {
- print $logfile "\t cycleThroughBackUps detected (see cycleThroughBackUps) \n";
- for(my $i=1;$i<=$maxNumberOfBackUps;$i++) {
- # remove number from backUpFile
- my $oldBackupFile = $backupFile;
- $oldBackupFile =~ s/$backupExtension.*/$backupExtension/;
- my $newBackupFile = $oldBackupFile;
-
- # add numbers back on
- $oldBackupFile .= $i;
- $newBackupFile .= $i-1;
-
- # check that the oldBackupFile exists
- if(-e $oldBackupFile){
- print $logfile "\t\t copying $oldBackupFile to $newBackupFile \n";
- copy($oldBackupFile,$newBackupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n";
- }
- }
- }
-
- # rest maxNumberOfBackUps
- $maxNumberOfBackUps=1 ;
- last; # break out of the loop
- } elsif(!(-e $backupFile)) {
- $maxNumberOfBackUps=1 ;
- last; # break out of the loop
- }
- print $logfile "\t $backupFile already exists, incrementing by 1...\n";
- $backupCounter++;
- $backupFile =~ s/$backupExtension.*/$backupExtension$backupCounter/;
- }
- print $logfile "\n\t copying $fileName to $backupFile\n\n";
- }
-
- # output these lines to the log file
- print $logfile "\tBackup file: ",$backupFile,"\n";
- print $logfile "\tOverwriting file: ",$fileName,"\n\n";
- copy($fileName,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n";
-}
-
-if(!($outputToFile or $overwrite)) {
- print $logfile "Just out put to the terminal :)\n\n" if !$silentMode ;
-}
-
-
-# scalar variables
-my $line; # $line: takes the $line of the file
-my $inpreamble=!$indentPreamble;
- # $inpreamble: switch to determine if in
- # preamble or not
-my $inverbatim=0; # $inverbatim: switch to determine if in
- # a verbatim environment or not
-my $delimiters=0; # $delimiters: switch that governs if
- # we need to check for & or not
-my $trailingcomments; # $trailingcomments stores the comments at the end of
- # a line
-my $lineCounter=0; # $lineCounter keeps track of the line number
-my $inIndentBlock=0; # $inindentblock: switch to determine if in
- # a inindentblock or not
-my $inFileContents=0; # $inFileContents: switch to determine if we're in a filecontents environment
-
-# array variables
-my @lines; # @lines: stores the newly indented lines
-my @mainfile; # @mainfile: stores input file; used to
- # grep for \documentclass
-
-# array of hashes, containing details of commands & environments
-my @masterIndentationArrayOfHashes;
-
-# check to see if the current file has \documentclass, if so, then
-# it's the main file, if not, then it doesn't have preamble
-open(MAINFILE, $fileName) or die "Could not open input file, $fileName";
- @mainfile=<MAINFILE>;
-close(MAINFILE);
-
-# if the MAINFILE doesn't have a \documentclass statement, then
-# it shouldn't have preamble
-if(scalar(@{[grep(m/^\s*\\documentclass/, @mainfile)]})==0) {
- $inpreamble=0;
-
- print $logfile "Trace:\tNo documentclass detected, assuming no preamble\n" if($tracingMode);
-} else {
- print $logfile "Trace:\t documentclass detected, assuming preamble\n" if($tracingMode);
-}
-
-# the previous OPEN command puts us at the END of the file
-open(MAINFILE, $fileName) or die "Could not open input file, $fileName";
-
-# loop through the lines in the INPUT file
-while(<MAINFILE>) {
- # increment the line counter
- $lineCounter++;
-
- # very detailed output to logfile
- if($tracingModeVeryDetailed){
- if( @masterIndentationArrayOfHashes){
- print $logfile "\nLine $lineCounter\t (detailed trace) indentation hash: \n" if($tracingMode);
- for my $href ( @masterIndentationArrayOfHashes) {
- print $logfile Dump \%{$href};
- }
- }
- }
-
- # tracing mode
- print $logfile $masterSettings{logFilePreferences}{traceModeBetweenLines} if($tracingMode and !($inpreamble or $inverbatim or $inIndentBlock));
-
- # check to see if we're still in the preamble
- # or in a verbatim environment or in IndentBlock
- if(!($inpreamble or $inverbatim or $inIndentBlock)) {
- # if not, remove all leading spaces and tabs
- # from the current line, assuming it isn't empty
- s/^\t*// if($_ !~ /^((\s*)|(\t*))*$/);
- s/^\s*// if($_ !~ /^((\s*)|(\t*))*$/);
-
- # tracing mode
- print $logfile "Line $lineCounter\t removing leading spaces\n" if($tracingMode);
- } else {
- # otherwise check to see if we've reached the main
- # part of the document
- if(m/^\s*\\begin\{document\}/ and !$inFileContents and !$inverbatim) {
- $inpreamble = 0;
-
- # tracing mode
- print $logfile "Line $lineCounter\t \\begin{document} found, switching indentation searches on. \n" if($tracingMode);
- } else {
- # tracing mode
- if($inpreamble) {
- print $logfile "Line $lineCounter\t still in PREAMBLE, leaving exisiting leading space (see indentPreamble)\n" if($tracingMode);
- } elsif($inverbatim) {
- print $logfile "Line $lineCounter\t in VERBATIM-LIKE environment, leaving exisiting leading space\n" if($tracingMode);
- } elsif($inIndentBlock) {
- print $logfile "Line $lineCounter\t in NO INDENT BLOCK, leaving exisiting leading space\n" if($tracingMode);
- }
- }
- }
-
- # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ]
- # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ]
- # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ]
-
- # check to see if we're ending a filecontents environment
- if( $_ =~ m/^\s*\\end\{(.*?)\}/ and $fileContentsEnvironments{$1} and $inFileContents){
- print $logfile "Line $lineCounter\t Found END of filecontents environment (see fileContentsEnvironments)\n" if($tracingMode);
- $inFileContents = 0;
- }
-
- # set the delimiters switch
- $delimiters = @masterIndentationArrayOfHashes?$masterIndentationArrayOfHashes[-1]{alignmentDelimiters}:0;
-
- if($inverbatim){
- print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in VERBATIM-LIKE environment, looking for $masterIndentationArrayOfHashes[-1]{end} \n" if($tracingMode);
- } elsif($inIndentBlock) {
- print $logfile "Line $lineCounter\t in NO INDENT BLOCK, doing nothing\n" if($tracingMode);
- } elsif($delimiters) {
- print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in ALIGNMENT BLOCK environment, looking for $masterIndentationArrayOfHashes[-1]{end}\n" if($tracingMode);
- } elsif($inpreamble and !$inFileContents) {
- print $logfile "Line $lineCounter\t In preamble, looking for \\begin{document}\n" if($tracingMode);
- } elsif($inpreamble and $inFileContents) {
- print $logfile "Line $lineCounter\t In preamble, in filecontents environment\n" if($tracingMode);
- } else {
- print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: looking for reasons to DECREASE indentation of CURRENT line \n" if($tracingMode);
- }
-
- # check to see if we have \end{something} or \]
- &at_end_of_env_or_eq() unless ($inpreamble or $inIndentBlock);
-
- # check to see if we have %* \end{something} for alignment blocks
- # outside of environments
- &end_command_with_alignment();
-
- # check to see if we're at the end of a noindent
- # block %\end{noindent}
- &at_end_noindent();
-
- # only check for unmatched braces if we're not in
- # a verbatim-like environment or in the preamble or in a
- # noIndentBlock or in a delimiter block
- if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)) {
- # The check for closing } and ] relies on counting, so
- # we have to remove trailing comments so that any {, }, [, ]
- # that are found after % are not counted
- #
- # note that these lines are NOT in @lines, so we
- # have to store the $trailingcomments to put
- # back on after the counting
- #
- # note the use of (?<!\\)% so that we don't match \%
- if ( $_=~ m/(?<!\\)%.*/) {
- s/((?<!\\)%.*)//;
- $trailingcomments=$1;
-
- # tracing mode
- print $logfile "Line $lineCounter\t Removed trailing comments to count braces and brackets: $1\n" if($tracingMode);
- }
-
- # check to see if we're at the end of a \parbox, \marginpar
- # or other split-across-lines command and check that
- # we're not starting another command that has split braces (nesting)
- &end_command_or_key_unmatched_braces();
-
- # check to see if we're at the end of a command that splits
- # [ ] across lines
- &end_command_or_key_unmatched_brackets();
-
- # check for a heading such as \chapter, \section, etc
- &indent_heading();
-
- # check for \item
- &indent_item();
-
- # check for \else or \fi
- &indent_if_else_fi();
-
- # add the trailing comments back to the end of the line
- if(scalar($trailingcomments)) {
- # some line break magic, http://stackoverflow.com/questions/881779/neatest-way-to-remove-linebreaks-in-perl
- s/\R//;
- $_ = $_ . $trailingcomments."\n" ;
-
- # tracing mode
- print $logfile "Line $lineCounter\t counting braces/brackets complete\n" if($tracingMode);
- print $logfile "Line $lineCounter\t Adding trailing comments back on: $trailingcomments\n" if($tracingMode);
-
- # empty the trailingcomments
- $trailingcomments='';
-
- }
- # remove trailing whitespace
- if ($removeTrailingWhitespace) {
- print $logfile "Line $lineCounter\t removing trailing whitespace (see removeTrailingWhitespace)\n" if ($tracingMode);
- s/\s+$/\n/;
- }
- }
-
- # ADD CURRENT LEVEL OF INDENTATION
- # ADD CURRENT LEVEL OF INDENTATION
- # ADD CURRENT LEVEL OF INDENTATION
- # (unless we're in a delimiter-aligned block)
- if(!$delimiters) {
- # make sure we're not in a verbatim block or in the preamble
- if($inverbatim or $inpreamble or $inIndentBlock) {
- # just push the current line as is
- push(@lines,$_);
- } else {
- # add current value of indentation to the current line
- # and output it
- # unless this would only create trailing whitespace and the
- # corresponding option is set
- unless ($_ =~ m/^$/ and $removeTrailingWhitespace){
- $_ = &current_indentation().$_;
- }
- push(@lines,$_);
- # tracing mode
- print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeAddCurrentIndent} PHASE 2: Adding current level of indentation: ",&current_indentation_names(),"\n" if($tracingMode);
- }
- } else {
- # output to @block (within masterIndentationArrayOfHashes) if we're in a delimiter block
- push(@{$masterIndentationArrayOfHashes[-1]{block}},$_);
-
- # tracing mode
- print $logfile "Line $lineCounter\t In delimeter block ($masterIndentationArrayOfHashes[-1]{name}), waiting for block formatting\n" if($tracingMode);
- }
-
- # \BEGIN{ENVIRONMENT} or OPEN { or OPEN [
- # \BEGIN{ENVIRONMENT} or OPEN { or OPEN [
- # \BEGIN{ENVIRONMENT} or OPEN { or OPEN [
-
- # check to see if we're beginning a filecontents environment
- if( ($_ =~ m/^\s*\\begin\{(.*?)\}/ and $fileContentsEnvironments{$1} and !$inverbatim)){
- print $logfile "Line $lineCounter\t Found filecontents environment (see fileContentsEnvironments)\n" if($tracingMode);
- $inFileContents = 1;
- }
-
- # only check for new environments or commands if we're
- # not in a verbatim-like environment or in the preamble
- # or in a noIndentBlock, or delimiter block
- if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)) {
-
- print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeIncreaseIndent} PHASE 3: looking for reasons to INCREASE indentation of SUBSEQUENT lines \n" if($tracingMode);
-
- # check if we are in a
- # % \begin{noindent}
- # block; this is similar to a verbatim block, the user
- # may not want some blocks of code to be touched
- #
- # IMPORTANT: this needs to go before the trailing comments
- # are removed!
- &at_beg_noindent();
-
- # check for
- # %* \begin{tabular}
- # which might be used to align blocks that contain delimeters that
- # are NOT contained in an alignment block in the usual way, e.g
- # \matrix{
- # %* \begin{tabular}
- # 1 & 2 \\
- # 3 & 4 \\
- # %* \end{tabular}
- # }
- &begin_command_with_alignment();
- if(@masterIndentationArrayOfHashes){
- $delimiters = $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}||0;
- }
-
- # remove trailing comments so that any {, }, [, ]
- # that are found after % are not counted
- #
- # note that these lines are already in @lines, so we
- # can remove the trailing comments WITHOUT having
- # to put them back in
- #
- # Note that this won't match \%
- s/(?<!\\)%.*// if( $_=~ m/(?<!\\)%.*/);
-
- # tracing mode
- print $logfile "Line $lineCounter\t Removing trailing comments for brace count (line is already stored)\n" if($tracingMode);
-
- # check to see if we have \begin{something} or \[
- &at_beg_of_env_or_eq() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
- if(@masterIndentationArrayOfHashes){
- $delimiters = $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}||0;
- }
-
- # check to see if we have \parbox, \marginpar, or
- # something similar that might split braces {} across lines,
- # specified in %checkunmatched hash table
- &start_command_or_key_unmatched_braces() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
-
- # check for an else statement (braces, not \else)
- &check_for_else() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
-
- # check for a command that splits [] across lines
- &start_command_or_key_unmatched_brackets();
-
- # check for a heading
- &indent_after_heading() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
-
- # check for \item
- &indent_after_item() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
-
- # check for \if or \else command
- &indent_after_if_else_fi() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters));
-
- # tracing mode
- if($tracingMode){
- if(scalar(@masterIndentationArrayOfHashes)){
- print $logfile "Line $lineCounter\t Indentation array: ",&current_indentation_names(),"\n";
- } else {
- print $logfile "Line $lineCounter\t Indentation array empty\n";
- }
- }
- }
-}
-
-# close the main file
-close(MAINFILE);
-
-# put line count information in the log file
-print $logfile "Line Count of $fileName: ",scalar(@mainfile),"\n";
-print $logfile "Line Count of indented $fileName: ",scalar(@lines);
-if(scalar(@mainfile) != scalar(@lines))
-{
- print $logfile <<ENDQUOTE
-WARNING: \t line count of original file and indented file does
-\t not match- consider reverting to a back up, see $backupExtension;
-ENDQUOTE
-;
-} else {
- print $logfile "\n\nLine counts of original file and indented file match.\n";
-}
-
-# output the formatted lines to the terminal
-print @lines if(!$silentMode);
-
-# if -w is active then output to $ARGV[0]
-if($overwrite) {
- open(OUTPUTFILE,">",$fileName);
- print OUTPUTFILE @lines;
- close(OUTPUTFILE);
-}
-
-# if -o is active then output to $ARGV[1]
-if($outputToFile) {
- open(OUTPUTFILE,">",$ARGV[1]);
- print OUTPUTFILE @lines;
- close(OUTPUTFILE);
- print $logfile "Output from indentation written to $ARGV[1].\n";
-}
-
-# final line of the logfil
-print $logfile "\n",$masterSettings{logFilePreferences}{endLogFileWith};
-
-# close the log file
-close($logfile);
-
+my $document = LatexIndent::Document->new(name=>"masterdocument",fileName=>$ARGV[0],switches=>\%switches);
+$document->latexindent;
exit(0);
-
-sub indent_if_else_fi{
- # PURPOSE: set indentation of line that contains \else, \fi command
- #
- #
-
- # @masterIndentationArrayOfHashes could be empty -- if so, exit
- return unless @masterIndentationArrayOfHashes;
- return unless $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}};
-
- # look for \fi
- if( $_ =~ m/^\s*\\fi/) {
- # tracing mode
- print $logfile "Line $lineCounter\t \\fi command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode);
- &decrease_indent($masterIndentationArrayOfHashes[-1]{name});
- }
- # look for \else or \or
- elsif( $_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) {
- # tracing mode
- print $logfile "Line $lineCounter\t \\else command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode);
- print $logfile "Line $lineCounter\t decreasing indent, still looking for \\fi to match \\",&current_indentation_names(), "\n" if($tracingMode);
-
- # finding an \else or \or command removes the *indentation*, but not the entry from the master hash
- $masterIndentationArrayOfHashes[-1]{indent}="";
- }
-}
-
-sub indent_after_if_else_fi{
- # PURPOSE: set indentation *after* \if construct such as
- #
- # \ifnum\x=2
- # <stuff>
- # <stuff>
- # \else
- # <stuff>
- # <stuff>
- # \fi
- #
- # How to read /^\s*\\(if.*?)(\s|\\|\#)
- #
- # ^\s* begins with multiple spaces (possibly none)
- # \\(if.*?)(\s|\\|\#) matches \if... up to either a
- # space, a \, or a #
- # Note: this won't match \if.*\fi
- if( $_ =~ m/^\s*\\(if.*?)(\s|\\|\#)/ and $_ !~ m/^\s*\\(if.*?\\fi)/ and $constructIfElseFi{$1}) {
- # tracing mode
- print $logfile "Line $lineCounter\t ifelsefi construct found: $1 \n" if($tracingMode);
- &increase_indent({name=>$1,type=>"ifelseif"});
- } elsif(@masterIndentationArrayOfHashes) {
- if( ($_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) and $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}) {
- # tracing mode
- print $logfile "Line $lineCounter\t setting indent *after* \\else or \\or command found for $masterIndentationArrayOfHashes[-1]{name} \n" if($tracingMode);
-
- # recover the indentation to be implemented *after* the \else or \or
- $masterIndentationArrayOfHashes[-1]{indent}=$indentRules{$masterIndentationArrayOfHashes[-1]{name}}||$defaultIndent unless ($noAdditionalIndent{$masterIndentationArrayOfHashes[-1]{name}});
- }
- }
-}
-
-sub indent_item{
- # PURPOSE: when considering environments that can contain items, such
- # as enumerate, itemize, etc, this subroutine sets the indentation for the item *itself*
-
- return unless(scalar(@masterIndentationArrayOfHashes)>1);
- return unless $indentAfterItems{$masterIndentationArrayOfHashes[-2]{name}};
-
- if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ and $itemNames{$1}){
- # tracing mode
- print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode);
- if($itemNames{$masterIndentationArrayOfHashes[-1]{name}}) {
- print $logfile "Line $lineCounter\t $1 found - neutralizing indentation from previous ",$masterIndentationArrayOfHashes[-1]{name},"\n" if($tracingMode);
- &decrease_indent($1);
- }
- }
-
-}
-
-sub indent_after_item{
- # PURPOSE: Set the indentation *after* the item
- # This matches a line that begins with
- #
- # \item
- # \item[
- # \myitem
- # \myitem[
- #
- # or anything else specified in itemNames
- #
- return unless @masterIndentationArrayOfHashes;
- return unless $indentAfterItems{$masterIndentationArrayOfHashes[-1]{name}};
-
- if( $_ =~ m/^\s*\\(.*?)(\[|\s)/
- and $itemNames{$1}) {
- # tracing mode
- print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode);
- &increase_indent({name=>$1,type=>"item"});
- }
-}
-
-sub begin_command_with_alignment{
- # PURPOSE: This matches
- # %* \begin{tabular}
- # with any number of spaces (possibly none) between
- # the * and \begin{noindent}.
- #
- # the comment symbol IS indended!
- #
- # This is to align blocks that contain delimeters that
- # are NOT contained in an alignment block in the usual way, e.g
- # \matrix{
- # %* \begin{tabular}
- # 1 & 2 \\
- # 3 & 4 \\
- # %* \end{tabular}
- # }
-
- if( $_ =~ m/^\s*%\*\s*\\begin\{(.*?)\}/ and $lookForAlignDelims{$1}) {
- # increase the indentation
- &increase_indent({name=>$1,
- alignmentDelimiters=>1,
- type=>"environment",
- begin=>"\\begin{$1}",
- end=>"\\end{$1}"});
- # tracing mode
- print $logfile "Line $lineCounter\t Delimiter environment started: $1 (see lookForAlignDelims)\n" if($tracingMode);
- }
-}
-
-sub end_command_with_alignment{
- # PURPOSE: This matches
- # %* \end{tabular}
- # with any number of spaces (possibly none) between
- # the * and \end{tabular} (or any other name used from
- # lookFroAlignDelims)
- #
- # Note: the comment symbol IS indended!
- #
- # This is to align blocks that contain delimeters that
- # are NOT contained in an alignment block in the usual way, e.g
- # \matrix{
- # %* \begin{tabular}
- # 1 & 2 \\
- # 3 & 4 \\
- # %* \end{tabular}
- # }
- return unless @masterIndentationArrayOfHashes;
- return unless $masterIndentationArrayOfHashes[-1]{alignmentDelimiters};
-
- if( $_ =~ m/^\s*%\*\s*\\end\{(.*?)\}/ and $lookForAlignDelims{$1}) {
- # same subroutine used at the end of regular tabular, align, etc
- # environments
- if($delimiters) {
- &print_aligned_block();
- &decrease_indent($1);
- } else {
- # tracing mode
- print $logfile "Line $lineCounter\t FYI: did you mean to start a delimiter block on a previous line? \n" if($tracingMode);
- print $logfile "Line $lineCounter\t perhaps using %* \\begin{$1}\n" if($tracingMode);
- }
- }
-}
-
-sub indent_heading{
- # PURPOSE: This matches
- # \part
- # \chapter
- # \section
- # \subsection
- # \subsubsection
- # \paragraph
- # \subparagraph
- #
- # and anything else listed in indentAfterHeadings
- #
- # This subroutine specifies the indentation for the
- # heading itself, i.e the line that has \chapter, \section etc
- if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}){
- # tracing mode
- print $logfile "Line $lineCounter\t Heading found: $1 \n" if($tracingMode);
-
- # get the heading settings, it's a hash within a hash
- my %currentHeading = %{$indentAfterHeadings{$1}};
-
- # $previousHeadingLevel: scalar that stores which heading
- # we are under: \part, \chapter, etc
- my $previousHeadingLevel=0;
-
- # form an array of the headings available
- my @headingStore=();
- foreach my $env (@masterIndentationArrayOfHashes){
- if($env->{type} eq 'heading'){
- push(@headingStore,$env->{name});
- # update heading level
- $previousHeadingLevel= $env->{headinglevel};
- }
- }
-
- # if current heading level < old heading level,
- if($currentHeading{level}<$previousHeadingLevel) {
- # decrease indentation, but only if
- # specified in indentHeadings. Note that this check
- # needs to be done here- decrease_indent won't
- # check a nested hash
-
- if(scalar(@headingStore)) {
- while($currentHeading{level}<$previousHeadingLevel and scalar(@headingStore)) {
- my $higherHeadingName = pop(@headingStore);
- my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}};
-
- # tracing mode
- print $logfile "Line $lineCounter\t stepping UP heading level from $higherHeadingName \n" if($tracingMode);
-
- &decrease_indent($higherHeadingName) if($higherLevelHeading{indent});
- $previousHeadingLevel=$higherLevelHeading{level};
- }
- # put the heading name back in to storage
- push(@headingStore,$1);
- }
- } elsif($currentHeading{level}==$previousHeadingLevel) {
- if(scalar(@headingStore)) {
- my $higherHeadingName = pop(@headingStore);
- my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}};
- &decrease_indent($higherHeadingName) if($higherLevelHeading{indent});
- }
- }
- }
-}
-
-sub indent_after_heading{
- # PURPOSE: This matches
- # \part
- # \chapter
- # \section
- # \subsection
- # \subsubsection
- # \paragraph
- # \subparagraph
- #
- # and anything else listed in indentAfterHeadings
- #
- # This subroutine is specifies the indentation for
- # the text AFTER the heading, i.e the body of conent
- # in each \chapter, \section, etc
- if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}) {
- # get the heading settings- it's a hash within a hash
- my %currentHeading = %{$indentAfterHeadings{$1}};
-
- &increase_indent({name=>$1,type=>"heading",headinglevel=>$currentHeading{level}}) if($currentHeading{indent});
- }
-}
-
-sub at_end_noindent{
- # PURPOSE: This matches
- # % \end{noindent}
- # with any number of spaces (possibly none) between
- # the comment and \end{noindent}.
- #
- # the comment symbol IS indended!
- #
- # This is for blocks of code that the user wants
- # to leave untouched- similar to verbatim blocks
-
- if( $_ =~ m/^%\s*\\end\{(.*?)\}/ and $noIndentBlock{$1}) {
- $inIndentBlock=0;
- # tracing mode
- print $logfile "Line $lineCounter\t % \\end{no indent block} found, switching inIndentBlock OFF \n" if($tracingMode);
- }
-}
-
-sub at_beg_noindent{
- # PURPOSE: This matches
- # % \begin{noindent}
- # with any number of spaces (possibly none) between
- # the comment and \begin{noindent}.
- #
- # the comment symbol IS indended!
- #
- # This is for blocks of code that the user wants
- # to leave untouched- similar to verbatim blocks
-
- if( $_ =~ m/^%\s*\\begin\{(.*?)\}/ and $noIndentBlock{$1}) {
- $inIndentBlock = 1;
- # tracing mode
- print $logfile "Line $lineCounter\t % \\begin{no indent block} found, switching inIndentBlock ON \n" if($tracingMode);
- }
-}
-
-sub start_command_or_key_unmatched_brackets{
- # PURPOSE: This matches
- # \pgfplotstablecreatecol[...
- #
- # or any other command/key that has brackets [ ]
- # split across lines specified in the
- # hash tables, %checkunmatchedbracket
- #
- # How to read: ^\s*(\\)?(.*?)(\[\s*)
- #
- # ^ line begins with
- # \s* any (or no)spaces
- # (\\)? matches a \ backslash but not necessarily
- # (.*?) non-greedy character match and store the result
- # ((?<!\\)\[\s*) match [ possibly leading with spaces
- # but it WON'T match \[
-
- if ($_ =~ m/^\s*(\\)?(.*?)(\s*(?<!\\)\[)/
- and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets)) {
- # store the command name, because $2
- # will not exist after the next match
- my $commandname = $2;
- my $matchedBRACKETS=0;
-
- # match [ but don't match \[
- $matchedBRACKETS++ while ($_ =~ /(?<!\\)\[/g);
- # match ] but don't match \]
- $matchedBRACKETS-- while ($_ =~ /(?<!\\)\]/g);
-
- # set the indentation
- if($matchedBRACKETS != 0 ) {
- # tracing mode
- print $logfile "Line $lineCounter\t Found opening BRACKET [ $commandname\n" if($tracingMode);
-
- &increase_indent({name=>$commandname,matchedBRACKETS=>$matchedBRACKETS,type=>'splitBrackets'});
- }
- }
-}
-
-sub end_command_or_key_unmatched_brackets{
- # PURPOSE: Check for the closing BRACKET of a command that
- # splits its BRACKETS across lines, such as
- #
- # \pgfplotstablecreatecol[ ...
- #
- # It works by checking if we have any entries
- # in the array @masterIndentationArrayOfHashes, and making
- # sure that we're not starting another command/key
- # that has split BRACKETS (nesting).
- #
- # It also checks that the line is not commented.
- #
- # We count the number of [ and ADD to the counter
- # ] and SUBTRACT to the counter
- return unless @masterIndentationArrayOfHashes;
- return unless ($masterIndentationArrayOfHashes[-1]{type} eq 'splitBrackets');
- print $logfile "Line $lineCounter\t Searching for closing BRACKET ] $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode);
-
- if(!($_ =~ m/^\s*(\\)?(.*?)(\s*\[)/
- and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets))
- and $_ !~ m/^\s*%/) {
-
- # get the details of the most recent command name
- my $commandname = $masterIndentationArrayOfHashes[-1]{name};
- my $matchedBRACKETS = $masterIndentationArrayOfHashes[-1]{matchedBRACKETS};
-
- # match [ but don't match \[
- $matchedBRACKETS++ while ($_ =~ m/(?<!\\)\[/g);
-
- # match ] but don't match \]
- $matchedBRACKETS-- while ($_ =~ m/(?<!\\)\]/g);
-
- # if we've matched up the BRACKETS then
- # we can decrease the indent by 1 level
- if($matchedBRACKETS == 0){
- # tracing mode
- print $logfile "Line $lineCounter\t Found closing BRACKET ] $commandname\n" if($tracingMode);
-
- # decrease the indentation (if appropriate)
- &decrease_indent($commandname);
- } else {
- # otherwise we need to enter the new value
- # of $matchedBRACKETS and the value of $command
- # back into storage
- $masterIndentationArrayOfHashes[-1]{matchedBRACKETS} = $matchedBRACKETS;
-
- # tracing mode
- print $logfile "Line $lineCounter\t Searching for closing BRACKET ] $commandname\n" if($tracingMode);
- }
- }
-}
-
-sub start_command_or_key_unmatched_braces{
- # PURPOSE: This matches
- # \parbox{...
- # \parbox[..]..{
- # empty header/.style={
- # \foreach \something
- # etc
- #
- # or any other command/key that has BRACES
- # split across lines specified in the
- # hash tables, %checkunmatched, %checkunmatchedELSE
- #
- # How to read: ^\s*(\\)?(.*?)(\[|{|\s)
- #
- # ^ line begins with
- # \s* any (or no) spaces
- # (\\)? matches a \ backslash but not necessarily
- # (.*?) non-greedy character match and store the result
- # (\[|}|=|(\s*\\)) either [ or { or = or space \
-
- if ($_ =~ m/^\s*(\\)?(.*?)(\[|{|=|(\s*\\))/
- and ($checkunmatched{$2} or $checkunmatchedELSE{$2}
- or $alwaysLookforSplitBraces)
- ) {
- # store the command name, because $2
- # will not exist after the next match
- my $commandname = $2;
- my $matchedbraces=0;
-
- # by default, don't look for an else construct
- my $lookforelse=$checkunmatchedELSE{$2}||0;
-
- # match { but don't match \{
- $matchedbraces++ while ($_ =~ /(?<!\\){/g);
-
- # match } but don't match \}
- $matchedbraces-- while ($_ =~ /(?<!\\)}/g);
-
- # tracing mode
- print $logfile "Line $lineCounter\t matchedbraces = $matchedbraces\n" if($tracingMode);
-
- # set the indentation
- if($matchedbraces > 0 ) {
- # tracing mode
- print $logfile "Line $lineCounter\t Found opening BRACE { $commandname\n" if($tracingMode);
-
- &increase_indent({name=>$commandname,
- matchedbraces=>$matchedbraces,
- lookforelse=>$lookforelse,
- countzeros=>0,
- type=>"splitbraces"});
- } elsif($matchedbraces<0) {
- # if $matchedbraces < 0 then we must be matching
- # braces from a previous split-braces command
-
- # keep matching { OR }, and don't match \{ or \}
- while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) {
-
- # store the match, either { or }
- my $braceType = $1;
-
- # exit the loop if @masterIndentationArrayOfHashes[-1] is empty
- last if(!@masterIndentationArrayOfHashes);
-
- # exit the loop if we're not looking for split braces
- last if($masterIndentationArrayOfHashes[-1]{type} ne 'splitbraces');
-
- # get the details of the most recent command name
- $commandname = $masterIndentationArrayOfHashes[-1]{name};
- $matchedbraces = $masterIndentationArrayOfHashes[-1]{'matchedbraces'};
- my $countzeros = $masterIndentationArrayOfHashes[-1]{'countzeros'};
- $lookforelse= $masterIndentationArrayOfHashes[-1]{'lookforelse'};
-
- $matchedbraces++ if($1 eq "{");
- $matchedbraces-- if($1 eq "}");
-
- # update the matched braces count
- $masterIndentationArrayOfHashes[-1]{matchedbraces} = $matchedbraces;
-
- # if we've matched up the braces then
- # we can decrease the indent by 1 level
- if($matchedbraces == 0) {
- $countzeros++ if $lookforelse;
-
- # tracing mode
- print $logfile "Line $lineCounter\t Found closing BRACE } $1\n" if($tracingMode);
-
- # decrease the indentation (if appropriate)
- &decrease_indent($commandname);
-
- if($countzeros==1) {
- $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces;
- $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros;
- $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse;
- }
- }
- }
- }
- }
-}
-
-sub end_command_or_key_unmatched_braces{
- # PURPOSE: Check for the closing BRACE of a command that
- # splits its BRACES across lines, such as
- #
- # \parbox{ ...
- #
- # or one of the tikz keys, such as
- #
- # empty header/.style={
- #
- # It works by checking if we have any entries
- # in the array @masterIndentationArrayOfHashes, and making
- # sure that we're not starting another command/key
- # that has split BRACES (nesting).
- #
- # It also checks that the line is not commented.
- #
- # We count the number of { and ADD to the counter
- # } and SUBTRACT to the counter
- return unless @masterIndentationArrayOfHashes;
- return unless ($masterIndentationArrayOfHashes[-1]{type} eq 'splitbraces');
- print $logfile "Line $lineCounter\t Searching for closing BRACE } $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode);
-
- if(!($_ =~ m/^\s*(\\)?(.*?)(\[|{|=|(\s*\\))/
- and ($checkunmatched{$2} or $checkunmatchedELSE{$2} or $alwaysLookforSplitBraces))
- and $_ !~ m/^\s*%/
- ) {
- # keep matching { OR }, and don't match \{ or \}
- while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) {
- # store the match, either { or }
- my $braceType = $1;
-
- # exit the loop if @masterIndentationArrayOfHashes[-1] is empty
- last if(!@masterIndentationArrayOfHashes);
-
- # exit the loop if we're not looking for split braces
- last if($masterIndentationArrayOfHashes[-1]{type} ne 'splitbraces');
-
- # get the details of the most recent command name
- my $commandname = $masterIndentationArrayOfHashes[-1]{name};
- my $matchedbraces = $masterIndentationArrayOfHashes[-1]{matchedbraces};
- my $countzeros = $masterIndentationArrayOfHashes[-1]{countzeros};
- my $lookforelse= $masterIndentationArrayOfHashes[-1]{lookforelse};
-
- $matchedbraces++ if($1 eq "{");
- $matchedbraces-- if($1 eq "}");
-
- # update the matched braces count
- $masterIndentationArrayOfHashes[-1]{matchedbraces} = $matchedbraces;
-
- # if we've matched up the braces then
- # we can decrease the indent by 1 level
- if($matchedbraces == 0) {
- $countzeros++ if $lookforelse;
-
- # tracing mode
- print $logfile "Line $lineCounter\t Found closing BRACE } $commandname\n" if($tracingMode);
-
- # decrease the indentation (if appropriate)
- &decrease_indent($commandname);
-
- if($countzeros==1){
- $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces;
- $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros;
- $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse;
- }
- }
-
- if(@masterIndentationArrayOfHashes){
- if($masterIndentationArrayOfHashes[-1]{'type'} eq 'splitbraces'){
- # tracing mode
- print $logfile "Line $lineCounter\t Searching for closing BRACE } $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode);
- }
- }
- }
- }
-}
-
-sub check_for_else{
- # PURPOSE: Check for an else clause
- #
- # Some commands have the form
- #
- # \mycommand{
- # if this
- # }
- # {
- # else this
- # }
- #
- # so we need to look for the else bit, and set
- # the indentation appropriately.
- #
- # We only perform this check if there's something
- # in the array @masterIndentationArrayOfHashes, and if
- # the line itself is not a command, or comment,
- # and if it begins with {
-
- if(scalar(@masterIndentationArrayOfHashes)
- and !($_ =~ m/^\s*(\\)?(.*?)(\[|{|=)/
- and ($checkunmatched{$2} or $checkunmatchedELSE{$2}
- or $alwaysLookforSplitBraces))
- and $_ =~ m/^\s*{/
- and $_ !~ m/^\s*%/
- ) {
- # get the details of the most recent command name
- my $matchedbraces = $masterIndentationArrayOfHashes[-1]{'matchedbraces'};
- my $countzeros = $masterIndentationArrayOfHashes[-1]{'countzeros'};
- my $lookforelse= $masterIndentationArrayOfHashes[-1]{'lookforelse'};
-
- # increase indentation
- if($lookforelse and $countzeros==1) {
- #&increase_indent($commandname);
- }
-
- # put the array back together
- $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces;
- $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros;
- $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse;
- }
-}
-
-sub at_beg_of_env_or_eq{
- # PURPOSE: Check if we're at the BEGINning of an environment
- # or at the BEGINning of a displayed equation \[
- #
- # This subroutine checks for matches of the form
- #
- # \begin{environmentname}
- # or
- # \[
- #
- # It also checks to see if the current environment
- # should have alignment delimiters; if so, we need to turn
- # ON the $delimiter switch
-
- # How to read
- # m/^\s*(\$)?\\begin{(.*?)}/
- #
- # ^ beginning of a line
- # \s* any white spaces (possibly none)
- # (\$)? possibly a $ symbol, but not required
- # \\begin{(.*)?} \begin{environmentname}
- #
- # How to read
- # m/^\s*()(\\\[)/
- #
- # ^ beginning of a line
- # \s* any white spaces (possibly none)
- # () empty just so that $1 and $2 are defined
- # (\\\[) \[ there are lots of \ because both \ and [ need escaping
- # \\begin{\\?(.*?)} \begin{something} where something could start
- # with a backslash, e.g \my@env@ which can happen
- # in a style or class file, for example
-
- if( ( ( $_ =~ m/^\s*(\$)?\\begin\{\\?(.*?)\}/ and $_ !~ m/\\end\{$2\}/)
- or ($_=~ m/^\s*()(\\\[)/ and $_ !~ m/\\\]/) )
- and $_ !~ m/^\s*%/ ) {
- # tracing mode
- print $logfile "Line $lineCounter\t \\begin{environment} found: $2 \n" if($tracingMode);
-
- # increase the indentation
- &increase_indent({name=>$2,
- type=>"environment",
- begin=>"\\begin{$2}",
- end=>"\\end{$2}"});
-
- # check for verbatim-like environments
- if($verbatimEnvironments{$2}){
- $inverbatim = 1;
- # tracing mode
- print $logfile "Line $lineCounter\t \\begin{verbatim-like} found, $2, switching ON verbatim \n" if($tracingMode);
-
- # remove the key and value from %lookForAlignDelims hash
- # to avoid any further confusion
- if($lookForAlignDelims{$2}) {
- print $logfile "WARNING\n\t Line $lineCounter\t $2 is in *both* lookForAlignDelims and verbatimEnvironments\n";
- print $logfile "\t\t\t ignoring lookForAlignDelims and prioritizing verbatimEnvironments\n";
- print $logfile "\t\t\t Note that you only get this message once per environment\n";
- delete $lookForAlignDelims{$2};
- }
- }
- }
-}
-
-sub at_end_of_env_or_eq{
- # PURPOSE: Check if we're at the END of an environment
- # or at the END of a displayed equation \]
- #
- # This subroutine checks for matches of the form
- #
- # \end{environmentname}
- # or
- # \]
- #
- # Note: environmentname can begin with a backslash
- # which might happen in a sty or cls file.
- #
- # It also checks to see if the current environment
- # had alignment delimiters; if so, we need to turn
- # OFF the $delimiter switch
-
- return unless @masterIndentationArrayOfHashes;
- print $logfile "Line $lineCounter\t looking for \\end{$masterIndentationArrayOfHashes[-1]{name}} \n" if($tracingMode);
-
- if( ($_ =~ m/^\s*\\end\{\\?(.*?)\}/ or $_=~ m/^(\\\])/) and $_ !~ m/\s*^%/) {
- # check if we're at the end of a verbatim-like environment
- if($verbatimEnvironments{$1}) {
- $inverbatim = 0;
- # tracing mode
-
- print $logfile "Line $lineCounter\t \\end{verbatim-like} found: $1, switching off verbatim \n" if($tracingMode);
- print $logfile "Line $lineCounter\t removing leading spaces \n" if($tracingMode);
- #s/^\ *//;
- s/^\t+// if($_ ne "");
- s/^\s+// if($_ ne "");
- }
-
- # check if we're in an environment that is looking
- # to indent after each \item
- if(scalar(@masterIndentationArrayOfHashes) and $itemNames{$masterIndentationArrayOfHashes[-1]{name}}) {
- &decrease_indent($masterIndentationArrayOfHashes[-1]{name});
- }
-
- # if we're at the end of an environment that receives no additional indent, log it, and move on
- if($noAdditionalIndent{$1}){
- print $logfile "Line $lineCounter\t \\end{$1} finished a no-additional-indent environment (see noAdditionalIndent)\n" if($tracingMode);
- }
-
- # some commands contain \end{environmentname}, which
- # can cause a problem if \begin{environmentname} was not
- # started previously; if @masterIndentationArrayOfHashes is empty,
- # then we don't need to check for \end{environmentname}
- if(@masterIndentationArrayOfHashes) {
- # check to see if \end{environment} fits with most recent \begin{...}
- my %previousEnvironment = %{$masterIndentationArrayOfHashes[-1]};
-
- # check to see if we need to turn off alignment
- # delimiters and output the current block
- if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters} and ($previousEnvironment{name} eq $1)) {
- &print_aligned_block();
- }
-
- # tracing mode
- print $logfile "Line $lineCounter\t \\end{environment} found: $1 \n" if($tracingMode and !$verbatimEnvironments{$1});
-
- # check to see if \end{environment} fits with most recent \begin{...}
- if($previousEnvironment{name} eq $1) {
- # decrease the indentation (if appropriate)
- print $logfile "Line $lineCounter\t removed $1 from Indentation array\n" if($tracingMode);
- &decrease_indent($1);
- } else {
- # otherwise put the environment name back on the stack
- print $logfile "Line $lineCounter\t WARNING: \\end{$1} found on its own line, not matched to \\begin{$previousEnvironment{name}}\n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]");
- }
-
- # need a special check for \[ and \]
- if($1 eq "\\\]") {
- &decrease_indent($1);
- }
- }
-
- # if we're at the end of the document, we remove all current
- # indentation- this is especially prominent in examples that
- # have headings, and the user has chosen to indentAfterHeadings
- if($1 eq "document" and !$inFileContents and !$inpreamble and !$delimiters and !$inverbatim and !$inIndentBlock and @masterIndentationArrayOfHashes) {
- @masterIndentationArrayOfHashes=();
-
- # tracing mode
- if($tracingMode) {
- print $logfile "Line $lineCounter\t \\end{$1} found, emptying indentation array \n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]");
- }
- }
- }
-}
-
-sub print_aligned_block{
- # PURPOSE: this subroutine does a few things related
- # to printing blocks of code that contain
- # delimiters, such as align, tabular, etc
- #
- # It does the following
- # - turns off delimiters switch
- # - processes the block
- # - deletes the block
- $delimiters=0;
-
- # tracing mode
- print $logfile "Line $lineCounter\t Delimiter body FINISHED: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode);
-
- # print the current FORMATTED block
- my @block = &format_block(@{$masterIndentationArrayOfHashes[-1]{block}});
- foreach $line (@block) {
- # add the indentation and add the
- # each line of the formatted block
- # to the output
- # unless this would only create trailing whitespace and the
- # corresponding option is set
- unless ($line =~ m/^$/ and $removeTrailingWhitespace) {
- $line =&current_indentation().$line;
- }
- push(@lines,$line);
- }
-}
-
-sub format_block{
- # PURPOSE: Format a delimited environment such as the
- # tabular or align environment that contains &
- #
- # INPUT: @block array containing unformatted block
- # from, for example, align, or tabular
- # OUTPUT: @formattedblock array containing FORMATTED block
-
- # @block is the input
- my @block=@_;
-
- # tracing mode
- print $logfile "\t\tFormatting alignment block: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode);
-
- # step the line counter back to the beginning of the block-
- # it will be increased back to the end of the block in the
- # loop later on: foreach $row (@tmpblock)
- $lineCounter -= scalar(@block);
-
- # local array variables
- my @formattedblock;
- my @tmprow=();
- my @tmpblock=();
- my @maxmstringsize=();
- my @ampersandCount=();
-
- # local scalar variables
- my $alignrowcounter=-1;
- my $aligncolcounter=-1;
- my $tmpstring;
- my $row;
- my $column;
- my $maxmcolstrlength;
- my $i;
- my $j;
- my $fmtstring;
- my $linebreak;
- my $maxNumberAmpersands = 0;
- my $currentNumberAmpersands;
- my $trailingcomments;
-
- # local hash table
- my %stringsize=();
-
- # loop through the block and count & per line- store the biggest
- # NOTE: this needs to be done in its own block so that
- # we can know what the maximum number of & in the block is
- foreach $row (@block) {
- # delete trailing comments
- $trailingcomments='';
- if($row =~ m/((?<!\\)%.*$)/) {
- $row =~ s/((?<!\\)%.*)/%TC/;
- $trailingcomments=$1;
- }
-
- # reset temporary counter
- $currentNumberAmpersands=0;
-
- # count & in current row (exclude \&)
- $currentNumberAmpersands++ while ($row =~ /(?<!\\)&/g);
-
- # store the ampersand count for future
- push(@ampersandCount,$currentNumberAmpersands);
-
- # overwrite maximum count if the temp count is higher
- $maxNumberAmpersands = $currentNumberAmpersands if($currentNumberAmpersands > $maxNumberAmpersands );
-
- # put trailing comments back on
- if($trailingcomments){
- $row =~ s/%TC/$trailingcomments/;
- }
- }
-
- # tracing mode
- print $logfile "\t\tmaximum number of & in any row: $maxNumberAmpersands\n" if($tracingMode);
-
- # loop through the lines in the @block
- foreach $row (@block){
- # get the ampersand count
- $currentNumberAmpersands = shift(@ampersandCount);
-
- # increment row counter
- $alignrowcounter++;
-
- # clear the $linebreak variable
- $linebreak='';
-
- # check for line break \\
- # and don't mess with a line that doesn't have the maximum
- # number of &
- if($row =~ m/\\\\/ and $currentNumberAmpersands==$maxNumberAmpersands ) {
- # remove \\ and all characters that follow
- # and put it back in later, once the measurement
- # has been done
- $row =~ s/(\\\\.*)//;
- $linebreak = $1;
- }
-
- if($currentNumberAmpersands==$maxNumberAmpersands) {
-
- # remove trailing comments
- $trailingcomments='';
- if($row =~ m/((?<!\\)%.*$)/) {
- $row =~ s/((?<!\\)%.*)/%TC/;
- $trailingcomments=$1;
- }
-
- # separate the row at each &, but not at \&
- @tmprow = split(/(?<!\\)&/,$row);
-
- # reset column counter
- $aligncolcounter=-1;
-
- # loop through each column element
- # removing leading and trailing space
- foreach $column (@tmprow) {
- # increment column counter
- $aligncolcounter++;
-
- # remove leading and trailing space from element
- $column =~ s/^\s+//;
- $column =~ s/\s+$//;
-
- # assign string size to the array
- $stringsize{$alignrowcounter.$aligncolcounter}=length($column);
- if(length($column)==0){
- $column=" ";
- }
-
- # put the row back together
- if ($aligncolcounter ==0){
- $tmpstring = $column;
- } else {
- $tmpstring .= "&".$column;
- }
- }
-
-
- # put $linebreak back on the string, now that
- # the measurement has been done
- $tmpstring .= $linebreak;
-
- # put trailing comments back on
- if($trailingcomments) {
- $tmpstring =~ s/%TC/$trailingcomments/;
- }
-
- push(@tmpblock,$tmpstring);
- } else {
- # if there are no & then use the
- # NOFORMATTING token
- # remove leading space
- s/^\s+//;
- push(@tmpblock,$row."NOFORMATTING");
- }
- }
-
- # calculate the maximum string size of each column
- for($j=0;$j<=$aligncolcounter;$j++) {
- $maxmcolstrlength=0;
- for($i=0; $i<=$alignrowcounter;$i++) {
- # make sure the stringsize is defined
- if(defined $stringsize{$i.$j}) {
- if ($stringsize{$i.$j}>$maxmcolstrlength) {
- $maxmcolstrlength = $stringsize{$i.$j};
- }
- }
- }
- push(@maxmstringsize,$maxmcolstrlength);
- }
-
- # README: printf( formatting, expression)
- #
- # formatting has the form %-50s & %-20s & %-19s
- # (the numbers have been made up for example)
- # the - symbols mean that each column should be left-aligned
- # the numbers represent how wide each column is
- # the s represents string
- # the & needs to be inserted
-
- # join up the maximum string lengths using "s %-"
- $fmtstring = join("s & %-",@maxmstringsize);
-
- # add an s to the end, and a newline
- $fmtstring .= "s ";
-
- # add %- to the beginning
- $fmtstring = "%-".$fmtstring;
-
- # process the @tmpblock of aligned material
- foreach $row (@tmpblock) {
- $linebreak='';
- # check for line break \\
- if($row =~ m/\\\\/) {
- # remove \\ and all characters that follow
- # and put it back in later
- $row =~ s/(\\\\.*$)//;
- $linebreak = $1;
- }
-
- if($row =~ m/NOFORMATTING/) {
- $row =~ s/NOFORMATTING//;
- $tmpstring=$row;
-
- # tracing mode
- print $logfile "\t\tLine $lineCounter\t maximum number of & NOT found- not aligning delimiters \n" if($tracingMode);
- } else {
- # remove trailing comments
- $trailingcomments='';
- if($row =~ m/((?<!\\)%.*$)/) {
- $row =~ s/((?<!\\)%.*)/%TC/;
- $trailingcomments=$1;
- }
-
- $tmpstring = sprintf($fmtstring,split(/(?<!\\)&/,$row)).$linebreak."\n";
-
- # remove space before \\ if specified in alignDoubleBackSlash
- if($masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}==0){
- print $logfile "\t\tLine $lineCounter\t removing space before \\\\ (see $masterIndentationArrayOfHashes[-1]{name} alignDoubleBackSlash)\n" if($tracingMode);
- $tmpstring =~ s/\s*\\\\/\\\\/;
- # some users may like to put a number of spaces before \\
- if($masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash}){
- my $spaceString;
- for($j=1;$j<=$masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash};$j++) {
- $spaceString .= ' ';
- }
- print $logfile "\t\tLine $lineCounter\t adding $masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash} ",$masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash}>1?"spaces":"space"," before \\\\ (see $masterIndentationArrayOfHashes[-1]{name} spacesBeforeDoubleBackSlash)\n" if($tracingMode);
- $tmpstring =~ s/\\\\/$spaceString\\\\/;
- }
- }
-
- # put trailing comments back on
- if($trailingcomments) {
- $tmpstring =~ s/%TC/$trailingcomments/;
- }
-
- # tracing mode
- print $logfile "\t\tLine $lineCounter\t Found maximum number of & so aligning delimiters\n" if($tracingMode);
- }
-
- # remove trailing whitespace
- if ($removeTrailingWhitespace) {
- print $logfile "\t\tLine $lineCounter\t removing trailing whitespace from delimiter aligned line\n" if ($tracingMode);
- $tmpstring =~ s/\s+$/\n/;
- }
-
- push(@formattedblock,$tmpstring);
-
- # increase the line counter
- $lineCounter++;
- }
-
- # return the formatted block
- @formattedblock;
-}
-
-sub increase_indent{
- # PURPOSE: Adjust the indentation
- # of the current environment, command, etc;
- # check that it's not an environment
- # that doesn't want indentation.
-
- my %infoHash = %{pop(@_)};
- my $command = $infoHash{name};
-
- # check for conflicting hash keys
- &check_conflicting_keys($command);
-
- # quick check for verbatim Environment
- if($inverbatim){
- print $logfile "Line $lineCounter\t currently inverbatim environment, not increasing indentation\n" if($tracingMode);
- return;
- }
-
- if($indentRules{$command}) {
- # tracing mode
- print $logfile "Line $lineCounter\t increasing indent using rule for $command (see indentRules)\n" if($tracingMode);
- } else {
- # default indentation
- if(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command})) {
- # tracing mode
- print $logfile "Line $lineCounter\t increasing indent using defaultIndent\n" if($tracingMode);
- } elsif($noAdditionalIndent{$command}) {
- # tracing mode
- print $logfile "Line $lineCounter\t no additional indent added for $command (see noAdditionalIndent)\n" if($tracingMode);
- }
- }
-
- # add to the master array of hashes
- push(@masterIndentationArrayOfHashes,\%infoHash);
-
- # handle the keys slightly different when dealing with environments or commands
- if($infoHash{type} eq 'environment'){
- # environments
- if(!$noAdditionalIndent{$command}){
- $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent;
- }
- # check to see if we need to look for alignment delimiters
- if($lookForAlignDelims{$command}){
- # there are two ways to complete the lookForAlignDelims field, either as a scalar
- # or as a hash, so that we can check for alignDoubleBackSlash.
- #
- # tabular:
- # delims: 1
- # alignDoubleBackSlash: 1
- #
- # or, simply,
- #
- # tabular: 1
- #
- # We need to perform a check to see which has been done.
- if(ref($lookForAlignDelims{$command}) eq 'HASH'){
- # tabular:
- # delims: 1
- # alignDoubleBackSlash: 1
- $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=defined $lookForAlignDelims{$command}{delims}?$lookForAlignDelims{$command}{delims}:1;
- $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=defined $lookForAlignDelims{$command}{alignDoubleBackSlash}?$lookForAlignDelims{$command}{alignDoubleBackSlash}:1;
- $masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash}=$lookForAlignDelims{$command}{spacesBeforeDoubleBackSlash}||0;
- } else {
- # tabular: 1
- $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=1;
- $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=1;
- }
- if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters}==1){
- # tracing mode
- print $logfile "Line $lineCounter\t Delimiter environment started: $command (see lookForAlignDelims)\n" if($tracingMode);
- }
- }
- } else {
- # commands, headings, etc
- if(!$noAdditionalIndent{$command}){
- $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent;
- }
- }
-
- # details of noAdditionalIndent to the main hash
- if($noAdditionalIndent{$command}){
- $masterIndentationArrayOfHashes[-1]{noAdditionalIndent} = 'yes';
- }
-}
-
-sub decrease_indent{
- # PURPOSE: Adjust the indentation
- # of the current environment;
- # check that it's not an environment
- # that doesn't want indentation.
-
- # if there is no evidence of indentation, then return
- return unless(scalar(@masterIndentationArrayOfHashes));
-
- # otherwise get details of the most recent command, environment, item, if, heading, etc
- my $command = pop(@_);
-
- if(!$inverbatim) {
- print $logfile "Line $lineCounter\t removing ", $masterIndentationArrayOfHashes[-1]{name}, " from masterIndentationArrayOfHashes\n" if($tracingMode);
- pop(@masterIndentationArrayOfHashes);
- # tracing mode
- if($tracingMode) {
- if(@masterIndentationArrayOfHashes) {
- print $logfile "Line $lineCounter\t decreasing masterIndentationArrayOfHashes to: ",&current_indentation_names(),"\n";
- } else {
- print $logfile "Line $lineCounter\t masterIndentationArrayOfHashes now empty \n";
- }
- }
- }
-}
-
-sub current_indentation{
- # PURPOSE: loop through masterIndentationArrayOfHashes and
- # pull out the indentation, and join it together
-
- # if the masterIndentationArrayOfHashes is empty, return an empty string
- return "" unless(@masterIndentationArrayOfHashes);
-
- my $indent;
- foreach my $env (@masterIndentationArrayOfHashes){
- $indent .= defined($env->{indent})?$env->{indent}:'';
- }
- return $indent;
-}
-
-sub current_indentation_names{
- # PURPOSE: loop through masterIndentationArrayOfHashes and
- # pull out the list of environment/command names
- return "masterIndentationArrayOfHashes empty" unless(@masterIndentationArrayOfHashes);
-
- my $listOfNames;
- foreach my $env (@masterIndentationArrayOfHashes){
- $listOfNames .= $env->{name};
- $listOfNames .= "," unless $env == $masterIndentationArrayOfHashes[-1];
- }
- return $listOfNames;
-}
-
-sub check_conflicting_keys{
- # PURPOSE: users may sometimes put an environment in two
- # hash keys; for example, they might put lstlistings
- # in both indentRules and in noAdditionalIndent;
- # in which case, we need a hierachy.
- #
- # This subroutine implements such a hierachy,
- # and deletes the redundant key.
-
- # if the user has specified $indentRules{$command} and
- # $noAdditionalIndent{$command} then they are a bit confused-
- # we remove the $indentRules{$command} and assume that they
- # want $noAdditionalIndent{$command}
-
- my $command = pop(@_);
-
- if(scalar($indentRules{$command}) and $noAdditionalIndent{$command}) {
- print $logfile "WARNING\n\t Line $lineCounter\t $command is in *both* indentRules and noAdditionalIndent\n";
- print $logfile "\t\t\t ignoring indentRules and prioritizing noAdditionalIndent\n";
- print $logfile "\t\t\t Note that you only get this message once per command/environment\n";
-
- # remove the key and value from %indentRules hash
- # to avoid any further confusion
- delete $indentRules{$command};
- }
-
- # if the command is in verbatimEnvironments and in indentRules then
- # remove it from %indentRules hash
- # to avoid any further confusion
- if($indentRules{$command} and $verbatimEnvironments{$command}) {
- # remove the key and value from %indentRules hash
- # to avoid any further confusion
- print $logfile "WARNING\n\t Line $lineCounter\t $command is in *both* indentRules and verbatimEnvironments\n";
- print $logfile "\t\t\t ignoring indentRules and prioritizing verbatimEnvironments\n";
- print $logfile "\t\t\t Note that you only get this message once per environment\n";
- delete $indentRules{$command};
- }
-
-}