From 3223dc8b31952693cb552ebf58bf7b25abd0264f Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 27 Oct 2016 21:22:59 +0000 Subject: latexindent (27oct16) git-svn-id: svn://tug.org/texlive/trunk@42366 c570f23f-e606-0410-a88d-b1316a301751 --- .../scripts/latexindent/defaultSettings.yaml | 47 +- .../texmf-dist/scripts/latexindent/latexindent.pl | 1521 ++++++++++---------- 2 files changed, 801 insertions(+), 767 deletions(-) (limited to 'Master/texmf-dist/scripts/latexindent') diff --git a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml index 799c081f4dc..ef620846f4f 100755 --- a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml +++ b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml @@ -1,5 +1,9 @@ # -# defaultSettings.yaml +# defaultSettings.yaml for latexindent.pl, +# a script that aims to +# beautify .tex, .sty, .cls files +# +# (or latexindent.exe if you're on Windows) # # You're welcome to change anything you like in here, but # it would probably be better to have your own user settings @@ -63,13 +67,21 @@ removeTrailingWhitespace: 0 # environments that have tab delimiters, add more # as needed lookForAlignDelims: - tabular: 1 - tabularx: 1 + tabular: + delims: 1 + alignDoubleBackSlash: 1 + spacesBeforeDoubleBackSlash: 2 + tabularx: + delims: 1 longtable: 1 + tabu: 1 array: 1 matrix: 1 bmatrix: 1 + Bmatrix: 1 pmatrix: 1 + vmatrix: 1 + Vmatrix: 1 align: 1 align*: 1 alignat: 1 @@ -202,6 +214,35 @@ constructIfElseFi: ifeof: 1 iftrue: 1 ifcase: 1 + +# latexindent can be called without a file extension, +# e.g, simply +# latexindent myfile +# in which case the choice of file extension is chosen +# according to the choices made in fileExtensionPreference +# Other file extensions can be added. +fileExtensionPreference: + .tex: 1 + .sty: 2 + .cls: 3 + .bib: 4 + +# preferences for information displayed in the log file +logFilePreferences: + showEveryYamlRead: 1 + showAlmagamatedSettings: 0 + endLogFileWith: '--------------' + traceModeIncreaseIndent: '>>' + traceModeAddCurrentIndent: '||' + traceModeDecreaseIndent: '<<' + traceModeBetweenLines: "\n" + +# \begin{document} and \end{document} are treated differently +# by latexindent within filecontents environments +fileContentsEnvironments: + filecontents: 1 + filecontents*: 1 + # *** NOTE *** # If you have specified alwaysLookforSplitBraces: 1 diff --git a/Master/texmf-dist/scripts/latexindent/latexindent.pl b/Master/texmf-dist/scripts/latexindent/latexindent.pl index f273ab7b890..cdd979a8ccf 100755 --- a/Master/texmf-dist/scripts/latexindent/latexindent.pl +++ b/Master/texmf-dist/scripts/latexindent/latexindent.pl @@ -21,8 +21,7 @@ use warnings; my @listOfModules = ('FindBin','YAML::Tiny','File::Copy','File::Basename','Getopt::Long','File::HomeDir'); # check the other modules are available -foreach my $moduleName (@listOfModules) -{ +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 @@ -35,52 +34,101 @@ foreach my $moduleName (@listOfModules) } # 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 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 # get the options my $overwrite; my $outputToFile; my $silentMode; my $tracingMode; -my $readLocalSettings; +my $tracingModeVeryDetailed; +my $readLocalSettings=0; my $onlyDefault; my $showhelp; my $cruftDirectory; -GetOptions ("w"=>\$overwrite, -"o"=>\$outputToFile, -"s"=>\$silentMode, -"t"=>\$tracingMode, -"l"=>\$readLocalSettings, -"d"=>\$onlyDefault, -"h"=>\$showhelp, -"c=s"=>\$cruftDirectory, +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, ); +# check local settings doesn't interfer with reading the file; +# this can happen if the script is called as follows: +# +# latexindent.pl -l myfile.tex +# +# in which case, the GetOptions routine mistakes myfile.tex +# as the optional parameter to the l flag. +# +# 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 = ''; +} + +# default value of readLocalSettings +# +# 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.1R"; +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) -{ +if(scalar(@ARGV) < 1 or $showhelp) { print < + used to specify the location of backup files and indent.log ENDQUOTE ; exit(2); @@ -115,8 +163,7 @@ 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 ) -{ +if($FindBin::Script eq 'latexindent.exe' and !$tracingMode ) { print $logfile <2) -{ +if(scalar(@ARGV)>2) { for my $fh ($out,$logfile) {print $fh <new; # Open defaultSettings.yaml $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" ); -print $logfile "Reading defaultSettings.yaml from $FindBin::RealBin/defaultSettings.yaml\n\n" if($defaultSettings); +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) -{ +if(!$defaultSettings) { $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml"); - print $logfile "Reading defaultSettings.yaml (2nd attempt, TeXLive, Windows) from $FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml\n\n" if($defaultSettings); + 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) -{ +if(!$defaultSettings) { for my $fh ($out,$logfile) { print $fh <[0]->{defaultIndent}; -my $alwaysLookforSplitBraces = $defaultSettings->[0]->{alwaysLookforSplitBraces}; -my $alwaysLookforSplitBrackets = $defaultSettings->[0]->{alwaysLookforSplitBrackets}; -my $backupExtension = $defaultSettings->[0]->{backupExtension}; -my $indentPreamble = $defaultSettings->[0]->{indentPreamble}; -my $onlyOneBackUp = $defaultSettings->[0]->{onlyOneBackUp}; -my $maxNumberOfBackUps = $defaultSettings->[0]->{maxNumberOfBackUps}; -my $removeTrailingWhitespace = $defaultSettings->[0]->{removeTrailingWhitespace}; -my $cycleThroughBackUps = $defaultSettings->[0]->{cycleThroughBackUps}; - -# hash variables -my %lookForAlignDelims= %{$defaultSettings->[0]->{lookForAlignDelims}}; -my %indentRules= %{$defaultSettings->[0]->{indentRules}}; -my %verbatimEnvironments= %{$defaultSettings->[0]->{verbatimEnvironments}}; -my %noIndentBlock= %{$defaultSettings->[0]->{noIndentBlock}}; -my %checkunmatched= %{$defaultSettings->[0]->{checkunmatched}}; -my %checkunmatchedELSE= %{$defaultSettings->[0]->{checkunmatchedELSE}}; -my %checkunmatchedbracket= %{$defaultSettings->[0]->{checkunmatchedbracket}}; -my %noAdditionalIndent= %{$defaultSettings->[0]->{noAdditionalIndent}}; -my %indentAfterHeadings= %{$defaultSettings->[0]->{indentAfterHeadings}}; -my %indentAfterItems= %{$defaultSettings->[0]->{indentAfterItems}}; -my %itemNames= %{$defaultSettings->[0]->{itemNames}}; -my %constructIfElseFi= %{$defaultSettings->[0]->{constructIfElseFi}}; - -# need new hashes to store the user and local data before -# overwriting the default -my %lookForAlignDelimsUSER; -my %indentRulesUSER; -my %verbatimEnvironmentsUSER; -my %noIndentBlockUSER; -my %checkunmatchedUSER; -my %checkunmatchedELSEUSER; -my %checkunmatchedbracketUSER; -my %noAdditionalIndentUSER; -my %indentAfterHeadingsUSER; -my %indentAfterItemsUSER; -my %itemNamesUSER; -my %constructIfElseFiUSER; - -# for printing the user and local settings to the log file -my %dataDump; +# 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; @@ -294,37 +293,27 @@ 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 "Reading path information from $indentconfig\n"; +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") - { + 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 "Alternatively, ",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"; - } - elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) - { - print $logfile "Alternatively, ",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) - { - %dataDump = %{$userSettings->[0]}; - print $logfile Dump \%dataDump; + if($userSettings) { + print $logfile "\t",Dump \%{$userSettings->[0]}; print $logfile "\n"; @absPaths = @{$userSettings->[0]->{paths}}; - } - else - { + } else { print $logfile <my_home,"\n"; - print $logfile "To specify user settings you would put indentconfig.yaml here: \n\t",File::HomeDir->my_home,"/indentconfig.yaml\n\n"; - print $logfile "Alternatively, you can use the hidden file .indentconfig.yaml as: \n\t",File::HomeDir->my_home,"/.indentconfig.yaml\n\n"; + 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 localSettings.yaml exists +# 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/localSettings.yaml") and $readLocalSettings and !(-z "$directoryName/localSettings.yaml")) -{ - print $logfile "\nAdding $directoryName/localSettings.yaml to paths\n\n"; - push(@absPaths,"$directoryName/localSettings.yaml"); -} -elsif ( !(-e "$directoryName/localSettings.yaml") and $readLocalSettings) -{ - print $logfile "WARNING\n\t$directoryName/localSettings.yaml not found\n"; - print $logfile "\tcarrying on without it.\n"; +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) -{ +foreach my $settings (@absPaths) { # check that the settings file exists and that it isn't empty - if (-e $settings and !(-z $settings)) - { - print $logfile "Reading USER settings from $settings\n"; + 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) - { + 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 - %dataDump = %{$userSettings->[0]}; - print $logfile Dump \%dataDump; - print $logfile "\n"; - - # scalar variables - $defaultIndent = $userSettings->[0]->{defaultIndent} if defined($userSettings->[0]->{defaultIndent}); - $alwaysLookforSplitBraces = $userSettings->[0]->{alwaysLookforSplitBraces} if defined($userSettings->[0]->{alwaysLookforSplitBraces}); - $alwaysLookforSplitBrackets = $userSettings->[0]->{alwaysLookforSplitBrackets} if defined($userSettings->[0]->{alwaysLookforSplitBrackets}); - $backupExtension = $userSettings->[0]->{backupExtension} if defined($userSettings->[0]->{backupExtension}); - $indentPreamble = $userSettings->[0]->{indentPreamble} if defined($userSettings->[0]->{indentPreamble}); - $onlyOneBackUp = $userSettings->[0]->{onlyOneBackUp} if defined($userSettings->[0]->{onlyOneBackUp}); - $maxNumberOfBackUps = $userSettings->[0]->{maxNumberOfBackUps} if defined($userSettings->[0]->{maxNumberOfBackUps}); - $removeTrailingWhitespace = $userSettings->[0]->{removeTrailingWhitespace} if defined($userSettings->[0]->{removeTrailingWhitespace}); - $cycleThroughBackUps = $userSettings->[0]->{cycleThroughBackUps} if defined($userSettings->[0]->{cycleThroughBackUps}); - - # hash variables - note that each one requires two lines, - # one to read in the data, one to put the keys&values in correctly - - %lookForAlignDelimsUSER= %{$userSettings->[0]->{lookForAlignDelims}} if defined($userSettings->[0]->{lookForAlignDelims}); - @lookForAlignDelims{ keys %lookForAlignDelimsUSER } = values %lookForAlignDelimsUSER if (%lookForAlignDelimsUSER); - - %indentRulesUSER= %{$userSettings->[0]->{indentRules}} if defined($userSettings->[0]->{indentRules}); - @indentRules{ keys %indentRulesUSER } = values %indentRulesUSER if (%indentRulesUSER); - - %verbatimEnvironmentsUSER= %{$userSettings->[0]->{verbatimEnvironments}} if defined($userSettings->[0]->{verbatimEnvironments}); - @verbatimEnvironments{ keys %verbatimEnvironmentsUSER } = values %verbatimEnvironmentsUSER if (%verbatimEnvironmentsUSER); - - %noIndentBlockUSER= %{$userSettings->[0]->{noIndentBlock}} if defined($userSettings->[0]->{noIndentBlock}); - @noIndentBlock{ keys %noIndentBlockUSER } = values %noIndentBlockUSER if (%noIndentBlockUSER); - - %checkunmatchedUSER= %{$userSettings->[0]->{checkunmatched}} if defined($userSettings->[0]->{checkunmatched}); - @checkunmatched{ keys %checkunmatchedUSER } = values %checkunmatchedUSER if (%checkunmatchedUSER); - - %checkunmatchedbracketUSER= %{$userSettings->[0]->{checkunmatchedbracket}} if defined($userSettings->[0]->{checkunmatchedbracket}); - @checkunmatchedbracket{ keys %checkunmatchedbracketUSER } = values %checkunmatchedbracketUSER if (%checkunmatchedbracketUSER); - - %noAdditionalIndentUSER= %{$userSettings->[0]->{noAdditionalIndent}} if defined($userSettings->[0]->{noAdditionalIndent}); - @noAdditionalIndent{ keys %noAdditionalIndentUSER } = values %noAdditionalIndentUSER if (%noAdditionalIndentUSER); - - %indentAfterHeadingsUSER= %{$userSettings->[0]->{indentAfterHeadings}} if defined($userSettings->[0]->{indentAfterHeadings}); - @indentAfterHeadings{ keys %indentAfterHeadingsUSER } = values %indentAfterHeadingsUSER if (%indentAfterHeadingsUSER); - - %indentAfterItemsUSER= %{$userSettings->[0]->{indentAfterItems}} if defined($userSettings->[0]->{indentAfterItems}); - @indentAfterItems{ keys %indentAfterItemsUSER } = values %indentAfterItemsUSER if (%indentAfterItemsUSER); - - %itemNamesUSER= %{$userSettings->[0]->{itemNames}} if defined($userSettings->[0]->{itemNames}); - @itemNames{ keys %itemNamesUSER } = values %itemNamesUSER if (%itemNamesUSER); - - %constructIfElseFiUSER= %{$userSettings->[0]->{constructIfElseFi}} if defined($userSettings->[0]->{constructIfElseFi}); - @constructIfElseFi{ keys %constructIfElseFiUSER } = values %constructIfElseFiUSER if (%constructIfElseFiUSER); - } - else - { + 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 - { + } 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) - { + if (-z $settings) { print $logfile "\tspecifies $settings \n\tbut this file is EMPTY- not reading from it\n\n" - } - else - { + } 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 ; +} -# if we want to over write the current file -# create a backup first -if ($overwrite) -{ +# 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 <1) - { + 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; @@ -477,40 +502,28 @@ if ($overwrite) # if the user has specified that $maxNumberOfBackUps = 1 then # they only want one backup - if($maxNumberOfBackUps==1) - { + 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) - { -# print $logfile "\t FYI: maxNumberOfBackUps=$maxNumberOfBackUps which won't have any effect\n"; -# print $logfile "\t on the script- at least ONE backup is made when the -w flag is invoked.\n"; -# print $logfile "\t I'm setting onlyOneBackUp: 0, which means that you'll get a new back up file \n"; -# print $logfile "\t every time you run the script.\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) - { + if($onlyOneBackUp) { $backupFile .= $backupExtension; - print $logfile "\t copying $filename to $backupFile\n"; - print $logfile "\t $backupFile was overwritten\n\n" if (-e $backupFile); - } - else - { + 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) - { + 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: @@ -519,11 +532,9 @@ if ($overwrite) # copy myfile.bak3 to myfile.bak2 # # current back up is stored in myfile.bak4 - if($cycleThroughBackUps) - { + if($cycleThroughBackUps) { print $logfile "\t cycleThroughBackUps detected (see cycleThroughBackUps) \n"; - for(my $i=1;$i<=$maxNumberOfBackUps;$i++) - { + for(my $i=1;$i<=$maxNumberOfBackUps;$i++) { # remove number from backUpFile my $oldBackupFile = $backupFile; $oldBackupFile =~ s/$backupExtension.*/$backupExtension/; @@ -544,9 +555,7 @@ if ($overwrite) # rest maxNumberOfBackUps $maxNumberOfBackUps=1 ; last; # break out of the loop - } - elsif(!(-e $backupFile)) - { + } elsif(!(-e $backupFile)) { $maxNumberOfBackUps=1 ; last; # break out of the loop } @@ -554,17 +563,16 @@ if ($overwrite) $backupCounter++; $backupFile =~ s/$backupExtension.*/$backupExtension$backupCounter/; } - print $logfile "\n\t copying $filename to $backupFile\n\n"; + print $logfile "\n\t copying $fileName to $backupFile\n\n"; } # output these lines to the log file - print $logfile "\t Backup file: ",$backupFile,"\n"; - print $logfile "\t Overwriting file: ",$filename,"\n\n"; - copy($filename,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n"; + 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)) -{ +if(!($outputToFile or $overwrite)) { print $logfile "Just out put to the terminal :)\n\n" if !$silentMode ; } @@ -578,123 +586,84 @@ 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 $matchedbraces=0; # $matchedbraces: counter to see if { } - # are matched; it will be - # positive if too many { - # negative if too many } - # 0 if matched -my $matchedBRACKETS=0; # $matchedBRACKETS: counter to see if [ ] - # are matched; it will be - # positive if too many { - # negative if too many } - # 0 if matched -my $commandname; # $commandname: either \parbox, \marginpar, - # or anything else from %checkunmatched -my $commanddetails; # $command details: a scalar that stores - # details about the command - # that splits {} across lines -my $countzeros; # $countzeros: a counter that helps - # when determining if we're in - # an else construct -my $lookforelse=0; # $lookforelse: a boolean to help determine - # if we need to look for an - # else construct 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 $headingLevel=0; # $headingLevel: scalar that stores which heading - # we are under: \part, \chapter, etc +my $inFileContents=0; # $inFileContents: switch to determine if we're in a filecontents environment # array variables -my @indent; # @indent: stores current level of indentation my @lines; # @lines: stores the newly indented lines -my @block; # @block: stores blocks that have & delimiters -my @commandstore; # @commandstore: stores commands that - # have split {} across lines -my @commandstorebrackets; # @commandstorebrackets: stores commands that - # have split [] across lines my @mainfile; # @mainfile: stores input file; used to # grep for \documentclass -my @headingStore; # @headingStore: stores headings: chapter, section, etc -my @indentNames; # @indentNames: keeps names of commands and - # environments that have caused - # indentation to increase -my @environmentStack; # @environmentStack: stores the (nested) names - # of environments + +# 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, $ARGV[0]) or die "Could not open input file"; +open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; @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) -{ +if(scalar(@{[grep(m/^\s*\\documentclass/, @mainfile)]})==0) { $inpreamble=0; print $logfile "Trace:\tNo documentclass detected, assuming no preamble\n" if($tracingMode); -} -else -{ +} 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, $ARGV[0]) or die "Could not open input file"; +open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; # loop through the lines in the INPUT file -while() -{ +while() { # 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 "\n" if($tracingMode and !($inpreamble or $inverbatim or $inIndentBlock)); + 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(!($inpreamble or $inverbatim or $inIndentBlock)) { # if not, remove all leading spaces and tabs # from the current line, assuming it isn't empty - #s/^\ *//; - #s/^\s+//; - #s/^\t+//; s/^\t*// if($_ !~ /^((\s*)|(\t*))*$/); s/^\s*// if($_ !~ /^((\s*)|(\t*))*$/); # tracing mode print $logfile "Line $lineCounter\t removing leading spaces\n" if($tracingMode); - } - else - { + } else { # otherwise check to see if we've reached the main # part of the document - if(m/^\s*\\begin{document}/) - { + if(m/^\s*\\begin\{document\}/ and !$inFileContents and !$inverbatim) { $inpreamble = 0; # tracing mode - print $logfile "Line $lineCounter\t \\begin{document} found \n" if($tracingMode); - } - else - { + 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, doing nothing\n" if($tracingMode); - } - elsif($inverbatim) - { - print $logfile "Line $lineCounter\t in VERBATIM-LIKE environment, doing nothing\n" if($tracingMode); - } - elsif($inIndentBlock) - { - print $logfile "Line $lineCounter\t in NO INDENT BLOCK, doing nothing\n" if($tracingMode); + 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); } } } @@ -703,7 +672,29 @@ while() # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - print $logfile "Line $lineCounter\t << PHASE 1: looking for reasons to DECREASE indentation of CURRENT line \n" if($tracingMode); + # 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); @@ -718,8 +709,7 @@ while() # 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)) - { + 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 @@ -729,8 +719,7 @@ while() # back on after the counting # # note the use of (?) &indent_if_else_fi(); # add the trailing comments back to the end of the line - if(scalar($trailingcomments)) - { + if(scalar($trailingcomments)) { # some line break magic, http://stackoverflow.com/questions/881779/neatest-way-to-remove-linebreaks-in-perl s/\R//; $_ = $_ . $trailingcomments."\n" ; @@ -772,8 +760,7 @@ while() } # remove trailing whitespace - if ($removeTrailingWhitespace) - { + if ($removeTrailingWhitespace) { print $logfile "Line $lineCounter\t removing trailing whitespace (see removeTrailingWhitespace)\n" if ($tracingMode); s/\s+$/\n/; } @@ -783,48 +770,47 @@ while() # ADD CURRENT LEVEL OF INDENTATION # ADD CURRENT LEVEL OF INDENTATION # (unless we're in a delimiter-aligned block) - if(!$delimiters) - { + if(!$delimiters) { # make sure we're not in a verbatim block or in the preamble - if($inverbatim or $inpreamble or $inIndentBlock) - { + if($inverbatim or $inpreamble or $inIndentBlock) { # just push the current line as is push(@lines,$_); - } - else - { + } 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){ - $_ = join("",@indent).$_; + $_ = ¤t_indentation().$_; } push(@lines,$_); # tracing mode - print $logfile "Line $lineCounter\t || PHASE 2: Adding current level of indentation: ",join(", ",@indentNames),"\n" if($tracingMode); + print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeAddCurrentIndent} PHASE 2: Adding current level of indentation: ",¤t_indentation_names(),"\n" if($tracingMode); } - } - else - { - # output to @block if we're in a delimiter block - push(@block,$_); + } 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, waiting for block formatting\n" if($tracingMode); + 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)) - { + if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)) { - print $logfile "Line $lineCounter\t >> PHASE 3: looking for reasons to INCREASE indentation of SUBSEQUENT lines \n" if($tracingMode); + 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} @@ -846,6 +832,9 @@ while() # %* \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 @@ -861,30 +850,39 @@ while() 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(); + &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(); + &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(); + &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(); + &indent_after_heading() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)); # check for \item - &indent_after_item(); + &indent_after_item() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)); # check for \if or \else command - &indent_after_if_else_fi(); + &indent_after_if_else_fi() if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)); # tracing mode - print $logfile "Line $lineCounter\t Environments: ",join(", ",@environmentStack),"\n" if($tracingMode and scalar(@environmentStack)); + if($tracingMode){ + if(scalar(@masterIndentationArrayOfHashes)){ + print $logfile "Line $lineCounter\t Indentation array: ",¤t_indentation_names(),"\n"; + } else { + print $logfile "Line $lineCounter\t Indentation array empty\n"; + } + } } } @@ -892,8 +890,8 @@ while() close(MAINFILE); # put line count information in the log file -print $logfile "Line Count of $ARGV[0]: ",scalar(@mainfile),"\n"; -print $logfile "Line Count of indented $ARGV[0]: ",scalar(@lines); +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 <",$ARGV[0]); +if($overwrite) { + open(OUTPUTFILE,">",$fileName); print OUTPUTFILE @lines; close(OUTPUTFILE); } # if -o is active then output to $ARGV[1] -if($outputToFile) -{ +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); -exit; +exit(0); sub indent_if_else_fi{ # PURPOSE: set indentation of line that contains \else, \fi command # # - # @indentNames could be empty -- if so, exit - return 0 unless(@indentNames); + # @masterIndentationArrayOfHashes could be empty -- if so, exit + return unless @masterIndentationArrayOfHashes; + return unless $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}; # look for \fi - if( $_ =~ m/^\s*\\fi/ and $constructIfElseFi{$indentNames[-1]}) - { + if( $_ =~ m/^\s*\\fi/) { # tracing mode - print $logfile "Line $lineCounter\t \\fi command found, matching: \\",$indentNames[-1], "\n" if($tracingMode); - &decrease_indent($indentNames[-1]); - } - elsif( ($_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/) and $constructIfElseFi{$indentNames[-1]}) - { + 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: \\",$indentNames[-1], "\n" if($tracingMode); - print $logfile "Line $lineCounter\t decreasing indent, but indentNames is still \\",join(", ",@indentNames), "\n" if($tracingMode); - pop(@indent); + 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 \\",¤t_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}=""; } } @@ -971,36 +971,34 @@ sub indent_after_if_else_fi{ # ^\s* begins with multiple spaces (possibly none) # \\(if.*?)(\s|\\|\#) matches \if... up to either a # space, a \, or a # - if( $_ =~ m/^\s*\\(if.*?)(\s|\\|\#)/ and $constructIfElseFi{$1}) - { + # 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($1); - } - elsif(@indentNames) - { - if( ($_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) and $constructIfElseFi{$indentNames[-1]}) - { + &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 $indentNames[-1] \n" if($tracingMode); - &increase_indent($indentNames[-1]); - # don't want to store the name of the \if construct twice - # so remove the second copy - pop(@indentNames); + 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: this subroutine sets the indentation for the item *itself* + # 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} and $indentAfterItems{$environmentStack[-1]}) - { + if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ and $itemNames{$1}){ # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$environmentStack[-1]," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - if($itemNames{$indentNames[-1]}) - { - print $logfile "Line $lineCounter\t $1 found- neutralizing indentation from previous ",$indentNames[-1],"\n" if($tracingMode); + 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); } } @@ -1018,15 +1016,17 @@ sub indent_after_item{ # # or anything else specified in itemNames # + return unless @masterIndentationArrayOfHashes; + return unless $indentAfterItems{$masterIndentationArrayOfHashes[-1]{name}}; + if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ - and $itemNames{$1} - and $indentAfterItems{$environmentStack[-1]}) - { + and $itemNames{$1}) { # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$environmentStack[-1]," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - &increase_indent($1); + 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} @@ -1044,9 +1044,13 @@ sub begin_command_with_alignment{ # %* \end{tabular} # } - if( $_ =~ m/^\s*%\*\s*\\begin{(.*?)}/ and $lookForAlignDelims{$1}) - { - $delimiters=1; + 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); } @@ -1069,17 +1073,16 @@ sub end_command_with_alignment{ # 3 & 4 \\ # %* \end{tabular} # } + return unless @masterIndentationArrayOfHashes; + return unless $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}; - if( $_ =~ m/^\s*%\*\s*\\end{(.*?)}/ and $lookForAlignDelims{$1}) - { + if( $_ =~ m/^\s*%\*\s*\\end\{(.*?)\}/ and $lookForAlignDelims{$1}) { # same subroutine used at the end of regular tabular, align, etc # environments - if($delimiters) - { + if($delimiters) { &print_aligned_block(); - } - else - { + &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); @@ -1101,29 +1104,36 @@ sub indent_heading{ # # This subroutine specifies the indentation for the # heading itself, i.e the line that has \chapter, \section etc - if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}) - { + 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 + # get the heading settings, it's a hash within a hash my %currentHeading = %{$indentAfterHeadings{$1}}; - # local scalar - my $previousHeadingLevel = $headingLevel; + # $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) - { + 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)) - { + if(scalar(@headingStore)) { + while($currentHeading{level}<$previousHeadingLevel and scalar(@headingStore)) { my $higherHeadingName = pop(@headingStore); my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; @@ -1136,23 +1146,13 @@ sub indent_heading{ # put the heading name back in to storage push(@headingStore,$1); } - } - elsif($currentHeading{level}==$previousHeadingLevel) - { - if(scalar(@headingStore)) - { + } elsif($currentHeading{level}==$previousHeadingLevel) { + if(scalar(@headingStore)) { my $higherHeadingName = pop(@headingStore); my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; &decrease_indent($higherHeadingName) if($higherLevelHeading{indent}); } - # put the heading name back in to storage - push(@headingStore,$1); - } - else - { - # put the heading name into storage - push(@headingStore,$1); - } + } } } @@ -1171,20 +1171,14 @@ sub indent_after_heading{ # 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}) - { + if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}) { # get the heading settings- it's a hash within a hash my %currentHeading = %{$indentAfterHeadings{$1}}; - &increase_indent($1) if($currentHeading{indent}); - - # update heading level - $headingLevel = $currentHeading{level}; + &increase_indent({name=>$1,type=>"heading",headinglevel=>$currentHeading{level}}) if($currentHeading{indent}); } } - - sub at_end_noindent{ # PURPOSE: This matches # % \end{noindent} @@ -1196,16 +1190,13 @@ sub at_end_noindent{ # This is for blocks of code that the user wants # to leave untouched- similar to verbatim blocks - if( $_ =~ m/^%\s*\\end{(.*?)}/ and $noIndentBlock{$1}) - { + 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} @@ -1217,8 +1208,7 @@ sub at_beg_noindent{ # This is for blocks of code that the user wants # to leave untouched- similar to verbatim blocks - if( $_ =~ m/^%\s*\\begin{(.*?)}/ and $noIndentBlock{$1}) - { + 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); @@ -1243,14 +1233,11 @@ sub start_command_or_key_unmatched_brackets{ # but it WON'T match \[ if ($_ =~ m/^\s*(\\)?(.*?)(\s*(?$commandname, - matchedBRACKETS=>$matchedBRACKETS}); - + &increase_indent({name=>$commandname,matchedBRACKETS=>$matchedBRACKETS,type=>'splitBrackets'}); } } } @@ -1281,7 +1261,7 @@ sub end_command_or_key_unmatched_brackets{ # \pgfplotstablecreatecol[ ... # # It works by checking if we have any entries - # in the array @commandstorebrackets, and making + # in the array @masterIndentationArrayOfHashes, and making # sure that we're not starting another command/key # that has split BRACKETS (nesting). # @@ -1289,17 +1269,17 @@ sub end_command_or_key_unmatched_brackets{ # # We count the number of [ and ADD to the counter # ] and SUBTRACT to the counter - if(scalar(@commandstorebrackets) - and !($_ =~ m/^\s*(\\)?(.*?)(\s*\[)/ - and (scalar($checkunmatchedbracket{$2}) - or $alwaysLookforSplitBrackets)) - and $_ !~ m/^\s*%/ - ) - { + 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 - $commanddetails = pop(@commandstorebrackets); - $commandname = $commanddetails->{'commandname'}; - $matchedBRACKETS = $commanddetails->{'matchedBRACKETS'}; + my $commandname = $masterIndentationArrayOfHashes[-1]{name}; + my $matchedBRACKETS = $masterIndentationArrayOfHashes[-1]{matchedBRACKETS}; # match [ but don't match \[ $matchedBRACKETS++ while ($_ =~ m/(?$commandname, - matchedBRACKETS=>$matchedBRACKETS}); + $masterIndentationArrayOfHashes[-1]{matchedBRACKETS} = $matchedBRACKETS; + # tracing mode print $logfile "Line $lineCounter\t Searching for closing BRACKET ] $commandname\n" if($tracingMode); } @@ -1351,22 +1328,16 @@ sub start_command_or_key_unmatched_braces{ # (\[|}|=|(\s*\\)) either [ or { or = or space \ if ($_ =~ m/^\s*(\\)?(.*?)(\[|{|=|(\s*\\))/ - and (scalar($checkunmatched{$2}) - or scalar($checkunmatchedELSE{$2}) + and ($checkunmatched{$2} or $checkunmatchedELSE{$2} or $alwaysLookforSplitBraces) - ) - { + ) { # store the command name, because $2 # will not exist after the next match - $commandname = $2; - $matchedbraces=0; + my $commandname = $2; + my $matchedbraces=0; # by default, don't look for an else construct - $lookforelse=0; - if(scalar($checkunmatchedELSE{$2})) - { - $lookforelse=1; - } + my $lookforelse=$checkunmatchedELSE{$2}||0; # match { but don't match \{ $matchedbraces++ while ($_ =~ /(? 0 ) - { + if($matchedbraces > 0 ) { # tracing mode print $logfile "Line $lineCounter\t Found opening BRACE { $commandname\n" if($tracingMode); - &increase_indent($commandname); - - # store the command name - # and the value of $matchedbraces - push(@commandstore,{commandname=>$commandname, + &increase_indent({name=>$commandname, matchedbraces=>$matchedbraces, lookforelse=>$lookforelse, - countzeros=>0}); - - } - elsif($matchedbraces<0) - { + 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/(((?{'commandname'}; - $matchedbraces = $commanddetails->{'matchedbraces'}; - $countzeros = $commanddetails->{'countzeros'}; - $lookforelse= $commanddetails->{'lookforelse'}; + $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) - { + if($matchedbraces == 0) { $countzeros++ if $lookforelse; # tracing mode @@ -1430,23 +1397,12 @@ sub start_command_or_key_unmatched_braces{ # decrease the indentation (if appropriate) &decrease_indent($commandname); - if($countzeros==1) - { - push(@commandstore,{commandname=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>$countzeros}); + if($countzeros==1) { + $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces; + $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros; + $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse; } - } - else - { - # otherwise we need to put the command back for the - # next brace count - push(@commandstore,{commandname=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>$countzeros}); - } + } } } } @@ -1463,7 +1419,7 @@ sub end_command_or_key_unmatched_braces{ # empty header/.style={ # # It works by checking if we have any entries - # in the array @commandstore, and making + # in the array @masterIndentationArrayOfHashes, and making # sure that we're not starting another command/key # that has split BRACES (nesting). # @@ -1471,37 +1427,40 @@ sub end_command_or_key_unmatched_braces{ # # We count the number of { and ADD to the counter # } and SUBTRACT to the counter - if(scalar(@commandstore) - and !($_ =~ m/^\s*(\\)?(.*?)(\[|{|=|(\s*\\))/ - and (scalar($checkunmatched{$2}) - or scalar($checkunmatchedELSE{$2}) - or $alwaysLookforSplitBraces)) + 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/(((?{'commandname'}; - $matchedbraces = $commanddetails->{'matchedbraces'}; - $countzeros = $commanddetails->{'countzeros'}; - $lookforelse= $commanddetails->{'lookforelse'}; + 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) - { + if($matchedbraces == 0) { $countzeros++ if $lookforelse; # tracing mode @@ -1510,28 +1469,20 @@ sub end_command_or_key_unmatched_braces{ # decrease the indentation (if appropriate) &decrease_indent($commandname); - if($countzeros==1) - { - push(@commandstore,{commandname=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>$countzeros}); + if($countzeros==1){ + $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces; + $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros; + $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse; } - } - else - { - # otherwise we need to enter the new value - # of $matchedbraces and the value of $command - # back into storage - push(@commandstore,{commandname=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>$countzeros}); - - # tracing mode - print $logfile "Line $lineCounter\t Searching for closing BRACE } $commandname\n" if($tracingMode); - } - } + } + + 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); + } + } + } } } @@ -1551,37 +1502,31 @@ sub check_for_else{ # the indentation appropriately. # # We only perform this check if there's something - # in the array @commandstore, and if + # in the array @masterIndentationArrayOfHashes, and if # the line itself is not a command, or comment, # and if it begins with { - if(scalar(@commandstore) + if(scalar(@masterIndentationArrayOfHashes) and !($_ =~ m/^\s*(\\)?(.*?)(\[|{|=)/ - and (scalar($checkunmatched{$2}) - or scalar($checkunmatchedELSE{$2}) + and ($checkunmatched{$2} or $checkunmatchedELSE{$2} or $alwaysLookforSplitBraces)) and $_ =~ m/^\s*{/ and $_ !~ m/^\s*%/ - ) - { + ) { # get the details of the most recent command name - $commanddetails = pop(@commandstore); - $commandname = $commanddetails->{'commandname'}; - $matchedbraces = $commanddetails->{'matchedbraces'}; - $countzeros = $commanddetails->{'countzeros'}; - $lookforelse= $commanddetails->{'lookforelse'}; + 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); + if($lookforelse and $countzeros==1) { + #&increase_indent($commandname); } # put the array back together - push(@commandstore,{commandname=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>$countzeros}); + $masterIndentationArrayOfHashes[-1]{'matchedbraces'} = $matchedbraces; + $masterIndentationArrayOfHashes[-1]{'countzeros'} = $countzeros; + $masterIndentationArrayOfHashes[-1]{'lookforelse'} = $lookforelse; } } @@ -1618,47 +1563,33 @@ sub at_beg_of_env_or_eq{ # 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}/) + if( ( ( $_ =~ m/^\s*(\$)?\\begin\{\\?(.*?)\}/ and $_ !~ m/\\end\{$2\}/) or ($_=~ m/^\s*()(\\\[)/ and $_ !~ m/\\\]/) ) - and $_ !~ m/^\s*%/ ) - { + and $_ !~ m/^\s*%/ ) { # tracing mode print $logfile "Line $lineCounter\t \\begin{environment} found: $2 \n" if($tracingMode); # increase the indentation - &increase_indent($2); + &increase_indent({name=>$2, + type=>"environment", + begin=>"\\begin{$2}", + end=>"\\end{$2}"}); # check for verbatim-like environments - if($verbatimEnvironments{$2}) - { + 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}) - { + 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}; } - - } - - # check to see if we need to look for alignment - # delimiters - if($lookForAlignDelims{$2}) - { - $delimiters=1; - # tracing mode - print $logfile "Line $lineCounter\t Delimiter environment started: $2 (see lookForAlignDelims)\n" if($tracingMode); } - - # store the name of the environment - push(@environmentStack,$2); - } } @@ -1679,12 +1610,12 @@ sub at_end_of_env_or_eq{ # had alignment delimiters; if so, we need to turn # OFF the $delimiter switch - if( ($_ =~ m/^\s*\\end{\\?(.*?)}/ or $_=~ m/^(\\\])/) and $_ !~ m/\s*^%/) - { + 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}) - { + if($verbatimEnvironments{$1}) { $inverbatim = 0; # tracing mode @@ -1697,63 +1628,57 @@ sub at_end_of_env_or_eq{ # check if we're in an environment that is looking # to indent after each \item - if(scalar(@indentNames) and $itemNames{$indentNames[-1]}) - { - &decrease_indent($indentNames[-1]); + 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 @environmentStack is empty, + # started previously; if @masterIndentationArrayOfHashes is empty, # then we don't need to check for \end{environmentname} - if(@environmentStack) - { + if(@masterIndentationArrayOfHashes) { # check to see if \end{environment} fits with most recent \begin{...} - my $previousEnvironment = pop(@environmentStack); + my %previousEnvironment = %{$masterIndentationArrayOfHashes[-1]}; # check to see if we need to turn off alignment # delimiters and output the current block - if($lookForAlignDelims{$1} and ($previousEnvironment eq $1)) - { + if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters} and ($previousEnvironment{name} eq $1)) { &print_aligned_block(); } # tracing mode - print $logfile "Line $lineCounter\t \\end{envrionment} found: $1 \n" if($tracingMode and !$verbatimEnvironments{$1}); + 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 eq $1) - { + 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 - { + } else { # otherwise put the environment name back on the stack - push(@environmentStack,$previousEnvironment); - print $logfile "Line $lineCounter\t WARNING: \\end{$1} found on its own line, not matched to \\begin{$previousEnvironment}\n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); + 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 "\\\]") - { + if($1 eq "\\\]") { &decrease_indent($1); - pop(@environmentStack); } } # 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 !(grep(/filecontents/, @indentNames)) and !$inpreamble and !$delimiters and !$inverbatim and !$inIndentBlock) - { - @indent=(); - @indentNames=(); + 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 indent array \n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); + if($tracingMode) { + print $logfile "Line $lineCounter\t \\end{$1} found, emptying indentation array \n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); } } } @@ -1771,25 +1696,21 @@ sub print_aligned_block{ $delimiters=0; # tracing mode - print $logfile "Line $lineCounter\t Delimiter body FINISHED: $1\n" if($tracingMode); + print $logfile "Line $lineCounter\t Delimiter body FINISHED: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); # print the current FORMATTED block - @block = &format_block(@block); - foreach $line (@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 = join("",@indent).$line; + unless ($line =~ m/^$/ and $removeTrailingWhitespace) { + $line =¤t_indentation().$line; } push(@lines,$line); } - # empty the @block, very important! - @block=(); } sub format_block{ @@ -1800,19 +1721,17 @@ sub format_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\n" if($tracingMode); + 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=(); @@ -1841,12 +1760,10 @@ sub format_block{ # 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) - { + foreach $row (@block) { # delete trailing comments $trailingcomments=''; - if($row =~ m/((? $maxNumberAmpersands ); # put trailing comments back on - if($trailingcomments) - { + if($trailingcomments){ $row =~ s/%TC/$trailingcomments/; } } @@ -1874,8 +1790,7 @@ sub format_block{ print $logfile "\t\tmaximum number of & in any row: $maxNumberAmpersands\n" if($tracingMode); # loop through the lines in the @block - foreach $row (@block) - { + foreach $row (@block){ # get the ampersand count $currentNumberAmpersands = shift(@ampersandCount); @@ -1888,8 +1803,7 @@ sub format_block{ # 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 ) - { + if($row =~ m/\\\\/ and $currentNumberAmpersands==$maxNumberAmpersands ) { # remove \\ and all characters that follow # and put it back in later, once the measurement # has been done @@ -1897,13 +1811,11 @@ sub format_block{ $linebreak = $1; } - if($currentNumberAmpersands==$maxNumberAmpersands) - { + if($currentNumberAmpersands==$maxNumberAmpersands) { # remove trailing comments $trailingcomments=''; - if($row =~ m/((?$maxmcolstrlength) - { + if(defined $stringsize{$i.$j}) { + if ($stringsize{$i.$j}>$maxmcolstrlength) { $maxmcolstrlength = $stringsize{$i.$j}; } } @@ -2003,42 +1903,49 @@ sub format_block{ $fmtstring = "%-".$fmtstring; # process the @tmpblock of aligned material - foreach $row (@tmpblock) - { - + foreach $row (@tmpblock) { $linebreak=''; # check for line break \\ - if($row =~ m/\\\\/) - { + if($row =~ m/\\\\/) { # remove \\ and all characters that follow # and put it back in later $row =~ s/(\\\\.*$)//; $linebreak = $1; } - if($row =~ m/NOFORMATTING/) - { + 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 - { + } else { # remove trailing comments $trailingcomments=''; - if($row =~ m/((?1?"spaces":"space"," before \\\\ (see $masterIndentationArrayOfHashes[-1]{name} spacesBeforeDoubleBackSlash)\n" if($tracingMode); + $tmpstring =~ s/\\\\/$spaceString\\\\/; + } + } + # put trailing comments back on - if($trailingcomments) - { + if($trailingcomments) { $tmpstring =~ s/%TC/$trailingcomments/; } @@ -2047,8 +1954,7 @@ sub format_block{ } # remove trailing whitespace - if ($removeTrailingWhitespace) - { + if ($removeTrailingWhitespace) { print $logfile "\t\tLine $lineCounter\t removing trailing whitespace from delimiter aligned line\n" if ($tracingMode); $tmpstring =~ s/\s+$/\n/; } @@ -2065,64 +1971,87 @@ sub format_block{ sub increase_indent{ # PURPOSE: Adjust the indentation - # of the current environment; + # of the current environment, command, etc; # check that it's not an environment # that doesn't want indentation. - my $command = pop(@_); + my %infoHash = %{pop(@_)}; + my $command = $infoHash{name}; - # 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} - 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}; - } + # check for conflicting hash keys + &check_conflicting_keys($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}; + # quick check for verbatim Environment + if($inverbatim){ + print $logfile "Line $lineCounter\t currently inverbatim environment, not increasing indentation\n" if($tracingMode); + return; } - if(scalar($indentRules{$command})) - { - # if there's a rule for indentation for this environment - push(@indent, $indentRules{$command}); + if($indentRules{$command}) { # tracing mode print $logfile "Line $lineCounter\t increasing indent using rule for $command (see indentRules)\n" if($tracingMode); - push(@indentNames,"$command"); - } - else - { + } else { # default indentation - if(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command} or $inverbatim)) - { - push(@indent, $defaultIndent); - push(@indentNames,"$command"); + if(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command})) { # tracing mode print $logfile "Line $lineCounter\t increasing indent using defaultIndent\n" if($tracingMode); - } - elsif($noAdditionalIndent{$command}) - { + } 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{ @@ -2131,25 +2060,89 @@ sub decrease_indent{ # 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(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command} or $inverbatim)) - { - print $logfile "Line $lineCounter\t removing ", $indentNames[-1], " from indentNames\n" if($tracingMode); - pop(@indent); - pop(@indentNames); + if(!$inverbatim) { + print $logfile "Line $lineCounter\t removing ", $masterIndentationArrayOfHashes[-1]{name}, " from masterIndentationArrayOfHashes\n" if($tracingMode); + pop(@masterIndentationArrayOfHashes); # tracing mode - if($tracingMode) - { - if(@indentNames) - { - print $logfile "Line $lineCounter\t decreasing indent to: ",join(", ",@indentNames),"\n" ; - } - else - { - print $logfile "Line $lineCounter\t indent now empty \n"; + if($tracingMode) { + if(@masterIndentationArrayOfHashes) { + print $logfile "Line $lineCounter\t decreasing masterIndentationArrayOfHashes to: ",¤t_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}; + } + +} -- cgit v1.2.3