diff options
author | Karl Berry <karl@freefriends.org> | 2016-10-27 21:22:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-10-27 21:22:59 +0000 |
commit | 3223dc8b31952693cb552ebf58bf7b25abd0264f (patch) | |
tree | 202ed7b9669317654becd627040ed86776eef627 | |
parent | 5a052b76b791d6fca889eead61e7fef3d5de4f2a (diff) |
latexindent (27oct16)
git-svn-id: svn://tug.org/texlive/trunk@42366 c570f23f-e606-0410-a88d-b1316a301751
32 files changed, 3041 insertions, 2477 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl b/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl index f273ab7b890..cdd979a8ccf 100755 --- a/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl +++ b/Build/source/texk/texlive/linked_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 <<ENDQUOTE latexindent.pl version $versionNumber usage: latexindent.pl [options] [file][.tex] - -h help (see the documentation for detailed instructions and examples) - -o output to another file; sample usage + -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 the current file- a backup will be made, but still be careful - -s silent mode- no output will be given to the terminal - -t tracing mode- verbose information given to the log file - -l use localSettings.yaml (assuming it exists in the directory of your file) - -d ONLY use defaultSettings.yaml, ignore ALL user files - -c=cruft directory used to specify the location of backup files and indent.log + -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); @@ -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 <<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, @@ -127,23 +174,17 @@ ENDQUOTE } # output location of modules -if($FindBin::Script eq 'latexindent.pl' or ($FindBin::Script eq 'latexindent.exe' and $tracingMode )) -{ +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) - { + foreach my $moduleName (@listOfModules) { (my $file = $moduleName) =~ s|::|/|g; require $file . '.pm'; print $logfile "\t",$INC{$file .'.pm'},"\n"; } } -# cruft directory -print $logfile "Directory for backup files and indent.log: $cruftDirectory\n"; - # a quick options check -if($outputToFile and $overwrite) -{ +if($outputToFile and $overwrite) { print $logfile <<ENDQUOTE WARNING: @@ -156,8 +197,7 @@ ENDQUOTE } # can't call the script with MORE THAN 2 files -if(scalar(@ARGV)>2) -{ +if(scalar(@ARGV)>2) { for my $fh ($out,$logfile) {print $fh <<ENDQUOTE ERROR: @@ -194,8 +234,7 @@ ENDQUOTE # 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) -{ +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 @@ -208,24 +247,25 @@ ENDQUOTE exit(2); } +# 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 "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 <<ENDQUOTE ERROR There seems to be a yaml formatting error in defaultSettings.yaml @@ -238,50 +278,9 @@ ENDQUOTE exit(2); } -# setup the DEFAULT variables and hashes from the YAML file - -# scalar variables -my $defaultIndent = $defaultSettings->[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 <<ENDQUOTE WARNING: $indentconfig contains some invalid .yaml formatting- unable to read from it. @@ -332,144 +321,180 @@ WARNING: $indentconfig ENDQUOTE ; } -} -else -{ - if($onlyDefault) - { - print $logfile "Only default settings requested, not reading USER settings from $indentconfig\n"; - print $logfile "Ignoring localSettings.yaml\n" if($readLocalSettings); +} 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 - { + } else { # give the user instructions on where to put indentconfig.yaml or .indentconfig.yaml - print $logfile "Home directory is ",File::HomeDir->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 <<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"; - # original name of file - my $filename = $ARGV[0]; + # cruft directory + print $logfile "\tDirectory for backup files and indent.log: $cruftDirectory\n\n"; - # get the base file name, allowing for different extensions - my $backupFile = basename($filename,(".tex",".sty",".cls")); + 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) - { + 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=<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(<MAINFILE>) -{ +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 "\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(<MAINFILE>) # \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(<MAINFILE>) # 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(<MAINFILE>) # back on after the counting # # note the use of (?<!\\)% so that we don't match \% - if ( $_=~ m/(?<!\\)%.*/) - { + if ( $_=~ m/(?<!\\)%.*/) { s/((?<!\\)%.*)//; $trailingcomments=$1; @@ -757,8 +746,7 @@ while(<MAINFILE>) &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(<MAINFILE>) } # 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(<MAINFILE>) # 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(<MAINFILE>) # %* \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(<MAINFILE>) 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(<MAINFILE>) 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 <<ENDQUOTE @@ -901,57 +899,59 @@ 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"; +} 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,">",$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*(?<!\\)\[)/ - and (scalar($checkunmatchedbracket{$2}) - or $alwaysLookforSplitBrackets) - ) - { + and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets)) { # store the command name, because $2 # will not exist after the next match - $commandname = $2; - $matchedBRACKETS=0; + my $commandname = $2; + my $matchedBRACKETS=0; # match [ but don't match \[ $matchedBRACKETS++ while ($_ =~ /(?<!\\)\[/g); @@ -1258,18 +1245,11 @@ sub start_command_or_key_unmatched_brackets{ $matchedBRACKETS-- while ($_ =~ /(?<!\\)\]/g); # set the indentation - if($matchedBRACKETS != 0 ) - { + if($matchedBRACKETS != 0 ) { # tracing mode print $logfile "Line $lineCounter\t Found opening BRACKET [ $commandname\n" if($tracingMode); - &increase_indent($commandname); - - # store the command name - # and the value of $matchedBRACKETS - push(@commandstorebrackets,{commandname=>$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/(?<!\\)\[/g); @@ -1309,21 +1289,18 @@ sub end_command_or_key_unmatched_brackets{ # if we've matched up the BRACKETS then # we can decrease the indent by 1 level - if($matchedBRACKETS == 0) - { + 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 - { + } else { # otherwise we need to enter the new value # of $matchedBRACKETS and the value of $command # back into storage - push(@commandstorebrackets,{commandname=>$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 ($_ =~ /(?<!\\){/g); @@ -1378,50 +1349,46 @@ sub start_command_or_key_unmatched_braces{ print $logfile "Line $lineCounter\t matchedbraces = $matchedbraces\n" if($tracingMode); # set the indentation - if($matchedbraces > 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/(((?<!\\){)|((?<!\\)}))/g) - { + while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) { # store the match, either { or } my $braceType = $1; - # exit the loop if @commandstore is empty - last if(!@commandstore); + # 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 - $commanddetails = pop(@commandstore); - $commandname = $commanddetails->{'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/(((?<!\\){)|((?<!\\)}))/g) - { + while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) { # store the match, either { or } my $braceType = $1; - # exit the loop if @commandstore is empty - last if(!@commandstore); + # 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 - $commanddetails = pop(@commandstore); - $commandname = $commanddetails->{'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/((?<!\\)%.*$)/) - { + if($row =~ m/((?<!\\)%.*$)/) { $row =~ s/((?<!\\)%.*)/%TC/; $trailingcomments=$1; } @@ -1864,8 +1781,7 @@ sub format_block{ $maxNumberAmpersands = $currentNumberAmpersands if($currentNumberAmpersands > $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/((?<!\\)%.*$)/) - { + if($row =~ m/((?<!\\)%.*$)/) { $row =~ s/((?<!\\)%.*)/%TC/; $trailingcomments=$1; } @@ -1916,8 +1828,7 @@ sub format_block{ # loop through each column element # removing leading and trailing space - foreach $column (@tmprow) - { + foreach $column (@tmprow) { # increment column counter $aligncolcounter++; @@ -1927,18 +1838,14 @@ sub format_block{ # assign string size to the array $stringsize{$alignrowcounter.$aligncolcounter}=length($column); - if(length($column)==0) - { + if(length($column)==0){ $column=" "; } # put the row back together - if ($aligncolcounter ==0) - { + if ($aligncolcounter ==0){ $tmpstring = $column; - } - else - { + } else { $tmpstring .= "&".$column; } } @@ -1949,15 +1856,12 @@ sub format_block{ $tmpstring .= $linebreak; # put trailing comments back on - if($trailingcomments) - { + if($trailingcomments) { $tmpstring =~ s/%TC/$trailingcomments/; } push(@tmpblock,$tmpstring); - } - else - { + } else { # if there are no & then use the # NOFORMATTING token # remove leading space @@ -1967,16 +1871,12 @@ sub format_block{ } # calculate the maximum string size of each column - for($j=0;$j<=$aligncolcounter;$j++) - { + for($j=0;$j<=$aligncolcounter;$j++) { $maxmcolstrlength=0; - for($i=0; $i<=$alignrowcounter;$i++) - { + for($i=0; $i<=$alignrowcounter;$i++) { # make sure the stringsize is defined - if(defined $stringsize{$i.$j}) - { - if ($stringsize{$i.$j}>$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/((?<!\\)%.*$)/) - { + 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) - { + 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}; + } + +} diff --git a/Master/bin/win32/latexindent.exe b/Master/bin/win32/latexindent.exe Binary files differindex 039a470087f..fd9756080a7 100755 --- a/Master/bin/win32/latexindent.exe +++ b/Master/bin/win32/latexindent.exe diff --git a/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf Binary files differnew file mode 100644 index 00000000000..4ac36f075da --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf diff --git a/Master/texmf-dist/doc/support/latexindent/documentation/manual.tex b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex index a34339c06cd..c39b89e627e 100644 --- a/Master/texmf-dist/doc/support/latexindent/documentation/manual.tex +++ b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex @@ -1,24 +1,9 @@ % arara: pdflatex -% !arara: bibtex -% !arara: pdflatex -% !arara: pdflatex +% arara: bibtex +% arara: pdflatex +% arara: pdflatex % !arara: pdflatex -% !arara: indent: {overwrite: no, trace: yes, localSettings: yes, silent: yes} -% http://tex.stackexchange.com/questions/122135/how-to-add-a-png-icon-on-the-right-side-of-a-tcolorbox-title -\begin{filecontents}{mybib.bib} - @online{cmh:videodemo, - title="Video demonstration of latexindet.pl on youtube", - url="http://www.youtube.com/watch?v=s_AMmNVg5WM"} - @online{cpan, - title="CPAN: Comprehensive Perl Archive Network", - url="http://www.cpan.org/"} - @online{strawberryperl, - title="Strawberry Perl", - url="http://strawberryperl.com/"} - @online{cmhblog, - title="A Perl script for indenting tex files", - url="http://tex.blogoverflow.com/2012/08/a-perl-script-for-indenting-tex-files/"} -\end{filecontents} +% !arara: indent: {overwrite: yes, trace: yes, localSettings: yes, silent: yes} \documentclass[11pt]{article} % This program is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by @@ -45,22 +30,35 @@ top=2cm,bottom=1.5cm]{geometry} % page setup \usepackage[charter]{mathdesign} % changes font \usepackage[expansion=false,kerning=true]{microtype} % better kerning \usepackage{enumitem} % custom lists -\usepackage{tikz} % so so much -\usepackage{tcolorbox} +% setup gitinfo2, as in the manual, details just above begin{document} +\usepackage[mark,grumpy]{gitinfo2} +\usepackage{examplep} % tcolorbox libraries \tcbuselibrary{breakable,skins,listings} +% tikz libraries \usetikzlibrary{positioning} +\usetikzlibrary{decorations.pathmorphing} +\usetikzlibrary{decorations,shapes} \usepackage{varioref} % clever referencing -\usepackage[colorlinks=true,linkcolor=blue,citecolor=black]{hyperref} +\usepackage{hyperref} +\hypersetup{ + pdfauthor={Chris Hughes}, + pdftitle={latexindent.pl package}, + pdfkeywords={perl;beautify;indentation}, + bookmarksnumbered, + bookmarksopen, + linktocpage, + colorlinks=true, + linkcolor=blue, + citecolor=black, +} \usepackage{cleveref} -\addbibresource{mybib} - -%\newmdenv[linecolor=red,innertopmargin=.5cm,linewidth=3pt, -% splittopskip=\topskip,skipbelow=0pt,% -%]{warning} +\addbibresource{latex-indent} +\addbibresource{contributors} +% http://tex.stackexchange.com/questions/122135/how-to-add-a-png-icon-on-the-right-side-of-a-tcolorbox-title \newtcolorbox{warning}{parbox=false,breakable,enhanced,arc=0mm,colback=red!5,colframe=red,leftrule=12mm,% overlay={\node[anchor=north west,outer sep=2pt] at (frame.north west) {\includegraphics[width=8mm]{warning}}; }} @@ -106,7 +104,66 @@ top=2cm,bottom=1.5cm]{geometry} % page setup linewidth=1.25\textwidth, columns=fullflexible, } -\newcommand{\verbitem}[1]{\small\ttfamily{#1}} + +% stars around contributors +\pgfdeclaredecoration{stars}{initial}{ + \state{initial}[width=15pt] + { + \pgfmathparse{round(rnd*100)} + \pgfsetfillcolor{yellow!\pgfmathresult!orange} + \pgfsetstrokecolor{yellow!\pgfmathresult!red} + \pgfnode{star}{center}{}{}{\pgfusepath{stroke,fill}} + } + \state{final} + { + \pgfpathmoveto{\pgfpointdecoratedpathlast} + } +} + +\newtcolorbox{stars}{% + enhanced jigsaw, + breakable, % allow page breaks + left=0cm, + top=0cm, + before skip=0.2cm, + boxsep=0cm, + frame style={draw=none,fill=none}, % hide the default frame + colback=white, + overlay={ + \draw[inner sep=0,minimum size=rnd*15pt+2pt] + decorate[decoration={stars,segment length=2cm}] { + decorate[decoration={zigzag,segment length=2cm,amplitude=0.3cm}] { + ([xshift=-.5cm,yshift=0.1cm]frame.south west) -- ([xshift=-.5cm,yshift=0.4cm]frame.north west) + }}; + \draw[inner sep=0,minimum size=rnd*15pt+2pt] + decorate[decoration={stars,segment length=2cm}] { + decorate[decoration={zigzag,segment length=2cm,amplitude=0.3cm}] { + ([xshift=.75cm,yshift=0.1cm]frame.south east) -- ([xshift=.75cm,yshift=0.6cm]frame.north east) + }}; + }, + % paragraph skips obeyed within tcolorbox + parbox=false, +} + +% copied from /usr/local/texlive/2013/texmf-dist/tex/latex/biblatex/bbx/numeric.bbx +% the only modification is the \stars and \endstars +\defbibenvironment{specialbib} +{\stars\list + {\printtext[labelnumberwidth]{% + \printfield{prefixnumber}% + \printfield{labelnumber}}} + {\setlength{\labelwidth}{\labelnumberwidth}% + \setlength{\leftmargin}{\labelwidth}% + \setlength{\labelsep}{\biblabelsep}% + \addtolength{\leftmargin}{\labelsep}% + \setlength{\itemsep}{\bibitemsep}% + \setlength{\parsep}{\bibparsep}}% + \renewcommand*{\makelabel}[1]{\hss##1}} +{\endlist\endstars} +{\item} + +% see: http://tex.stackexchange.com/questions/2245/verbatim-description-list-item +\newcommand{\verbitem}[1]{\small\PVerb{#1}} % stolen from arara.sty http://mirrors.med.harvard.edu/ctan/support/arara/doc/arara.sty %\lstnewenvironment{yaml}[1][]{\lstset{% % basicstyle=\ttfamily, @@ -160,16 +217,47 @@ top=2cm,bottom=1.5cm]{geometry} % page setup \crefname{listing}{Listing}{Listings} \Crefname{listing}{Listing}{Listings} +% headers and footers +\fancyhf{} % delete current header and footer +\fancyhead[R]{\bfseries\thepage} +\fancyheadoffset[L]{3cm} +\pagestyle{fancy} + +% renew plain style +\fancypagestyle{plain}{% +\fancyhf{} % clear all header and footer fields +\renewcommand{\headrulewidth}{0pt} +\renewcommand{\footrulewidth}{0pt}} + +% sidebyside environment +\newenvironment{sidebyside}{\begin{adjustwidth}{-3cm}{1cm}}{\end{adjustwidth}} + +% gitinfo2 settings +\renewcommand{\gitMark}{\gitBranch\,@\,\gitAbbrevHash{}\,\textbullet{}\,\gitAuthorDate } + +% setting up gitinfo2: +% copy the file post-xxx-sample.txt from https://www.ctan.org/tex-archive/macros/latex/contrib/gitinfo2 +% and put it in .git/hooks/post-checkout +% then +% cd .git/hooks +% chmod g+x post-checkout +% chmod +x post-checkout +% cp post-checkout post-commit +% cp post-checkout post-merge +% cd ../.. +% git checkout master +% git checkout develop +% ls .git +% and you should see gitHeadInfo.gin \begin{document} - % \begin{noindent} \title{\lstinline[basicstyle=\huge\ttfamily]!latexindent.pl!\\[1cm] - Version 2.1R} + Version 2.2} % \end{noindent} -\author{Chris Hughes \footnote{smr01cmh AT users.sourceforge.net}} +\author{Chris Hughes \footnote{and contributors! (See \vref{sec:contributors}.)}} \maketitle \begin{abstract} - \lstinline!latexindent.pl! is a \lstinline!Perl! script that indents \lstinline!.tex! + \lstinline!latexindent.pl! is a \lstinline!Perl! script that indents \lstinline!.tex! (and other) files according to an indentation scheme that the user can modify to suit their taste. Environments, including those with alignment delimiters (such as \lstinline!tabular!), and commands, including those that can split braces and brackets across lines, @@ -198,6 +286,10 @@ have to make a GUI for \lstinline!latexindent.pl!, but the release of \lstinline has meant there is no need. Thank you to Paulo for all of your advice and encouragement. +There have been several contributors to the project so far (and hopefully more in +the future!); thank you very much to the people detailed in \vref{sec:contributors} +for their valued contributions. + \subsection{License} \lstinline!latexindent.pl! is free and open source, and it always will be. Before you start using it on any important files, bear in mind that \lstinline!latexindent.pl! has the option to overwrite your \lstinline!.tex! files. @@ -240,8 +332,8 @@ result would be the same, regardless of the leading white space at the beginning each line which is stripped by \lstinline!latexindent.pl! (unless a \lstinline!verbatim!-like environment or \lstinline!noIndentBlock! is specified--more on this in \cref{sec:defuseloc}). -\begin{adjustwidth}{-2cm}{2cm} - \noindent + \begin{sidebyside} + \noindent \begin{minipage}{.6\textwidth} \begin{cmhlistings}[style=demo]{\lstinline!filecontents! before}{lst:filecontentsbefore} \begin{filecontents}{mybib.bib} @@ -254,7 +346,7 @@ url="... \end{filecontents} \end{cmhlistings} \end{minipage}% - \noindent + \noindent \begin{minipage}{.6\textwidth} \begin{cmhlistings}[style=demo]{\lstinline!filecontents! after}{lst:filecontentsafter} \begin{filecontents}{mybib.bib} @@ -317,99 +409,127 @@ shrink inner sep/.code={ \end{pspicture}} \end{cmhlistings} \end{minipage} -\end{adjustwidth} + \end{sidebyside} \section{How to use the script} +\lstinline!latexindent.pl! ships as part of the \TeX Live distribution for +Linux and Mac users; \lstinline!latexindent.exe! ships as part of the \TeX Live +and MiK\TeX distributions for Windows users. These files are also available +from github \cite{latexindent-home} should you wish to use them without +a \TeX{} distribution; in this case, you may like to read \vref{sec:updating-path} +which details how the \lstinline!path! variable can be updated. + +In what follows, we will always refer to \lstinline!latexindent.pl!, but depending on +your operating system and preference, you might substitute \lstinline!latexindent.exe! or +simply \lstinline!latexindent!. + There are two ways to use \lstinline!latexindent.pl!: from the command line, -and using \lstinline!arara!. We will discuss how to change the settings and behaviour -of the script in \cref{sec:defuseloc}. +and using \lstinline!arara!; we discuss these in \cref{sec:commandline} and +\cref{sec:arara} respectively. We will discuss how to change the settings and +behaviour of the script in \vref{sec:defuseloc}. \lstinline!latexindent.pl! ships with \lstinline!latexindent.exe! for Windows users, so that you can use the script with or without a Perl distribution. If you plan to use \lstinline!latexindent.pl! (i.e, the original Perl script) then you will need a few standard Perl modules--see \vref{sec:requiredmodules} for details. -In what follows, we will always refer to \lstinline!latexindent.pl!, but depending on -your operating system and preference, you might substitute \lstinline!latexindent.exe! or -simply \lstinline!latexindent!. - \subsection{From the command line}\label{sec:commandline} \lstinline!latexindent.pl! has a number of different switches/flags/options, which -can be combined in any way that you like. \lstinline!latexindent.pl! -produces a \lstinline!.log! file, \lstinline!indent.log! every time it +can be combined in any way that you like, either in short or long form as detailed below. +\lstinline!latexindent.pl! produces a \lstinline!.log! file, \lstinline!indent.log! every time it is run. There is a base of information that is written to \lstinline!indent.log!, but other additional information will be written depending on which of the following options are used. -\begin{itemize}[labelsep=.5cm] +\begin{itemize}[labelsep=.25cm] \item[] \lstinline!latexindent.pl! - This will output a welcome message to the terminal, including the version number - and available options. - \item[\verbitem{-h}] \lstinline!latexindent.pl -h! + This will output a welcome message to the terminal, including the version number + and available options. + \item[\verbitem{-h, --help}] \lstinline!latexindent.pl -h! - As above this will output a welcome message to the terminal, including the version number - and available options. + As above this will output a welcome message to the terminal, including the version number + and available options. \item[] \lstinline!latexindent.pl myfile.tex! - This will operate on \lstinline!myfile.tex!, but will simply output to your terminal; \lstinline!myfile.tex! will not be changed in any way using this command. - \item[\verbitem{-w}] \lstinline!latexindent.pl -w myfile.tex! - - This \emph{will} overwrite \lstinline!myfile.tex!, but it will - make a copy of \lstinline!myfile.tex! first. You can control the name of - the extension (default is \lstinline!.bak!), and how many different backups are made-- - more on this in \cref{sec:defuseloc}; see \lstinline!backupExtension! and \lstinline!onlyOneBackUp!. - - Note that if \lstinline!latexindent.pl! can not create the backup, then it - will exit without touching your original file; an error message will be given - asking you to check the permissions of the backup file. - \item[\verbitem{-o}] \lstinline!latexindent.pl -o myfile.tex outputfile.tex! - - This will indent \lstinline!myfile.tex! and output it to \lstinline!outputfile.tex!, - overwriting it (\lstinline!outputfile.tex!) if it already exists. Note that if \lstinline!latexindent.pl! is called with both - the \lstinline!-w! and \lstinline!-o! switches, then \lstinline!-w! will - be ignored and \lstinline!-o! will take priority (this seems safer than the - other way round). - - Note that using \lstinline!-o! is equivalent to using \lstinline!latexindent.pl myfile.tex > outputfile.tex! - \item[\verbitem{-s}] \lstinline!latexindent.pl -s myfile.tex! - - Silent mode: no output will be given to the terminal. - \item[\verbitem{-t}] \lstinline!latexindent.pl -t myfile.tex! - - Tracing mode: verbose output will be given to \lstinline!indent.log!. This - is useful if \lstinline!latexindent.pl! has made a mistake and you're - trying to find out where and why. You might also be interested in learning - about \lstinline!latexindent.pl!'s thought process--if so, this - switch is for you. - \item[\verbitem{-l}] \lstinline!latexindent.pl -l myfile.tex! - - \label{page:localswitch} - Local settings: you might like to read \cref{sec:defuseloc} before - using this switch. \lstinline!latexindent.pl! will always load \lstinline!defaultSettings.yaml! - and if it is called with the \lstinline!-l! switch and it finds \lstinline!localSettings.yaml! - in the same directory as \lstinline!myfile.tex! then these settings will be - added to the indentation scheme. Information will be given in \lstinline!indent.log! on - the success or failure of loading \lstinline!localSettings.yaml!. - \item[\verbitem{-d}] \lstinline!latexindent.pl -d myfile.tex! - - Only \lstinline!defaultSettings.yaml!: you might like to read \cref{sec:defuseloc} before - using this switch. By default, \lstinline!latexindent.pl! will always search for - \lstinline!indentconfig.yaml! or \lstinline!.indentconfig.yaml! in your home directory. If you would prefer it not to do so - then (instead of deleting or renaming \lstinline!indentconfig.yaml!/\lstinline!.indentconfig.yaml!) you can simply - call the script with the \lstinline!-d! switch; note that this will also tell - the script to ignore \lstinline!localSettings.yaml! even if it has been called with the - \lstinline!-l! switch. - - \item[\verbitem{-c}]\lstinline!latexindent.pl -c=/path/to/directory/ myfile.tex! - - If you wish to have backup files and \lstinline!indent.log! written to a directory - other than the current working directory, then you can send these `cruft' files - to another directory. - % this switch was made as a result of http://tex.stackexchange.com/questions/142652/output-latexindent-auxiliary-files-to-a-different-directory + This will operate on \lstinline!myfile.tex!, but will simply output to your terminal; \lstinline!myfile.tex! will not be changed in any way using this command. + \item[\verbitem{-w, --overwrite}] \lstinline!latexindent.pl -w myfile.tex! + + This \emph{will} overwrite \lstinline!myfile.tex!, but it will + make a copy of \lstinline!myfile.tex! first. You can control the name of + the extension (default is \lstinline!.bak!), and how many different backups are made-- + more on this in \cref{sec:defuseloc}; see \lstinline!backupExtension! and \lstinline!onlyOneBackUp!. + + Note that if \lstinline!latexindent.pl! can not create the backup, then it + will exit without touching your original file; an error message will be given + asking you to check the permissions of the backup file. + \item[\verbitem{-o,--outputfile}] \lstinline!latexindent.pl -o myfile.tex outputfile.tex! + + This will indent \lstinline!myfile.tex! and output it to \lstinline!outputfile.tex!, + overwriting it (\lstinline!outputfile.tex!) if it already exists. Note that if \lstinline!latexindent.pl! is called with both + the \lstinline!-w! and \lstinline!-o! switches, then \lstinline!-w! will + be ignored and \lstinline!-o! will take priority (this seems safer than the + other way round). + + Note that using \lstinline!-o! is equivalent to using \lstinline!latexindent.pl myfile.tex > outputfile.tex! + \item[\verbitem{-s, --silent}] \lstinline!latexindent.pl -s myfile.tex! + + Silent mode: no output will be given to the terminal. + \item[\verbitem{-t, --trace}] \lstinline!latexindent.pl -t myfile.tex! + + \label{page:traceswitch} + Tracing mode: verbose output will be given to \lstinline!indent.log!. This + is useful if \lstinline!latexindent.pl! has made a mistake and you're + trying to find out where and why. You might also be interested in learning + about \lstinline!latexindent.pl!'s thought process--if so, this + switch is for you. + \item[\verbitem{-tt, --ttrace}] \lstinline!latexindent.pl -tt myfile.tex! + + \emph{More detailed} tracing mode: this option gives more details to \lstinline!indent.log! + than the standard \lstinline!trace! option. + \item[\verbitem{-l, --local[=myyaml.yaml]}] \lstinline!latexindent.pl -l myfile.tex! + +\lstinline!latexindent.pl -l=myyaml.yaml myfile.tex! + +\lstinline!latexindent.pl -l myyaml.yaml myfile.tex! + + + \label{page:localswitch} + Local settings: you might like to read \cref{sec:defuseloc} before + using this switch. \lstinline!latexindent.pl! will always load \lstinline!defaultSettings.yaml! + and if it is called with the \lstinline!-l! switch and it finds \lstinline!localSettings.yaml! + in the same directory as \lstinline!myfile.tex! then these settings will be + added to the indentation scheme. Information will be given in \lstinline!indent.log! on + the success or failure of loading \lstinline!localSettings.yaml!. + +The \lstinline!-l! flag can take an \emph{optional} parameter which details the name of a \lstinline!yaml! file +that resides in the same directory as \lstinline!myfile.tex!; you can use this option if you would +like to load a settings file in the current working directory that is \emph{not} called \lstinline!localSettings.yaml!. + + \item[\verbitem{-d, --onlydefault}] \lstinline!latexindent.pl -d myfile.tex! + + Only \lstinline!defaultSettings.yaml!: you might like to read \cref{sec:defuseloc} before + using this switch. By default, \lstinline!latexindent.pl! will always search for + \lstinline!indentconfig.yaml! or \lstinline!.indentconfig.yaml! in your home directory. If you would prefer it not to do so + then (instead of deleting or renaming \lstinline!indentconfig.yaml!/\lstinline!.indentconfig.yaml!) you can simply + call the script with the \lstinline!-d! switch; note that this will also tell + the script to ignore \lstinline!localSettings.yaml! even if it has been called with the + \lstinline!-l! switch. + + \item[\verbitem{-c, --cruft=<directory>}]\lstinline!latexindent.pl -c=/path/to/directory/ myfile.tex! + + If you wish to have backup files and \lstinline!indent.log! written to a directory + other than the current working directory, then you can send these `cruft' files + to another directory. + % this switch was made as a result of http://tex.stackexchange.com/questions/142652/output-latexindent-auxiliary-files-to-a-different-directory \end{itemize} -\subsection{From \lstinline!arara!} +\lstinline!latexindent.pl! can also be called on a file without the file extension, for +example \lstinline[breaklines=true,breakatwhitespace=true,]!latexindent.pl myfile! and in which case, you can specify +the order in which extensions are searched for; see \vref{lst:fileExtensionPreference} +for full details. + +\subsection{From \lstinline!arara!}\label{sec:arara} Using \lstinline!latexindent.pl! from the command line is fine for some folks, but others may find it easier to use from \lstinline!arara!. \lstinline!latexindent.pl! ships with an \lstinline!arara! rule, \lstinline!indent.yaml!, which can be copied @@ -476,100 +596,102 @@ but here is a description of what each switch is designed to do. The default value is given in each case. You can certainly feel free to edit \lstinline!defaultSettings.yaml!, but -this is not ideal as it may be overwritten when you update your distribution-- +this is not ideal as it may be overwritten when you update your \TeX{} distribution -- all of your hard work tweaking the script would be undone! Don't worry, -there's a solution--feel free to peek ahead to \cref{sec:indentconfig} if you like. +there's a solution, feel free to peek ahead to \cref{sec:indentconfig} if you like. \begin{itemize} \item[\verbitem{defaultIndent}] \lstinline!"\t"! - This is the default indentation (\lstinline!\t! means a tab) used in the absence of other details - for the command or environment we are working with--see \lstinline!indentRules! - for more details (\cpageref{page:indentRules}). + This is the default indentation (\lstinline!\t! means a tab) used in the absence of other details + for the command or environment we are working with--see \lstinline!indentRules! + for more details (\cpageref{page:indentRules}). - If you're interested in experimenting with \lstinline!latexindent.pl! then you - can \emph{remove} all indentation by setting \lstinline!defaultIndent: ""! + If you're interested in experimenting with \lstinline!latexindent.pl! then you + can \emph{remove} all indentation by setting \lstinline!defaultIndent: ""! \item[\verbitem{backupExtension}] \lstinline!.bak! - If you call \lstinline!latexindent.pl! with the \lstinline!-w! switch (to overwrite - \lstinline!myfile.tex!) then it will create a backup file before doing - any indentation: \lstinline!myfile.bak0! + If you call \lstinline!latexindent.pl! with the \lstinline!-w! switch (to overwrite + \lstinline!myfile.tex!) then it will create a backup file before doing + any indentation: \lstinline!myfile.bak0! - By default, every time you call \lstinline!latexindent.pl! after this with - the \lstinline!-w! switch it will create \lstinline!myfile.bak1!, \lstinline!myfile.bak2!, - etc. + By default, every time you call \lstinline!latexindent.pl! after this with + the \lstinline!-w! switch it will create \lstinline!myfile.bak1!, \lstinline!myfile.bak2!, + etc. \item[\verbitem{onlyOneBackUp}] \lstinline!0! - \label{page:onlyonebackup} - If you don't want a backup for every time that you call \lstinline!latexindent.pl! (so - you don't want \lstinline!myfile.bak1!, \lstinline!myfile.bak2!, etc) and you simply - want \lstinline!myfile.bak! (or whatever you chose \lstinline!backupExtension! to be) - then change \lstinline!onlyOneBackUp! to \lstinline!1!. + \label{page:onlyonebackup} + If you don't want a backup for every time that you call \lstinline!latexindent.pl! (so + you don't want \lstinline!myfile.bak1!, \lstinline!myfile.bak2!, etc) and you simply + want \lstinline!myfile.bak! (or whatever you chose \lstinline!backupExtension! to be) + then change \lstinline!onlyOneBackUp! to \lstinline!1!. \item[\verbitem{maxNumberOfBackUps}]\lstinline!0! - Some users may only want a finite number of backup files, - say at most $3$, in which case, they can change this switch. - The smallest value of \lstinline!maxNumberOfBackUps! is $0$ which will \emph{not} - prevent backup files being made--in this case, the behaviour will be dictated - entirely by \lstinline!onlyOneBackUp!. - %\footnote{This was a feature request made on \href{https://github.com/cmhughes/latexindent.plx}{github}} + Some users may only want a finite number of backup files, + say at most $3$, in which case, they can change this switch. + The smallest value of \lstinline!maxNumberOfBackUps! is $0$ which will \emph{not} + prevent backup files being made--in this case, the behaviour will be dictated + entirely by \lstinline!onlyOneBackUp!. + %\footnote{This was a feature request made on \href{https://github.com/cmhughes/latexindent.plx}{github}} \item[\verbitem{cycleThroughBackUps}]\lstinline!0! - Some users may wish to cycle through backup files, by deleting the - oldest backup file and keeping only the most recent; for example, - with \lstinline!maxNumberOfBackUps: 4!, and \lstinline!cycleThroughBackUps! - set to \lstinline!1! then the \lstinline!copy! procedure given in \cref{lst:cycleThroughBackUps} - would be obeyed. + Some users may wish to cycle through backup files, by deleting the + oldest backup file and keeping only the most recent; for example, + with \lstinline!maxNumberOfBackUps: 4!, and \lstinline!cycleThroughBackUps! + set to \lstinline!1! then the \lstinline!copy! procedure given in \cref{lst:cycleThroughBackUps} + would be obeyed. - \begin{cmhlistings}[language=Perl]{\lstinline!cycleThroughBackUps!}{lst:cycleThroughBackUps} + \begin{cmhlistings}[language=Perl]{\lstinline!cycleThroughBackUps!}{lst:cycleThroughBackUps} copy myfile.bak1 to myfile.bak0 copy myfile.bak2 to myfile.bak1 copy myfile.bak3 to myfile.bak2 copy myfile.bak4 to myfile.bak3 - \end{cmhlistings} + \end{cmhlistings} \item[\verbitem{indentPreamble}] \lstinline!0! - The preamble of a document can sometimes contain some trickier code - for \lstinline!latexindent.pl! to work with. By default, \lstinline!latexindent.pl! - won't try to operate on the preamble, but if you'd like it to try then - change \lstinline!indentPreamble! to \lstinline!1!. + The preamble of a document can sometimes contain some trickier code + for \lstinline!latexindent.pl! to work with. By default, \lstinline!latexindent.pl! + won't try to operate on the preamble, but if you'd like it to try then + change \lstinline!indentPreamble! to \lstinline!1!. \item[\verbitem{alwaysLookforSplitBraces}] \lstinline!1! - This switch tells \lstinline!latexindent.pl! to look for commands that - can split \emph{braces} across lines, such as \lstinline!parbox!, \lstinline!tikzset!, etc. In older - versions of \lstinline!latexindent.pl! you had to specify each one in \lstinline!checkunmatched!--this - clearly became tedious, hence the introduction of \lstinline!alwaysLookforSplitBraces!. + This switch tells \lstinline!latexindent.pl! to look for commands that + can split \emph{braces} across lines, such as \lstinline!parbox!, \lstinline!tikzset!, etc. In older + versions of \lstinline!latexindent.pl! you had to specify each one in \lstinline!checkunmatched!--this + clearly became tedious, hence the introduction of \lstinline!alwaysLookforSplitBraces!. - \emph{As long as you leave this switch on (set to 1) you don't need to specify which - commands can split braces across lines--you can ignore the - fields \lstinline!checkunmatched! and \lstinline!checkunmatchedELSE! described - later on \cpageref{lst:checkunmatched}}. + \emph{As long as you leave this switch on (set to 1) you don't need to specify which + commands can split braces across lines--you can ignore the + fields \lstinline!checkunmatched! and \lstinline!checkunmatchedELSE! described + later on \cpageref{lst:checkunmatched}}. \item[\verbitem{alwaysLookforSplitBrackets}] \lstinline!1! - This switch tells \lstinline!latexindent.pl! to look for commands that - can split \emph{brackets} across lines, such as \lstinline!psSolid!, \lstinline!pgfplotstabletypeset!, - etc. In older versions of \lstinline!latexindent.pl! you had to specify each one in \lstinline!checkunmatchedbracket!-- - this clearly became tedious, hence the introduction of \lstinline!alwaysLookforSplitBraces!. + This switch tells \lstinline!latexindent.pl! to look for commands that + can split \emph{brackets} across lines, such as \lstinline!psSolid!, \lstinline!pgfplotstabletypeset!, + etc. In older versions of \lstinline!latexindent.pl! you had to specify each one in \lstinline!checkunmatchedbracket!-- + this clearly became tedious, hence the introduction of \lstinline!alwaysLookforSplitBraces!. - \emph{As long as you leave this switch on (set to 1) you don't need to specify which - commands can split brackets across lines--you can ignore \lstinline!checkunmatchedbracket! described later on - \cpageref{lst:checkunmatched}}. + \emph{As long as you leave this switch on (set to 1) you don't need to specify which + commands can split brackets across lines--you can ignore \lstinline!checkunmatchedbracket! described later on + \cpageref{lst:checkunmatched}}. \item[\verbitem{removeTrailingWhitespace}] \lstinline!0! - By default \lstinline!latexindent.pl! indents every line (including empty lines) - which creates `trailing whitespace' feared by most version control systems. If - this option is set to \lstinline!1!, trailing whitespace is removed from all - lines, also non-empty ones. In general this should not create any problems, but - by precaution this option is turned off by default. Thanks to \href{https://github.com/vosskuhle}{vosskuhle} for - providing this feature. + By default \lstinline!latexindent.pl! indents every line (including empty lines) + which creates `trailing white space' feared by most version control systems. If + this option is set to \lstinline!1!, trailing white space is removed from all + lines, also non-empty ones. In general this should not create any problems, but + by precaution this option is turned off by default. Thanks to \cite{vosskuhle} for + providing this feature. \item[\verbitem{lookForAlignDelims}] This is the first example of a field - in \lstinline!defaultSettings.yaml! that has more than one line; \cref{lst:aligndelims} - shows more details. + in \lstinline!defaultSettings.yaml! that has more than one line; \cref{lst:aligndelims:basic} + shows more details. In fact, the fields in \verbitem{lookForAlignDelims} can actually + take two different forms: the \emph{basic} version is shown in \cref{lst:aligndelims:basic} + and the \emph{advanced} version in \cref{lst:aligndelims:advanced}; we will discuss each in turn. - \begin{cmhlistings}[style=yaml]{\lstinline!lookForAlignDelims!}{lst:aligndelims} + \begin{cmhlistings}[style=yaml]{\lstinline!lookForAlignDelims! (basic)}{lst:aligndelims:basic} lookForAlignDelims: tabular: 1 tabularx: 1 @@ -591,18 +713,18 @@ lookForAlignDelims: The environments specified in this field will be operated on in a special way by \lstinline!latexindent.pl!. In particular, it will try and align each column by its alignment tabs. It does have some limitations (discussed further in \cref{sec:knownlimitations}), - but in many cases it will produce results such as those in \cref{lst:tabularbefore,lst:tabularafter}. + but in many cases it will produce results such as those in \cref{lst:tabularbefore:basic,lst:tabularafter:basic}. \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! before}{lst:tabularbefore} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! before}{lst:tabularbefore:basic} \begin{tabular}{cccc} 1& 2 &3 &4\\ 5& &6 &\\ \end{tabular} \end{cmhlistings} - \end{minipage} + \end{minipage}% \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! after}{lst:tabularafter} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! after (basic)}{lst:tabularafter:basic} \begin{tabular}{cccc} 1 & 2 & 3 & 4 \\ 5 & & 6 & \\ @@ -614,13 +736,81 @@ lookForAlignDelims: environments then you can either remove them from \lstinline!lookForAlignDelims! altogether, or set the relevant key to \lstinline!0!, for example \lstinline!tabular: 0!, or if you just want to ignore \emph{specific} instances of the environment, you could wrap them in something from \lstinline!noIndentBlock! (see \cref{lst:noIndentBlock}). - \item If you have blocks of code that you wish to align at the \& character that - are \emph{not} wrapped in, for example, \lstinline!\begin{tabular}...\end{tabular}!, then you use the mark up - illustrated in \cref{lst:alignmentmarkup}. Note that the \lstinline!%*! must be next to - each other, but that there can be any number of spaces (possibly none) between the - \lstinline!*! and \lstinline!\begin{tabular}!; note also that you may use any - environment name that you have specified in \lstinline!lookForAlignDelims!. - \begin{cmhlistings}[style=demo,columns=fixed]{Mark up for aligning delimiters outside of environments}{lst:alignmentmarkup} + If you wish to remove the alignment of the \lstinline!\\! within a delimiter-aligned block, then the + advanced form of \lstinline!lookForAlignDelims! shown in \cref{lst:aligndelims:advanced} is for you. + \begin{cmhlistings}[style=yaml]{\lstinline!lookForAlignDelims! (advanced)}{lst:aligndelims:advanced} +lookForAlignDelims: + tabular: + delims: 1 + alignDoubleBackSlash: 0 + spacesBeforeDoubleBackSlash: 0 + tabularx: + delims: 1 + longtable: 1 + \end{cmhlistings} + + Note that you can use a mixture of the basic and advanced form: in \cref{lst:aligndelims:advanced} \lstinline!tabular! and \lstinline!tabularx! + are advanced and \lstinline!longtable! is basic. When using the advanced form, each field should receive at least 1 sub-field, and \emph{can} (but does not have to) receive up to 3 fields: + \begin{itemize} + \item \lstinline!delims!: switch equivalent to simply specifying, for example, \lstinline!tabular: 1! in + the basic version shown in \cref{lst:aligndelims:basic} (default: 1); + \item \lstinline!alignDoubleBackSlash!: switch to determine if \lstinline!\\! should be aligned (default: 1); + \item \lstinline!spacesBeforeDoubleBackSlash!: optionally, specifies the number of spaces to be inserted + before (non-aligned) \lstinline!\\!. In order to use this field, \lstinline!alignDoubleBackSlash! needs + to be set to 0 (default: 0). + \end{itemize} + + With the settings shown in \cref{lst:aligndelims:advanced} we receive the before-and-after results shown in + \cref{lst:tabularbefore:advanced,lst:tabularafter:advanced}; note that the ampersands have been aligned, but + the \lstinline!\\! have not (compare the alignment of \lstinline!\\! in \cref{lst:tabularafter:basic,lst:tabularafter:advanced}). + + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! before }{lst:tabularbefore:advanced} +\begin{tabular}{cccc} +1& 2 &3 &4\\ +5& &6 &\\ +\end{tabular} + \end{cmhlistings} + \end{minipage}% + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! after (advanced)}{lst:tabularafter:advanced} +\begin{tabular}{cccc} + 1 & 2 & 3 & 4\\ + 5 & & 6 &\\ +\end{tabular} + \end{cmhlistings} + \end{minipage} + + Using \lstinline!spacesBeforeDoubleBackSlash: 3! gives \cref{lst:tabularbefore:spacing,lst:tabularafter:spacing}, + note the spacing before the \lstinline!\\! in \cref{lst:tabularafter:spacing}. + + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! before}{lst:tabularbefore:spacing} +\begin{tabular}{cccc} +1& 2 &3 &4\\ +5& &6 &\\ +\end{tabular} + \end{cmhlistings} + \end{minipage}% + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! after (spacing)}{lst:tabularafter:spacing} +\begin{tabular}{cccc} + 1 & 2 & 3 & 4 \\ + 5 & & 6 & \\ +\end{tabular} + \end{cmhlistings} + \end{minipage} + + + + + If you have blocks of code that you wish to align at the \& character that + are \emph{not} wrapped in, for example, \lstinline!\begin{tabular}...\end{tabular}!, then you use the mark up + illustrated in \cref{lst:alignmentmarkup}. Note that the \lstinline!%*! must be next to + each other, but that there can be any number of spaces (possibly none) between the + \lstinline!*! and \lstinline!\begin{tabular}!; note also that you may use any + environment name that you have specified in \lstinline!lookForAlignDelims!. + \begin{cmhlistings}[style=demo,columns=fixed]{Mark up for aligning delimiters outside of environments}{lst:alignmentmarkup} \matrix{% %* \begin{tabular} 1 & 2 & 3 & 4 \\ @@ -630,11 +820,11 @@ lookForAlignDelims: \end{cmhlistings} \item[\verbitem{verbatimEnvironments}] A field that contains a list of environments - that you would like left completely alone--no indentation will be done - to environments that you have specified in this field--see \cref{lst:verbatimEnvironments}. + that you would like left completely alone--no indentation will be done + to environments that you have specified in this field--see \cref{lst:verbatimEnvironments}. - \begin{cmhlistings}[style=yaml]{\lstinline!verbatimEnvironments!}{lst:verbatimEnvironments} + \begin{cmhlistings}[style=yaml]{\lstinline!verbatimEnvironments!}{lst:verbatimEnvironments} verbatimEnvironments: verbatim: 1 lstlisting: 1 @@ -644,12 +834,12 @@ verbatimEnvironments: then \lstinline!latexindent.pl! will \emph{always} prioritize \lstinline!verbatimEnvironments!. \item[\verbitem{noIndentBlock}] If you have a block of code that you don't - want \lstinline!latexindent.pl! to touch (even if it is \emph{not} a verbatim-like - environment) then you can wrap it in an environment from \lstinline!noIndentBlock!; - you can use any name you like for this, provided you populate it as demonstrate in - \cref{lst:noIndentBlock}. + want \lstinline!latexindent.pl! to touch (even if it is \emph{not} a verbatim-like + environment) then you can wrap it in an environment from \lstinline!noIndentBlock!; + you can use any name you like for this, provided you populate it as demonstrate in + \cref{lst:noIndentBlock}. - \begin{cmhlistings}[style=yaml]{\lstinline!noIndentBlock!}{lst:noIndentBlock} + \begin{cmhlistings}[style=yaml]{\lstinline!noIndentBlock!}{lst:noIndentBlock} noIndentBlock: noindent: 1 cmhtest: 1 @@ -670,12 +860,12 @@ noIndentBlock: \end{cmhlistings} \item[\verbitem{noAdditionalIndent}] If you would prefer some of your - environments or commands not to receive any additional indent, then - populate \lstinline!noAdditionalIndent!; see \cref{lst:noAdditionalIndent}. - Note that these environments will still receive the \emph{current} level - of indentation unless they belong to \lstinline!verbatimEnvironments!, or \lstinline!noIndentBlock!. + environments or commands not to receive any additional indent, then + populate \lstinline!noAdditionalIndent!; see \cref{lst:noAdditionalIndent}. + Note that these environments will still receive the \emph{current} level + of indentation unless they belong to \lstinline!verbatimEnvironments!, or \lstinline!noIndentBlock!. - \begin{cmhlistings}[style=yaml]{\lstinline!noAdditionalIndent!}{lst:noAdditionalIndent} + \begin{cmhlistings}[style=yaml]{\lstinline!noAdditionalIndent!}{lst:noAdditionalIndent} noAdditionalIndent: document: 1 myexample: 1 @@ -695,10 +885,10 @@ noAdditionalIndent: you have to specify \emph{both} as \lstinline!1! (the default is \lstinline!0!). If you do not specify both as the same value you may get some interesting results! \item[\verbitem{indentRules}] If\label{page:indentRules} you would prefer to specify - individual rules for certain environments or commands, just - populate \lstinline!indentRules!; see \cref{lst:indentRules} + individual rules for certain environments or commands, just + populate \lstinline!indentRules!; see \cref{lst:indentRules} - \begin{cmhlistings}[style=yaml]{\lstinline!indentRules!}{lst:indentRules} + \begin{cmhlistings}[style=yaml]{\lstinline!indentRules!}{lst:indentRules} indentRules: myenvironment: "\t\t" anotherenvironment: "\t\t\t\t" @@ -715,11 +905,12 @@ indentRules: is given in \cref{sec:fieldhierachy}. \item[\verbitem{indentAfterHeadings}] This field enables the user to specify - indentation rules that take effect after heading commands such as \lstinline!\part!, \lstinline!\chapter!, - \lstinline!\section!, \lstinline!\subsection*! etc. This field is slightly different from all - of the fields that we have considered previously, because each element is - itself a field which has two elements: \lstinline!indent! and \lstinline!level!. - \begin{cmhlistings}[style=yaml]{\lstinline!indentAfterHeadings!}{lst:indentAfterHeadings} + indentation rules that take effect after heading commands such as \lstinline!\part!, \lstinline!\chapter!, + \lstinline!\section!, \lstinline!\subsection*! etc. This field is slightly different from most + of the fields that we have considered previously, because each element is + itself a field which has two elements: \lstinline!indent! and \lstinline!level!. (Similar + in structure to the advanced form of \lstinline!lookForAlignDelims! in \cref{lst:aligndelims:advanced}.) + \begin{cmhlistings}[style=yaml]{\lstinline!indentAfterHeadings!}{lst:indentAfterHeadings} indentAfterHeadings: part: indent: 0 @@ -744,15 +935,15 @@ indentAfterHeadings: tells \lstinline!latexindent.pl! simply to use a space character after \lstinline!\chapter! headings (once \lstinline!indent! is set to \lstinline!1! for \lstinline!chapter!). - \item[\verbitem{indentAfterItems}] The environments specified in \lstinline!indentAfterItems! tell -\lstinline!latexindent.pl! to look for \lstinline!\item! commands; if these switches are set to \lstinline!1! -then indentation will be performed so as indent the code after each \lstinline!item!. - \begin{cmhlistings}{\lstinline!indentAfterItems!}{lst:indentafteritems} + \item[\verbitem{indentAfterItems}] The environments specified in \lstinline!indentAfterItems! tell + \lstinline!latexindent.pl! to look for \lstinline!\item! commands; if these switches are set to \lstinline!1! + then indentation will be performed so as indent the code after each \lstinline!item!. + \begin{cmhlistings}{\lstinline!indentAfterItems!}{lst:indentafteritems} indentAfterItems: itemize: 1 enumerate: 1 - \end{cmhlistings} -A demonstration is given in \cref{lst:itemsbefore,lst:itemsafter} + \end{cmhlistings} + A demonstration is given in \cref{lst:itemsbefore,lst:itemsafter} \begin{minipage}{.5\textwidth} \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!items! before}{lst:itemsbefore} @@ -763,7 +954,7 @@ some more text here \item another item \end{itemize} \end{cmhlistings} - \end{minipage} + \end{minipage}% \begin{minipage}{.5\textwidth} \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!items! after}{lst:itemsafter} \begin{itemize} @@ -775,38 +966,91 @@ some more text here \end{cmhlistings} \end{minipage} - \item[\verbitem{itemNames}] If you have your own \lstinline!item! commands (perhaps you - prefer to use \lstinline!myitem!, for example) - then you can put populate them in \lstinline!itemNames!. - For example, users of the \lstinline!exam! document class might like to add -\lstinline!parts! to \lstinline!indentAfterItems! and \lstinline!part! to \lstinline!itemNames! -to their user settings--see \vref{sec:indentconfig} for details of how to configure user settings, -and \vref{lst:mysettings} in particular.\label{page:examsettings} - -\item[\verbitem{constructIfElseFi}] The commands specified in this field - will tell \lstinline!latexindent.pl! to look for constructs that - have the form \lstinline!\if...! \lstinline!\else...! \lstinline!\fi!, such as, - for example, \lstinline!\ifnum!; see \cref{lst:iffibefore,lst:iffiafter} for - a before-and-after demonstration. - - \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!if-else-fi! construct before}{lst:iffibefore} + \item[\verbitem{itemNames}] If you have your own \lstinline!item! commands (perhaps you + prefer to use \lstinline!myitem!, for example) + then you can put populate them in \lstinline!itemNames!. + For example, users of the \lstinline!exam! document class might like to add + \lstinline!parts! to \lstinline!indentAfterItems! and \lstinline!part! to \lstinline!itemNames! + to their user settings--see \vref{sec:indentconfig} for details of how to configure user settings, + and \vref{lst:mysettings} in particular.\label{page:examsettings} + + \item[\verbitem{constructIfElseFi}] The commands specified in this field + will tell \lstinline!latexindent.pl! to look for constructs that + have the form \lstinline!\if...! \lstinline!\else...! \lstinline!\fi!, such as, + for example, \lstinline!\ifnum!; see \cref{lst:iffibefore,lst:iffiafter} for + a before-and-after demonstration. + + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!if-else-fi! construct before}{lst:iffibefore} \ifnum\radius>5 \ifnum\radius<16 \draw[decorate,... \fi \fi -\end{cmhlistings} - \end{minipage} - \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!if-else-fi! construct after}{lst:iffiafter} + \end{cmhlistings} + \end{minipage}% + \begin{minipage}{.5\textwidth} + \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!if-else-fi! construct after}{lst:iffiafter} \ifnum\radius>5 \ifnum\radius<16 \draw[decorate,... \fi \fi -\end{cmhlistings} - \end{minipage} + \end{cmhlistings} + \end{minipage} + + \item[\verbitem{fileExtensionPreference}] \lstinline!latexindent.pl! can be called to + act on a file without + specifying the file extension. For example we can call \lstinline!latexindent.pl myfile! + in which case the script will look for \lstinline!myfile! with the extensions + specified in \lstinline!fileExtensionPreference! in their numeric order. If + no match is found, the script will exit. As with all of the fields, you should + change and/or add to this as necessary. + \begin{cmhlistings}[style=yaml]{\lstinline!fileExtensionPreference!}{lst:fileExtensionPreference} +fileExtensionPreference: + .tex: 1 + .sty: 2 + .cls: 3 + .bib: 4 + \end{cmhlistings} + Calling \lstinline!latexindent.pl myfile! with the details specified in \cref{lst:fileExtensionPreference} + means that the script will first look for \lstinline!myfile.tex!, then \lstinline!myfile.sty!, \lstinline!myfile.cls!, + and finally \lstinline!myfile.bib! in order. +\item[\verbitem{logFilePreferences}] + \lstinline!latexindent.pl! writes information to \lstinline!indent.log!, some + of which can be customised by changing \lstinline!logFilePreferences!; see \cref{lst:logFilePreferences}. +\begin{cmhlistings}[style=yaml]{\lstinline!logFilePreferences!}{lst:logFilePreferences} +logFilePreferences: + showEveryYamlRead: 1 + showAlmagamatedSettings: 0 + endLogFileWith: '--------------' + traceModeIncreaseIndent: '>>' + traceModeAddCurrentIndent: '||' + traceModeDecreaseIndent: '<<' + traceModeBetweenLines: "\n" + \end{cmhlistings} +If you load your own user settings (see \vref{sec:indentconfig}) then \lstinline!latexindent.pl! will +detail them in \lstinline!indent.log!; you can choose not to have the details logged by switching +\lstinline!showEveryYamlRead! to \lstinline!0!. Once all of your settings have +been loaded, you can see the amalgamated settings by switching \lstinline!showAlmagamatedSettings! +to \lstinline!1!, if you wish. The log file will end with the characters +given in \lstinline!endLogFileWith!. + +When \lstinline!trace! mode is active (see \cpageref{page:traceswitch}) verbose information is written +to \lstinline!indent.log!. The decoration of this information can be customised through the remaining +fields given in \cref{lst:logFilePreferences}; note, in particular, the use of \lstinline!"\n"! for +escaped characters (using single quotes will not produce the same results). + +\item[\verbitem{fileContentsEnvironments}] + \lstinline!latexindent.pl! determines when the main document begins by looking for \lstinline!\begin{document}!; + it will not do so when inside any of the environments specified in \lstinline!fileContentsEnvironments!, see + \cref{lst:fileContentsEnvironments}. +\begin{cmhlistings}[style=yaml]{\lstinline!fileContentsEnvironments!}{lst:fileContentsEnvironments} +fileContentsEnvironments: + filecontents: 1 + filecontents*: 1 + \end{cmhlistings} + \begin{warning} \emph{The following fields are marked in red, as they are not necessary unless you wish to micro-manage your indentation scheme. @@ -816,38 +1060,38 @@ and \vref{lst:mysettings} in particular.\label{page:examsettings} % to anyone reading the source code- I know the next line isn't the % correct way to do it :) \item[\color{red}\verbitem{checkunmatched}] Assuming you keep \lstinline!alwaysLookforSplitBraces! set to \lstinline!1! (which - is the default) then you don't need to worry about \lstinline!checkunmatched!. + is the default) then you don't need to worry about \lstinline!checkunmatched!. - Should you wish to deactivate \lstinline!alwaysLookforSplitBraces! by setting it to \lstinline!0!, then - you can populate \lstinline!checkunmatched! with commands that can split braces across - lines--see \cref{lst:checkunmatched}. + Should you wish to deactivate \lstinline!alwaysLookforSplitBraces! by setting it to \lstinline!0!, then + you can populate \lstinline!checkunmatched! with commands that can split braces across + lines--see \cref{lst:checkunmatched}. - \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatched!}{lst:checkunmatched} + \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatched!}{lst:checkunmatched} checkunmatched: parbox: 1 vbox: 1 \end{cmhlistings} \item[\color{red}\verbitem{checkunmatchedELSE}] Similarly, assuming you keep \lstinline!alwaysLookforSplitBraces! set to \lstinline!1! (which - is the default) then you don't need to worry about \lstinline!checkunmatchedELSE!. + is the default) then you don't need to worry about \lstinline!checkunmatchedELSE!. - As in \lstinline!checkunmatched!, should you wish to deactivate \lstinline!alwaysLookforSplitBraces! by setting it to \lstinline!0!, then - you can populate \lstinline!checkunmatchedELSE! with commands that can split braces across - lines \emph{and} have an `else' statement--see \cref{lst:checkunmatchedELSE}. + As in \lstinline!checkunmatched!, should you wish to deactivate \lstinline!alwaysLookforSplitBraces! by setting it to \lstinline!0!, then + you can populate \lstinline!checkunmatchedELSE! with commands that can split braces across + lines \emph{and} have an `else' statement--see \cref{lst:checkunmatchedELSE}. - \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatchedELSE!}{lst:checkunmatchedELSE} + \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatchedELSE!}{lst:checkunmatchedELSE} checkunmatchedELSE: pgfkeysifdefined: 1 DTLforeach: 1 ifthenelse: 1 \end{cmhlistings} \item[\color{red}\verbitem{checkunmatchedbracket}] Assuming you keep \lstinline!alwaysLookforSplitBrackets! - set to \lstinline!1! (which is the default) then you don't need to worry about \lstinline!checkunmatchedbracket!. + set to \lstinline!1! (which is the default) then you don't need to worry about \lstinline!checkunmatchedbracket!. - Should you wish to deactivate \lstinline!alwaysLookforSplitBrackets! by setting it - to \lstinline!0!, then you can populate \lstinline!checkunmatchedbracket! with commands that can - split \emph{brackets} across lines--see \cref{lst:checkunmatchedbracket}. + Should you wish to deactivate \lstinline!alwaysLookforSplitBrackets! by setting it + to \lstinline!0!, then you can populate \lstinline!checkunmatchedbracket! with commands that can + split \emph{brackets} across lines--see \cref{lst:checkunmatchedbracket}. - \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatchedbracket!}{lst:checkunmatchedbracket} + \begin{cmhlistings}[style=yaml]{\lstinline!checkunmatchedbracket!}{lst:checkunmatchedbracket} checkunmatchedbracket: psSolid: 1 pgfplotstablecreatecol: 1 @@ -919,11 +1163,11 @@ and \lstinline!.indentconfig.yaml! (unless it is called with the \lstinline!-d! switch), which is a plain text file you can create that contains the \emph{absolute} paths for any settings files that you wish \lstinline!latexindent.pl! to load. There is no difference -between \lstinline!indentconfig.yaml! and \lstinline!.indentconfig.yaml!, other than the -fact that \lstinline!.indentconfig.yaml! is a `hidden' file; thank you to \href{https://github.com/cmhughes/latexindent.pl/pull/23}{Jacobo Diaz} -for providing this feature. In what follows, we will use \lstinline!indentconfig.yaml!, but it -is understood that this equally represents \lstinline!.indentconfig.yaml! as well. If you -have both files in existence, \lstinline!indentconfig.yaml! takes priority. +between \lstinline!indentconfig.yaml! and \lstinline!.indentconfig.yaml!, other than the +fact that \lstinline!.indentconfig.yaml! is a `hidden' file; thank you to \cite{jacobo-diaz-hidden-config} +for providing this feature. In what follows, we will use \lstinline!indentconfig.yaml!, but it +is understood that this equally represents \lstinline!.indentconfig.yaml! as well. If you +have both files in existence, \lstinline!indentconfig.yaml! takes priority. For Mac and Linux users, their home directory is \lstinline!~/username! while Windows (Vista onwards) is \lstinline!C:\Users\username! \footnote{If you're not sure @@ -959,7 +1203,7 @@ example, \lstinline!mysettings.yaml!. Once you have added the path to \lstinline feel free to start changing the switches and adding more environments to it as you see fit--have a look at \cref{lst:mysettings} for an example that uses four tabs for the default indent, adds the \lstinline!tabbing! -environment to the list of environments that contains alignment delimiters, +environment to the list of environments that contains alignment delimiters, and adds the changes we described on \cpageref{page:examsettings}. \begin{cmhlistings}[style=yaml]{\lstinline!mysettings.yaml! (example)}{lst:mysettings} @@ -998,16 +1242,15 @@ recognize then you'll get a warning, otherwise you'll get confirmation that will tell you so in \lstinline!indent.log!. \end{warning} -\subsection{\lstinline!localSettings.yaml!} +\subsection{\lstinline!localSettings.yaml!}\label{sec:localsettings} You may remember on \cpageref{page:localswitch} we discussed the \lstinline!-l! switch that tells \lstinline!latexindent.pl! to look for \lstinline!localSettings.yaml! in the \emph{same directory} as \lstinline!myfile.tex!. This settings file will be read \emph{after} \lstinline!defaultSettings.yaml! and, assuming they exist, user settings. -In contrast to the \emph{user} settings which can be named anything you like (provided that -they are detailed in \lstinline!indentconfig.yaml!), the \emph{local} settings file -must be called \lstinline!localSettings.yaml!. It can contain any switches that you'd +The \emph{local} settings file may be called \lstinline!localSettings.yaml!, and +it can contain any switches that you'd like to change--a sample is shown in \cref{lst:localSettings}. \begin{cmhlistings}[style=yaml]{\lstinline!localSettings.yaml! (example)}{lst:localSettings} @@ -1030,13 +1273,17 @@ for details--if \lstinline!localSettings.yaml! can not be read then you will get a warning, otherwise you'll get confirmation that \lstinline!latexindent.pl! has read \lstinline!localSettings.yaml!. +If you'd prefer to name your \lstinline!localSettings.yaml! file something different, (say, \lstinline!myyaml.yaml!) then +you can call \lstinline!latexindent.pl! using, for example, \lstinline[breaklines=true]!latexindent.pl -l=myyaml.yaml myfile.tex!. + \subsection{Settings load order}\label{sec:loadorder} \lstinline!latexindent.pl! loads the settings files in the following order: \begin{enumerate} - \item \lstinline!defaultSettings.yaml! (always loaded, can not be renamed) - \item \lstinline!anyUserSettings.yaml! (and any other arbitrarily-named files specified in \lstinline!indentconfig.yaml!) - \item \lstinline!localSettings.yaml! (if found in same directory as \lstinline!myfile.tex! and called - with \lstinline!-l! switch; can not be renamed) + \item \lstinline!defaultSettings.yaml! is always loaded, and can not be renamed; + \item \lstinline!anyUserSettings.yaml! and any other arbitrarily-named files specified in \lstinline!indentconfig.yaml!; + \item \lstinline!localSettings.yaml! but only if found in the same directory as \lstinline!myfile.tex! and called + with \lstinline!-l! switch; this file can be renamed, provided that the call to \lstinline!latexindent.pl! is adjusted + accordingly (see \cref{sec:localsettings}). \end{enumerate} A visual representation of this is given in \cref{fig:loadorder}. @@ -1124,17 +1371,22 @@ environment, the \lstinline!verbatim! environment \emph{will} be formatted, whic is probably not what you want. I hope to address this in future versions, but for the moment wrap it in a \lstinline!noIndentBlock! (see \cpageref{lst:noIndentBlockdemo}). -You can run \lstinline!latexindent! on \lstinline!.sty! and \lstinline!.cls! files, but it may -struggle with some of the pattern matching; if you find such a case in which it struggles, please feel free -to report it at \href{https://github.com/cmhughes/latexindent.pl}{https://github.com/cmhughes/latexindent.pl}, and -in the meantime, use a \lstinline!noIndentBlock! (see \cpageref{lst:noIndentBlockdemo}). +You can run \lstinline!latexindent! on \lstinline!.sty!, \lstinline!.cls! and any filetypes +that you specify in \lstinline[breaklines=true]!fileExtensionPreference! (see \vref{lst:fileExtensionPreference}); +if you find a case in which the script struggles, please feel free +to report it at \cite{latexindent-home}, and +in the meantime, consider using a \lstinline!noIndentBlock! (see \cpageref{lst:noIndentBlockdemo}). -I hope that this script is useful to some--if you find an example where the -script does not behave as you think it should, feel free to e-mail me or else -come and find me on the \url{http://tex.stackexchange.com} site; I'm often around +I hope that this script is useful to some; if you find an example where the +script does not behave as you think it should, the best way to contact me is to +report an issue on \cite{latexindent-home}; otherwise, feel free to find me on +the \url{http://tex.stackexchange.com} site; I'm often around and in the chat room. -\printbibliography[heading=bibintoc] +\nocite{*} +\section{References} +\printbibliography[heading=subbibnumbered,title={External links},notkeyword=contributor] +\printbibliography[env=specialbib,heading=subbibnumbered,title={Contributors\label{sec:contributors}},keyword=contributor] \appendix \section{Required \lstinline!Perl! modules}\label{sec:requiredmodules} @@ -1167,12 +1419,25 @@ might visit the software center, or else run \begin{lstlisting}[numbers=none] sudo perl -MCPAN -e 'install "File::HomeDir"' \end{lstlisting} + +Linux users may be interested in exploring Perlbrew \cite{perlbrew}; possible installation and setup +options follow for Ubuntu (other distributions will need slightly different commands). +\begin{lstlisting}[numbers=none] +sudo apt-get install perlbrew +perlbrew install perl-5.20.1 +perlbrew switch perl-5.20.1 +sudo apt-get install curl +curl -L http://cpanmin.us | perl - App::cpanminus +cpanm YAML::Tiny +cpanm File::HomeDir +\end{lstlisting} + Strawberry Perl users on Windows might use \lstinline!CPAN client!. All of the modules are readily available on CPAN \cite{cpan}. -As of Version 2.1R, \lstinline!indent.log! will contain details of the location +As of Version 2.1, \lstinline!indent.log! will contain details of the location of the Perl modules on your system. \lstinline!latexindent.exe! is a standalone -executable for Windows (and therefore does not require a Perl distribution) and caches copies of the Perl modules onto your system; if you +executable for Windows (and therefore does not require a Perl distribution) and caches copies of the Perl modules onto your system; if you wish to see where they are cached, use the \lstinline!trace! option, e.g \lstinline!latexindent.exe -t myfile.tex!. \section{The \lstinline!arara! rule} @@ -1207,41 +1472,41 @@ mode then you can write \lstinline!% arara: indent: {trace: off}!. Of course, you can apply these types of modifications to \emph{any} of the identifiers, but proceed with caution if you intend to do this for \lstinline!overwrite!. +\section{Updating the \lstinline!path! variable}\label{sec:updating-path} +\lstinline!latexindent.pl! ships with a few scripts that can update the \lstinline!path! variables +\footnote{Thanks to \cite{jasjuang} for this feature!}. If you're +on a Linux or Mac machine, then you'll want \lstinline!CMakeLists.txt! from \cite{latexindent-home}. +\subsection{Add to path for Linux} +To add \lstinline!latexindent.pl! to the path for Linux, follow these steps: +\begin{enumerate} + \item download \lstinline!latexindent.pl!, \lstinline!defaultSettings.yaml!, to your + chosen directory from \cite{latexindent-home} ; + \item within your directory, create a directory called \lstinline!path-helper-files! and + download \lstinline!CMakeLists.txt! and \lstinline!cmake_uninstall.cmake.in! + from \cite{latexindent-home}/path-helper-files to this directory; + \item run \lstinline!ls /usr/local/bin! to see what is \emph{currently} in there; + \item run the commands given in \cref{linux-add-to-path}; + \item run \lstinline!ls /usr/local/bin! again to check that \lstinline!latexindent.pl! and \lstinline!defaultSettings.yaml! + have been added. +\end{enumerate} +\begin{cmhlistings}[style=yaml,numbers=none]{Add to path from a Linux terminal}{linux-add-to-path} +sudo apt-get install cmake +sudo apt-get update && sudo apt-get install build-essential +mkdir build && cd build +cmake ../path-helper-files +sudo make install +\end{cmhlistings} +To \emph{remove} the files, run \lstinline!sudo make uninstall!. +\subsection{Add to path for Windows} +To add \lstinline!latexindent.exe! to the path for Windows, follow these steps: +\begin{enumerate} + \item download \lstinline!latexindent.exe!, \lstinline!defaultSettings.yaml!, \lstinline!add-to-path.bat! + from \cite{latexindent-home} to your chosen directory; + \item open a command prompt and run \lstinline!echo %path%! to see what is \emph{currently} in your \lstinline!%path%! variable; + \item right click on \lstinline!add-to-path.bat! and \emph{Run as administrator}; + \item log out, and log back in; + \item open a command prompt and run \lstinline!echo %path%! to check that the appropriate directory has been added to your + \lstinline!%path%!. +\end{enumerate} +To \emph{remove} the directory from your \lstinline!%path%!, run \lstinline!remove-from-path.bat! as administrator. \end{document} - -set local settings to include psset as an item -\documentclass[pstricks,border=30pt,12pt]{standalone} -\usepackage{pst-eucl} -\psset{opacity=.2} -\begin{document} -\begin{pspicture}(7,7) - \pstGeonode[PosAngle={-90,-90,0,-90,180}]{A}(5,0){B}(7,1){C}(2,1){D}(0,5){A_1} - \pstTranslation[PosAngle=120]{A}{A_1}{B,C,D}[B_1,C_1,D_1] - \pspolygon(A)(B)(C)(C_1)(D_1)(A_1) - \psline(A_1)(B_1)(C_1)(B)(B_1) - \pstMiddleAB[PosAngle=20]{B}{C_1}{E} - \psline(E)(C) - \pstMarkAngle{D}{E}{C}{} - \psset{linestyle=dashed} - \psline(C)(D)(D_1) - \psline(A)(D) - \psline(B)(D)(C_1) - \psline(D)(E) - \psset{linestyle=none,fillstyle=solid,fillcolor=gray} - \pspolygon(A)(D)(D_1)(A_1) - \pspolygon(B)(C_1)(D) -\end{pspicture} -\end{document} -\begin{frame}[label=timeline]{The journey\ldots} - \begin{tikzpicture} - \pause - \node[cloudy](spring2010){Spr... - \node[below=0mm of spring2010... - \pause - \node[cloudy,right=of spring20... - \node[below=0mm of summer2010... - \pause - \node[cloudy,right=of summer2... - \node[below=0mm of fall2010... - \end{tikzpicture} -\end{frame} diff --git a/Master/texmf-dist/doc/support/latexindent/documentation/manual.pdf b/Master/texmf-dist/doc/support/latexindent/documentation/manual.pdf Binary files differdeleted file mode 100644 index 0fec7c336b1..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/documentation/manual.pdf +++ /dev/null diff --git a/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex b/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex index 0edbbbd28e1..04053c027a9 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex @@ -1,18 +1,18 @@ % arara: indent: {overwrite: true, trace: yes, silent: yes} \matrix{% - % \begin{tabular} - & A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\\hline - A_1 & 0 & & & & & & & & \\ - A_2 & & 0 & & & & & & & \\ - A_3 & & & 0 & & & & & & \\ - A_4 & & & & 0 & & & & & \\ - A_5 & & & & & 0 & & & & \\ - A_6 & & & & & & 0 & & & \\ - A_7 & & & & & & & 0 & & \\ - A_8 & & & & & & & & 0 & \\ - A_9 & & & & & & & & & 0 \\ - %* \end{align} + %* \begin{tabular} + & A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\\hline + A_1 & 0 & & & & & & & & \\ + A_2 & & 0 & & & & & & & \\ + A_3 & & & 0 & & & & & & \\ + A_4 & & & & 0 & & & & & \\ + A_5 & & & & & 0 & & & & \\ + A_6 & & & & & & 0 & & & \\ + A_7 & & & & & & & 0 & & \\ + A_8 & & & & & & & & 0 & \\ + A_9 & & & & & & & & & 0 \\ + %* \end{tabular} } \begin{tabular} & A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\\hline diff --git a/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex b/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex index ac6b72d6be4..b389b436602 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex @@ -48,7 +48,7 @@ some other text \parbox{ \begin{something} - + \end{something} } diff --git a/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex b/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex new file mode 100644 index 00000000000..34cf9df16fb --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex @@ -0,0 +1,6 @@ +\cmh[ + here is some text +] +\cmh{ + here is some text +} diff --git a/Master/texmf-dist/doc/support/latexindent/success/environments.tex b/Master/texmf-dist/doc/support/latexindent/success/environments.tex index bf1d4d86c80..986474dca79 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/environments.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/environments.tex @@ -9,7 +9,7 @@ text \begin{align*} {\color{red}(3x^3+y)}(-4x^3+y) & = {\color{red}(3x^3+y)}(-4x^3)+{\color{red}(3x^3+y)}(y) \\ & = -12x^6-4x^3y+3x^3y+y^2 \\ - & = -12x^6-x^3y+y^2 + & = -12x^6-x^3y+y^2 \end{align*} \end{enumerate} \begin{enumerate} @@ -19,7 +19,7 @@ text \begin{align*} {\color{red}(3x^3+y)}(-4x^3+y) & = {\color{red}(3x^3+y)}(-4x^3)+{\color{red}(3x^3+y)}(y) \\ & = -12x^6-4x^3y+3x^3y+y^2 \\ - & = -12x^6-x^3y+y^2 + & = -12x^6-x^3y+y^2 \end{align*} \end{enumerate} diff --git a/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex b/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex new file mode 100644 index 00000000000..46e501ebaa0 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex @@ -0,0 +1,18 @@ +% arara: indent: {overwrite: true, trace: false, localSettings: yes} + +\documentclass{article} +\begin{filecontents}{mybib.bib} + \begin{document} + here is some text + \end{document} +\end{filecontents} + +\begin{document} +\begin{myotherenvironment} + some text goes here + some text goes here + some text goes here + some text goes here +\end{myotherenvironment} + +\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/filecontents2.tex b/Master/texmf-dist/doc/support/latexindent/success/filecontents2.tex new file mode 100644 index 00000000000..54307023361 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/filecontents2.tex @@ -0,0 +1,21 @@ +% arara: indent: {overwrite: true, trace: false, localSettings: yes} + +\documentclass{article} +\usepackage{verbatim} +\begin{filecontents}{mybib.bib} + \begin{document} + here is some text + \end{document} +\end{filecontents} + +\begin{document} + +\begin{verbatim} +\begin{filecontents}{mybib.bib} + \begin{document} + here is some text + \end{document} + \end{filecontents} +\end{verbatim} + +\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex b/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex new file mode 100644 index 00000000000..f4b4bad3e64 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex @@ -0,0 +1,10 @@ +\ifnum\radius>5 + \ifnum\radius<16 + \draw[decorate,decoration={crosses},orange!\pgfmathresult!black] (1,1) circle ( \radius ex-5ex); + \fi +\fi +\ifnum + 1 +\else + 2 +\fi diff --git a/Master/texmf-dist/doc/support/latexindent/success/items1.tex b/Master/texmf-dist/doc/support/latexindent/success/items1.tex new file mode 100644 index 00000000000..29be75d5fdc --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/items1.tex @@ -0,0 +1,10 @@ +\begin{itemize} + \item one + here is some text + here is some text + here is some text + \item two + here is some text + here is some text + here is some text +\end{itemize} diff --git a/Master/texmf-dist/doc/support/latexindent/success/items2.tex b/Master/texmf-dist/doc/support/latexindent/success/items2.tex new file mode 100644 index 00000000000..76d70b95729 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/items2.tex @@ -0,0 +1,21 @@ +\begin{enumerate} + \item one + here is some text + here is some text + here is some text + \item two + here is some text + here is some text + here is some text + \begin{itemize} + \item bullet + here is some text + here is some text + here is some text + \item bullet + here is some text + here is some text + here is some text + \end{itemize} + some text +\end{enumerate} diff --git a/Master/texmf-dist/doc/support/latexindent/success/items3.tex b/Master/texmf-dist/doc/support/latexindent/success/items3.tex new file mode 100644 index 00000000000..30460f40e72 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/items3.tex @@ -0,0 +1,22 @@ +\begin{myenv} + \begin{itemize} + \item one + here is some text + here is some text + here is some text + \item two + here is some text + here is some text + here is some text + \end{itemize} +\end{myenv} +\begin{itemize} +\item one + here is some text + here is some text + here is some text +\item two + here is some text + here is some text + here is some text +\end{itemize} diff --git a/Master/texmf-dist/doc/support/latexindent/success/items4.tex b/Master/texmf-dist/doc/support/latexindent/success/items4.tex new file mode 100644 index 00000000000..49383c47e1a --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/items4.tex @@ -0,0 +1,22 @@ +\begin{myenv} +\begin{itemize} +\item one + here is some text + here is some text + here is some text +\item two + here is some text + here is some text + here is some text +\end{itemize} +\end{myenv} +\begin{itemize} +\item one + here is some text + here is some text + here is some text +\item two + here is some text + here is some text + here is some text +\end{itemize} diff --git a/Master/texmf-dist/doc/support/latexindent/success/matrix.tex b/Master/texmf-dist/doc/support/latexindent/success/matrix.tex index 729a922b8d7..79c959e1ba2 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/matrix.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/matrix.tex @@ -9,6 +9,6 @@ & 2 & & & \fullmoon & & & & \\ {\color{blue}*} & 1 & & & & & {\color{blue}\newmoon} & & \\\hline & & 1 & 2 & 3 & 4 & 5 & 6 & \\ - \% & & {\color{red}*} & {\color{red}*} & & {\color{red}*} & & & + \% & & {\color{red}*} & {\color{red}*} & & {\color{red}*} & & & \end{matrix} \] diff --git a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex b/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex index 4bf214f2e4f..6578b4f4e00 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex @@ -9,7 +9,7 @@ \end{array} \right. \) - & Substitution {\em or }Addition & Because it is easy to solve for $x$ in the 1st equation + & Substitution {\em or }Addition & Because it is easy to solve for $x$ in the 1st equation {\em or} Because it is easy to multiply the first equation by -1 \\ \hline \( @@ -29,5 +29,5 @@ \end{array} \right. \) - & Substitution & Because the first equation can easily be solved for one of the variables + & Substitution & Because the first equation can easily be solved for one of the variables \end{tabular} diff --git a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex b/Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex index 0e6aa609a03..9a19ca8da43 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex @@ -5,7 +5,7 @@ \%\&\%\% & & \\ % & & 2x+y & =8 x+y & = & 6 \\ 2x+y & =8 - 2x+y \&\& & = & 8 % trailine comment + 2x+y \&\& & = & 8 % trailine comment \end{tabular} here's another line $\{ x^2 + 5x \}$ diff --git a/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex b/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex index 4d5506777d4..aac040a48c7 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex @@ -48,7 +48,7 @@ some other text \parbox{ \begin{something} - + \end{something} } diff --git a/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex b/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex index c9b38625713..b1f37474fe0 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex @@ -25,7 +25,7 @@ a \emph{decreasing} function. Similarly, if $a>0$ then $g$ is \emph{concave up} and if $a<0$ then $g$ is \emph{concave down}. Graphical representations of these statements are given in \cref{poly:fig:linquad}. - + \begin{figure}[!htb] \setlength{\figurewidth}{.2\textwidth} \begin{subfigure}{\figurewidth} @@ -94,18 +94,18 @@ \caption{Typical graphs of linear and quadratic functions.} \label{poly:fig:linquad} \end{figure} - + Let's look a little more closely at the formulas for $f$ and $g$ in \cref{poly:eq:linquad}. Note that the \emph{degree} of $f$ is $1$ since the highest power of $x$ that is present in the formula for $f(x)$ is $1$. Similarly, the degree of $g$ is $2$ since the highest power of $x$ that is present in the formula for $g(x)$ is $2$. - + In this section we will build upon our knowledge of these elementary functions. In particular, we will generalize the functions $f$ and $g$ to a function $p$ that has any degree that we wish. - + %=================================== % Author: Hughes % Date: March 2012 @@ -161,7 +161,7 @@ \end{subproblem} \end{problem} \end{essentialskills} - + \subsection*{Power functions with positive exponents} The study of polynomials will rely upon a good knowledge of power functions| you may reasonably ask, what is a power function? @@ -171,17 +171,17 @@ f(x) = a_n x^n \] where $n$ can be any real number. - + Note that for this section we will only be concerned with the case when $n$ is a positive integer. \end{pccdefinition} - + You may find assurance in the fact that you are already very comfortable with power functions that have $n=1$ (linear) and $n=2$ (quadratic). Let's explore some power functions that you might not be so familiar with. As you read \cref{poly:ex:oddpow,poly:ex:evenpow}, try and spot as many patterns and similarities as you can. - + %=================================== % Author: Hughes % Date: March 2012 @@ -199,12 +199,12 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} f(x)\rightarrow\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty \end{align*} The same results hold for $g$ and $h$. \end{pccsolution} \end{pccexample} - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture} @@ -254,7 +254,7 @@ \label{poly:fig:evenpow} \end{minipage}% \end{figure} - + %=================================== % Author: Hughes % Date: March 2012 @@ -271,12 +271,12 @@ of each of the functions is the same, and in particular \begin{align*} F(x)\rightarrow\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} F(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} F(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty \end{align*} The same result holds for $G$ and $H$. \end{pccsolution} \end{pccexample} - + \begin{doyouunderstand} \begin{problem} Repeat \cref{poly:ex:oddpow,poly:ex:evenpow} using (respectively) @@ -285,7 +285,7 @@ \begin{shortsolution} The functions $f$, $g$, and $h$ have domain $(-\infty,\infty)$ and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -303,11 +303,11 @@ \legend{$f$,$g$,$h$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} f(x)\rightarrow-\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty \end{align*} The same is true for $g$ and $h$. \end{shortsolution} @@ -317,7 +317,7 @@ \begin{shortsolution} The functions $F$, $G$, and $H$ have domain $(-\infty,\infty)$ and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -335,18 +335,18 @@ \legend{$F$,$G$,$H$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} F(x)\rightarrow-\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} F(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} F(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty \end{align*} The same is true for $G$ and $H$. \end{shortsolution} \end{subproblem} \end{problem} \end{doyouunderstand} - + \subsection*{Polynomial functions} Now that we have a little more familiarity with power functions, we can define polynomial functions. Provided that you were comfortable @@ -357,7 +357,7 @@ and quadratic functions. Once you've studied the examples and problems in this section, you'll hopefully agree that polynomial functions are remarkably predictable. - + %=================================== % Author: Hughes % Date: May 2011 @@ -376,11 +376,11 @@ \end{itemize} In particular, we call $a_n$ the \emph{leading} coefficient, and $a_nx^n$ the \emph{leading term}. - + Note that if a polynomial is given in factored form, then the degree can be found by counting the number of linear factors. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: March 2012 @@ -416,7 +416,7 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: March 2012 @@ -440,7 +440,7 @@ shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. \end{itemize} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -536,7 +536,7 @@ \caption{Graphs to illustrate typical curves of polynomial functions.} \label{poly:fig:typical} \end{figure} - + %=================================== % Author: Hughes % Date: March 2012 @@ -550,7 +550,7 @@ to guide you. \begin{shortsolution} $a_1<0$: - + \begin{tikzpicture} \begin{axis}[ framed, @@ -563,9 +563,9 @@ \addplot expression[domain=-10:8]{-(x+2)}; \end{axis} \end{tikzpicture} - + $a_2<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -578,9 +578,9 @@ \addplot expression[domain=-4:4]{-(x^2-6)}; \end{axis} \end{tikzpicture} - + $a_3<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -593,9 +593,9 @@ \addplot expression[domain=-7.5:7.5]{-0.05*(x+6)*x*(x-6)}; \end{axis} \end{tikzpicture} - + $a_4<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -608,9 +608,9 @@ \addplot expression[domain=-2.35:5.35,samples=100]{-0.2*(x-5)*x*(x-3)*(x+2)}; \end{axis} \end{tikzpicture} - + $a_5<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -626,11 +626,11 @@ \end{shortsolution} \end{problem} \end{doyouunderstand} - + \fixthis{poly: Need a more basic example here- it can have a similar format to the multiple zeros example, but just keep it simple; it should be halfway between the 2 examples surrounding it} - + %=================================== % Author: Hughes % Date: May 2011 @@ -642,24 +642,24 @@ \begin{align*} p(x) & =(x-3)^2(x+4)^2 \\ q(x) & =x(x+2)^2(x-1)^2(x-3) \\ - r(x) & =x(x-3)^3(x+1)^2 + r(x) & =x(x-3)^3(x+1)^2 \end{align*} Find the degree of $p$, $q$, and $r$, and decide if the functions bounce off or cut through the horizontal axis at each of their zeros. \begin{pccsolution} The degree of $p$ is 4. Referring to \cref{poly:fig:bouncep}, the curve bounces off the horizontal axis at both zeros, $3$ and $4$. - + The degree of $q$ is 6. Referring to \cref{poly:fig:bounceq}, the curve bounces off the horizontal axis at $-2$ and $1$, and cuts through the horizontal axis at $0$ and $3$. - + The degree of $r$ is 6. Referring to \cref{poly:fig:bouncer}, the curve bounces off the horizontal axis at $-1$, and cuts through the horizontal axis at $0$ and at $3$, although is flattened immediately to the left and right of $3$. \end{pccsolution} \end{pccexample} - + \setlength{\figurewidth}{0.25\textwidth} \begin{figure}[!htb] \begin{subfigure}{\figurewidth} @@ -712,7 +712,7 @@ \caption{} \label{poly:fig:moremultiple} \end{figure} - + \begin{pccdefinition}[Multiple zeros]\label{poly:def:multzero} Let $p$ be a polynomial that has a repeated linear factor $(x-a)^n$. Then we say that $p$ has a multiple zero at $a$ of multiplicity $n$ and @@ -724,7 +724,7 @@ \end{itemize} If $n=1$, then we say that $p$ has a \emph{simple} zero at $a$. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: May 2011 @@ -786,7 +786,7 @@ Let's check if the formula we have written satisfies this requirement \begin{align*} p(1) & = (1)(4)(2)(-1) \\ - & = -8 + & = -8 \end{align*} which is clearly not correct| it is close though. We can correct this by multiplying $p$ by a constant $k$; so let's assume that @@ -807,7 +807,7 @@ evaluate $p(2)$ \begin{align*} p(2) & =k(4)^2(-1) \\ - & =-16k + & =-16k \end{align*} We solve the equation $4=-8k$ and obtain $k=-\frac{1}{4}$ and conclude that the formula for $q(x)$ is @@ -817,8 +817,8 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - - + + \fixthis{Chris: need sketching polynomial problems} \begin{pccspecialcomment}[Steps to follow when sketching polynomial functions] \begin{steps} @@ -865,12 +865,12 @@ \item We draw the details we have obtained so far on \cref{poly:fig:simplecubicp1}. Given that the curve of $p$ looks like the curve of $x^3$ in the long-run, we are able to complete a sketch of the graph of $p$ in \cref{poly:fig:simplecubicp2}. - + Note that we can not find the coordinates of the local minimums, local maximums, and inflection points| for the moment we make reasonable guesses as to where these points are (you'll find how to do this in calculus). \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -909,7 +909,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -934,7 +934,7 @@ \item We mark the details we have found so far on \cref{poly:fig:degree5p1}. Given that the curve of $q$ looks like the curve of $-x^5$ in the long-run, we can complete \cref{poly:fig:degree5p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -973,7 +973,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -1000,7 +1000,7 @@ the curve of $r$ looks like the curve of $x^6$ in the long-run, we complete the graph of $r$ in \cref{poly:fig:degree6p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -1038,7 +1038,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: March 2012 @@ -1058,7 +1058,7 @@ $x$ represents the length of a side, and $V(x)$ represents the volume of the box, we necessarily require both values to be positive; we illustrate the part of the curve that applies to this problem using a solid line. - + \begin{figure}[!htb] \centering \begin{tikzpicture} @@ -1080,21 +1080,21 @@ \caption{$y=V(x)$} \label{poly:fig:opentoppedbox} \end{figure} - + According to \cref{poly:fig:opentoppedbox}, the maximum volume of such a box is approximately $\unit[4000]{cm^2}$, and we achieve it using a base of length approximately $\unit[20]{cm}$. Since the base is square and each sheet of cardboard is $\unit[1200]{cm^2}$, we conclude that the dimensions of each box are $\unit[20]{cm}\times\unit[20]{cm}\times\unit[30]{cm}$. \end{pccsolution} \end{pccexample} - + \subsection*{Complex zeros} There has been a pattern to all of the examples that we have seen so far| the degree of the polynomial has dictated the number of \emph{real} zeros that the polynomial has. For example, the function $p$ in \cref{poly:ex:simplecubic} has degree $3$, and $p$ has $3$ real zeros; the function $q$ in \cref{poly:ex:degree5} has degree $5$ and $q$ has $5$ real zeros. - + You may wonder if this result can be generalized| does every polynomial that has degree $n$ have $n$ real zeros? Before we tackle the general result, let's consider an example that may help motivate it. @@ -1113,7 +1113,7 @@ x^2+1=0 \end{equation} The solutions to \cref{poly:eq:complx} are $\pm i$. - + We conclude that $c$ has $3$ zeros: $0$ and $\pm i$; we note that \emph{not all of them are real}. \end{pccexample} @@ -1143,7 +1143,7 @@ We begin by factoring $p$ \begin{align*} p(x) & =x^4-2x^3+5x^2 \\ - & =x^2(x^2-2x+5) + & =x^2(x^2-2x+5) \end{align*} We note that $0$ is a zero of $p$ with multiplicity $2$. The other zeros of $p$ can be found by solving the equation @@ -1154,7 +1154,7 @@ \begin{align*} x & =\frac{2\pm\sqrt{(-2)^2}-20}{2(1)} \\ & =\frac{2\pm\sqrt{-16}}{2} \\ - & =1\pm 2i + & =1\pm 2i \end{align*} We conclude that $p$ has $4$ zeros: $0$ (multiplicity $2$), and $1\pm 2i$ (simple). \end{pccsolution} @@ -1169,13 +1169,13 @@ We know that the zeros of a polynomial can be found by analyzing the linear factors. We are given the zeros, and have to work backwards to find the linear factors. - + We begin by assuming that $p$ has the form \begin{align*} p(x) & =(x-(2-i\sqrt{2}))(x-(2+i\sqrt{2})) \\ & =x^2-x(2+i\sqrt{2})-x(2-i\sqrt{2})+(2-i\sqrt{2})(2+i\sqrt{2}) \\ & =x^2-4x+(4-2i^2) \\ - & =x^2-4x+6 + & =x^2-4x+6 \end{align*} We conclude that a possible formula for a polynomial function, $p$, that has zeros at $2\pm i\sqrt{2}$ is @@ -1235,8 +1235,8 @@ \end{enumerate} \end{shortsolution} \end{problem} - - + + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -1287,10 +1287,10 @@ \caption{} \label{poly:fig:findformula} \end{figure} - - - - + + + + \begin{exercises} %=================================== % Author: Hughes @@ -1459,14 +1459,14 @@ \begin{align*} p(x) & = (x-1)(x+2)(x-3) \\ m(x) & = -(x-1)(x+2)(x-3) \\ - n(x) & = (x-1)(x+2)(x-3)(x+1)(x+4) + n(x) & = (x-1)(x+2)(x-3)(x+1)(x+4) \end{align*} Note that for our present purposes we are not concerned with the vertical scale of the graphs. \begin{subproblem} Identify both on the graph {\em and} algebraically, the zeros of each polynomial. \begin{shortsolution} $y=p(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1477,9 +1477,9 @@ \addplot[soldot] coordinates{(-2,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + $y=m(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1490,9 +1490,9 @@ \addplot[soldot] coordinates{(-2,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + $y=n(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1503,7 +1503,7 @@ \addplot[soldot] coordinates{(-4,0)(-2,0)(-1,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + The zeros of $p$ are $-2$, $1$, and $3$; the zeros of $m$ are $-2$, $1$, and $3$; the zeros of $n$ are $-4$, $-2$, $-1$, and $3$. \end{shortsolution} @@ -1520,7 +1520,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -1773,7 +1773,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -1792,7 +1792,7 @@ $\dd\lim_{x\rightarrow\infty}s(x)=\infty$, \end{shortsolution} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -1917,7 +1917,7 @@ is positive. \begin{shortsolution} Assuming that $a_3>0$: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1937,7 +1937,7 @@ is negative. \begin{shortsolution} Assuming that $a_3<0$: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1961,7 +1961,7 @@ coefficient of $q$ is positive. Hint: only one of the zeros is simple. \begin{shortsolution} Assuming that $a_4>0$ there are $2$ different options: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1982,7 +1982,7 @@ coefficient of $q$ is negative. \begin{shortsolution} Assuming that $a_4<0$ there are $2$ different options: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -2194,7 +2194,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -2238,7 +2238,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -2290,7 +2290,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2298,7 +2298,7 @@ \begin{problem}[Find a formula from a table]\label{poly:prob:findformula} \Crefrange{poly:tab:findformulap}{poly:tab:findformulas} show values of polynomial functions, $p$, $q$, $r$, and $s$. - + \begin{table}[!htb] \centering \begin{widepage} @@ -2382,7 +2382,7 @@ \end{subtable} \end{widepage} \end{table} - + \begin{subproblem} Assuming that all of the zeros of $p$ are shown (in \cref{poly:tab:findformulap}), how many zeros does $p$ have? \begin{shortsolution} @@ -2433,7 +2433,7 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Rational functions} \subsection*{Power functions with negative exponents} The study of rational functions will rely upon a good knowledge @@ -2455,21 +2455,21 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} f(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \end{align*} The same results hold for $g$ and $h$. Note also that each of the functions has a \emph{vertical asymptote} at $0$. We see that \begin{align*} f(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} f(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} f(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ \end{align*} The same results hold for $g$ and $h$. - + The curve of a function that has a vertical asymptote is necessarily separated into \emph{branches}| each of the functions $f$, $g$, and $h$ have $2$ branches. \end{pccsolution} \end{pccexample} - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture} @@ -2525,8 +2525,8 @@ \label{rat:fig:evenpow} \end{minipage}% \end{figure} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -2543,7 +2543,7 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} F(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \end{align*} As in \cref{rat:ex:oddpow}, $F$ has a horizontal asymptote that has equation $y=0$. @@ -2551,7 +2551,7 @@ has a \emph{vertical asymptote} at $0$. We see that \begin{align*} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ \end{align*} The same results hold for $G$ and $H$. Each of the functions $F$, $G$, and $H$ have $2$ branches. @@ -2569,7 +2569,7 @@ \begin{shortsolution} The functions $k$, $m$, and $n$ have domain $(-\infty,0)\cup (0,\infty)$, and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -2590,14 +2590,14 @@ \legend{$k$,$m$,$n$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} k(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ \mathllap{\text{and }} k(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \\ \intertext{and also} k(x)\rightarrow \infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} k(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} k(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ \end{align*} The same are true for $m$ and $n$. \end{shortsolution} @@ -2607,7 +2607,7 @@ \begin{shortsolution} The functions $K$, $M$, and $N$ have domain $(-\infty,0)\cup (0,\infty)$, and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -2628,21 +2628,21 @@ \legend{$K$,$M$,$N$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} K(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ \mathllap{\text{and }} K(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \\ \intertext{and also} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ \end{align*} The same are true for $M$ and $N$. \end{shortsolution} \end{subproblem} \end{problem} \end{doyouunderstand} - + \subsection*{Rational functions} \begin{pccdefinition}[Rational functions]\label{rat:def:function} Rational functions have the form @@ -2650,7 +2650,7 @@ r(x) = \frac{p(x)}{q(x)} \] where both $p$ and $q$ are polynomials. - + Note that \begin{itemize} \item the domain or $r$ will be all real numbers, except those that @@ -2658,13 +2658,13 @@ \item the zeros of $r$ are the zeros of $p$, i.e the real numbers that make the \emph{numerator}, $p(x)$, equal to $0$. \end{itemize} - + \Cref{rat:ex:oddpow,rat:ex:evenpow} are particularly important because $r$ will behave like $\frac{1}{x}$, or $\frac{1}{x^2}$ around its vertical asymptotes, depending on the power that the relevant term is raised to| we will demonstrate this in what follows. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2699,7 +2699,7 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2779,7 +2779,7 @@ \caption{} \label{rat:fig:whichiswhich} \end{figure} - + \begin{pccsolution} Let's start with the function $r$. Note that domain of $r$ is $(-\infty,3)\cup(0,3)$, so we search for a function that has a vertical asymptote at $3$. There @@ -2787,18 +2787,18 @@ but note that the function in \cref{rat:fig:which3} also has a vertical asymptote at $-2$ which is not consistent with the formula for $r(x)$. Therefore, $y=r(x)$ is graphed in \cref{rat:fig:which2}. - + The function $q$ has domain $(-\infty,-5)\cup(-5,\infty)$, so we search for a function that has a vertical asymptote at $-5$. The only candidate is the curve shown in \cref{rat:fig:which1}; note that the curve also goes through $(2,0)$, which is consistent with the formula for $q(x)$, since $q(2)=0$, i.e $q$ has a zero at $2$. - + The function $k$ has domain $(-\infty,-2)\cup(-2,3)\cup(3,\infty)$, and has vertical asymptotes at $-2$ and $3$. This is consistent with the graph in \cref{rat:fig:which3} (and is the only curve that has $3$ branches). - + We note that each function behaves like $\frac{1}{x}$ around its vertical asymptotes, because each linear factor in each denominator is raised to the power $1$; if (for example) the definition of $r$ was instead @@ -2809,7 +2809,7 @@ the graph of $r$ would be very different. We will deal with these cases in the examples that follow. \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2827,7 +2827,7 @@ so we are not surprised to see that each curve has $3$ branches. We also note that the numerator of each function is the same, which tells us that each function has only $1$ zero at $2$. - + The functions $g$ and $h$ are different from those that we have considered previously, because they have a repeated factor in the denominator. Notice in particular the way that the functions behave around their asymptotes: @@ -2910,7 +2910,7 @@ \caption{} \label{rat:fig:repfactd} \end{figure} - + \Cref{rat:def:function} says that the zeros of the rational function $r$ that has formula $r(x)=\frac{p(x)}{q(x)}$ are the zeros of $p$. Let's explore this a little more. @@ -2929,9 +2929,9 @@ x+5=0 \] The zero of $\alpha$ is $-5$. - + Similarly, we may solve $9-x=0$ to find the zero of $\beta$, which is clearly $9$. - + The zeros of $\gamma$ satisfy the equation \[ 17x^2-10=0 @@ -2943,7 +2943,7 @@ The zeros of $\gamma$ are $\pm\frac{10}{17}$. \end{pccsolution} \end{pccexample} - + \subsection*{Long-run behavior} Our focus so far has been on the behavior of rational functions around their \emph{vertical} asymptotes. In fact, rational functions also @@ -2966,7 +2966,7 @@ \end{pccdefinition} We will concentrate on functions that have horizontal asymptotes until we reach \cref{rat:sec:oblique}. - + %=================================== % Author: Hughes % Date: May 2012 @@ -2979,7 +2979,7 @@ and obtained the curves shown in \cref{rat:fig:horizasymp}. Kebede decides to test his knowledgeable friend \pccname{Oscar}, and asks him to match the formulas to the graphs. - + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -3050,7 +3050,7 @@ \caption{Horizontal asymptotes} \label{rat:fig:horizasymp} \end{figure} - + Oscar notices that each function has a vertical asymptote at $3$ and a zero at $-1$. The main thing that catches Oscar's eye is that each function has a different coefficient in the numerator, and that each curve has a different horizontal asymptote. @@ -3064,14 +3064,14 @@ that since the degree of the numerator and the degree of the denominator is the same for each of the functions $r$, $s$, and $t$, the horizontal asymptote will be determined by evaluating the ratio of their leading coefficients. - + Oscar therefore says that $r$ should have a horizontal asymptote $y=\frac{1}{1}=1$, $s$ should have a horizontal asymptote $y=\frac{2}{1}=2$, and $t$ should have a horizontal asymptote $y=\frac{3}{1}=3$. Kebede is able to finish the problem from here, and says that $r$ is shown in \cref{rat:fig:horizasymp2}, $s$ is shown in \cref{rat:fig:horizasymp1}, and $t$ is shown in \cref{rat:fig:horizasymp3}. \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -3080,7 +3080,7 @@ \pccname{Xiao} and \pccname{Dwayne} saw \cref{rat:ex:horizasymp} but are a little confused about horizontal asymptotes. What does it mean to say that a function $r$ has a horizontal asymptote? - + They decide to explore the concept by constructing a table of values for the rational functions $R$ and $S$ that have formulas \[ @@ -3119,13 +3119,13 @@ \end{tabular} \end{minipage} \end{table} - + Xiao and Dwayne study \cref{rat:tab:plusinfty,rat:tab:minusinfty} and decide that the functions $R$ and $S$ never actually touch their horizontal asymptotes, but they do get infinitely close. They also feel as if they have a better understanding of what it means to study the behavior of a function as $x\rightarrow\pm\infty$. \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3142,7 +3142,7 @@ \] We also notice that the numerators of each function are quite similar| indeed, each function has a zero at $2$, but how does each function behave around their zero? - + Using \cref{rat:fig:repfactn} to guide us, we note that \begin{itemize} \item $f$ has a horizontal intercept $(2,0)$, but the curve of @@ -3152,7 +3152,7 @@ \item $h$ has a horizontal intercept $(2,0)$, and the curve of $h$ also cuts the axis, but appears flattened as it does so. \end{itemize} - + We can further enrich our study by discussing the long-run behavior of each function. Using the tools of \cref{rat:def:longrun}, we can deduce that \begin{itemize} @@ -3162,7 +3162,7 @@ study this more in \cref{rat:sec:oblique}). \end{itemize} \end{pccexample} - + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -3235,7 +3235,7 @@ \caption{} \label{rat:fig:repfactn} \end{figure} - + \subsection*{Holes} Rational functions have a vertical asymptote at $a$ if the denominator is $0$ at $a$. What happens if the numerator is $0$ at the same place? In this case, we say that the rational @@ -3250,7 +3250,7 @@ $(a,r(a))$ on the curve $y=r(x)$ by using a hollow circle, $\circ$. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: March 2012 @@ -3262,12 +3262,12 @@ \] in their calculators, and can not decide if the correct graph is \cref{rat:fig:hole} or \cref{rat:fig:hole1}. - + Luckily for them, Oscar is nearby, and can help them settle the debate. Oscar demonstrates that \begin{align*} r(x) & =\frac{(x+3)(x-2)}{(x-2)} \\ - & = x+3 + & = x+3 \end{align*} but only when $x\ne 2$, because the function is undefined at $2$. Oscar says that this necessarily means that the domain or $r$ is @@ -3275,7 +3275,7 @@ (-\infty,2)\cup(2,\infty) \] and that $r$ must have a hole at $2$. - + Mohammed and Sue are very grateful for the clarification, and conclude that the graph of $r$ is shown in \cref{rat:fig:hole1}. \begin{figure}[!htb] @@ -3319,7 +3319,7 @@ \end{minipage}% \end{figure} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3333,12 +3333,12 @@ make the denominator equal to $0$. Notice that \begin{align*} f(x) & = \frac{x(x+3)}{x(x-4)} \\ - & = \frac{x+3}{x-4} + & = \frac{x+3}{x-4} \end{align*} provided that $x\ne 0$. Since $0$ makes the numerator and the denominator 0 at the same time, we say that $f$ has a hole at $(0,-\nicefrac{3}{4})$. Note that this necessarily means that $f$ does not have a vertical intercept. - + We also note $f$ has a vertical asymptote at $4$; the function is graphed in \cref{rat:fig:holeex}. \begin{figure}[!htb] \centering @@ -3362,9 +3362,9 @@ \label{rat:fig:holeex} \end{figure} \end{pccexample} - - - + + + %=================================== % Author: Hughes % Date: March 2012 @@ -3374,7 +3374,7 @@ if a rational function has a vertical asymptote, then it can not possibly have local minimums and maximums, nor can it have global minimums and maximums. - + Trang says this statement is not always true. She plots the functions $f$ and $g$ that have formulas \[ @@ -3383,7 +3383,7 @@ in \cref{rat:fig:minmax1,rat:fig:minmax2} and shows them to Seamus. On seeing the graphs, Seamus quickly corrects himself, and says that $f$ has a local (and global) maximum of $2$ at $0$, and that $g$ has a local (and global) minimum of $-2$ at $0$. - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture}[/pgf/declare function={f=-32*(x-1)*(x+1)/(( x-2)^2*(x+2)^2);}] @@ -3427,19 +3427,19 @@ \label{rat:fig:minmax2} \end{minipage}% \end{figure} - + Seamus also notes that (in its domain) the function $f$ is always concave down, and that (in its domain) the function $g$ is always concave up. Furthermore, Trang observes that each function behaves like $\frac{1}{x^2}$ around each of its vertical asymptotes, because each linear factor in the denominator is raised to the power $2$. - + \pccname{Oscar} stops by and reminds both students about the long-run behavior; according to \cref{rat:def:longrun} since the degree of the denominator is greater than the degree of the numerator (in both functions), each function has a horizontal asymptote at $y=0$. \end{pccexample} - - + + \investigation*{} %=================================== % Author: Pettit/Hughes @@ -3448,12 +3448,12 @@ \begin{problem}[The spaghetti incident] The same Queen from \vref{exp:prob:queenschessboard} has recovered from the rice experiments, and has called her loyal jester for another challenge. - + The jester has an $11-$inch piece of uncooked spaghetti that he puts on a table; he uses a book to cover $\unit[1]{inch}$ of it so that $\unit[10]{inches}$ hang over the edge. The jester then produces a box of $\unit{mg}$ weights that can be hung from the spaghetti. - + The jester says it will take $\unit[y]{mg}$ to break the spaghetti when hung $\unit[x]{inches}$ from the edge, according to the rule $y=\frac{100}{x}$. \begin{margintable} @@ -3537,7 +3537,7 @@ note that this necessarily means that you will not be able to plot all of the points. \begin{shortsolution} The graph of $y=\frac{100}{x}$ is shown below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -3567,9 +3567,9 @@ \end{subproblem} The Queen looks forward to more food-related investigations from her jester. \end{problem} - - - + + + %=================================== % Author: Adams (Hughes) % Date: March 2012 @@ -3593,17 +3593,17 @@ Paying off the debt in $2$ years, we use \begin{align*} M & = \frac{2000\cdot 0.015}{1-(1+0.015)^{-24}} \\ - & \approx 99.85 + & \approx 99.85 \end{align*} The monthly payments are \$99.85. - + Paying off the debt in $1$ year, we use \begin{align*} M & = \frac{2000\cdot 0.015}{1-(1+0.015)^{-12}} \\ - & \approx 183.36 + & \approx 183.36 \end{align*} The monthly payments are \$183.36 - + In the $2$-year model we would pay a total of $\$99.85\cdot 12=\$2396.40$. In the $1$-year model we would pay a total of $\$183.36\cdot 12=\$2200.32$. We would therefore save $\$196.08$ if we went with the $1$-year model instead of the $2$-year model. @@ -3619,20 +3619,20 @@ For the $20$-year loan we use \begin{align*} M & = \frac{300000\cdot \frac{0.052}{12}}{1-\left( 1+\frac{0.052}{12} \right)^{-12\cdot 20}} \\ - & \approx 2013.16 + & \approx 2013.16 \end{align*} The monthly payments are \$2013.16. - + For the $30$-year loan we use \begin{align*} M & = \frac{300000\cdot \frac{0.052}{12}}{1-\left( 1+\frac{0.052}{12} \right)^{-12\cdot 30}} \\ - & \approx 1647.33 + & \approx 1647.33 \end{align*} The monthly payments are \$1647.33. - + The total amount paid during the $20$-year loan is $\$2013.16\cdot 12\cdot 20=\$483,158.40$. The total amount paid during the $30$-year loan is $\$1647.33\cdot 12\cdot 30=\$593,038.80$. - + Recommendation: if you can afford the payments, choose the $20$-year loan. \end{shortsolution} \end{subproblem} @@ -3662,7 +3662,7 @@ This means that the monthly payments will be calculated using \begin{align*} M & = \frac{14000\cdot \frac{0.04}{12}}{1-\left( 1+\frac{0.04}{12} \right)^{-12\cdot 5}} \\ - & \approx 257.83 + & \approx 257.83 \end{align*} The monthly payments will be $\$257.83$. The total amount paid will be $\$257.83\cdot 5\cdot 12=\$15,469.80$, of which $\$1469.80$ is interest. @@ -3670,7 +3670,7 @@ This means that the monthly payments will be calculated using \begin{align*} M & = \frac{12000\cdot \frac{0.08}{12}}{1-\left( 1+\frac{0.08}{12} \right)^{-12\cdot 5}} \\ - & \approx 243.32 + & \approx 243.32 \end{align*} The monthly payments will be $\$243.32$. The total amount paid will be $\$243.32\cdot 5\cdot 12 =\$14,599.20$, of which $\$2599.2$ is @@ -3681,7 +3681,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + \begin{exercises} %=================================== % Author: Hughes @@ -3783,7 +3783,7 @@ $\begin{aligned}[t] r(0) & =\frac{(0-2)(0+3)}{(0+5)(0-7)} \\ & =\frac{-6}{-35} \\ - & =\frac{6}{35} + & =\frac{6}{35} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3793,7 +3793,7 @@ $\begin{aligned}[t] r(1) & =\frac{(1-2)(1+3)}{(1+5)(1-7)} \\ & =\frac{-4}{-36} \\ - & =\frac{1}{9} + & =\frac{1}{9} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3803,7 +3803,7 @@ $\begin{aligned}[t] r(2) & =\frac{(2-2)(2+3)}{(2+5)(2-7)} \\ & = \frac{0}{-50} \\ - & =0 + & =0 \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3813,7 +3813,7 @@ $\begin{aligned}[t] r(4) & =\frac{(4-2)(4+3)}{(4+5)(4-7)} \\ & =\frac{14}{-27} \\ - & =-\frac{14}{27} + & =-\frac{14}{27} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3822,9 +3822,9 @@ \begin{shortsolution} $\begin{aligned}[t] r(7) & =\frac{(7-2)(7+3)}{(7+5)(7-7)} \\ - & =\frac{50}{0} + & =\frac{50}{0} \end{aligned}$ - + $r(7)$ is undefined. \end{shortsolution} \end{subproblem} @@ -3834,7 +3834,7 @@ $\begin{aligned}[t] r(-3) & =\frac{(-3-2)(-3+3)}{(-3+5)(-3-7)} \\ & =\frac{0}{-20} \\ - & =0 + & =0 \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3843,9 +3843,9 @@ \begin{shortsolution} $\begin{aligned}[t] r(-5) & =\frac{(-5-2)(-5+3)}{(-5+5)(-5-7)} \\ - & =\frac{14}{0} + & =\frac{14}{0} \end{aligned}$ - + $r(-5)$ is undefined. \end{shortsolution} \end{subproblem} @@ -3856,7 +3856,7 @@ r\left( \frac{1}{2} \right) & = \frac{\left( \frac{1}{2}-2 \right)\left( \frac{1}{2}+3 \right)}{\left( \frac{1}{2}+5 \right)\left( \frac{1}{2}-7 \right)} \\ & =\frac{-\frac{3}{2}\cdot\frac{7}{2}}{\frac{11}{2}\left( -\frac{13}{2} \right)} \\ & =\frac{-\frac{21}{4}}{-\frac{143}{4}} \\ - & =\frac{37}{143} + & =\frac{37}{143} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3908,7 +3908,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3925,7 +3925,7 @@ \end{itemize} \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -3997,7 +3997,7 @@ \label{rat:fig:findformula} \end{widepage} \end{figure} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4034,7 +4034,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4099,7 +4099,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2012 @@ -4181,7 +4181,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4212,7 +4212,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: Feb 2011 @@ -4265,8 +4265,8 @@ \end{shortsolution} \end{subproblem} \end{problem} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -4309,7 +4309,7 @@ Sketch a graph of $r$. \begin{shortsolution} A graph of $r$ is shown below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -4329,7 +4329,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -4367,8 +4367,8 @@ \end{subproblem} \end{multicols} \end{problem} - - + + %=================================== % Author: Hughes % Date: July 2012 @@ -4419,8 +4419,8 @@ \end{subproblem} \end{multicols} \end{problem} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -4428,7 +4428,7 @@ \begin{problem}[Find a formula from a table]\label{rat:prob:findformula} \Crefrange{rat:tab:findformular}{rat:tab:findformulau} show values of rational functions $r$, $q$, $s$, and $t$. Assume that any values marked with an X are undefined. - + \begin{table}[!htb] \begin{widepage} \centering @@ -4525,7 +4525,7 @@ r(-4) & = \frac{-4-3}{-4+2} \\ & = \frac{7}{2} \\ \end{aligned}$ - + $r(-3)=\ldots$ etc \end{shortsolution} \end{subproblem} @@ -4541,9 +4541,9 @@ \begin{shortsolution} $\begin{aligned}[t] s(-4) & =\frac{-4+2}{(-4-3)(-4+1)} \\ - & =-\frac{2}{21} + & =-\frac{2}{21} \end{aligned}$ - + $s(-3)=\ldots$ etc \end{shortsolution} \end{subproblem} @@ -4563,13 +4563,13 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Graphing rational functions (horizontal asymptotes)} \reformatstepslist{R} % the steps list should be R1, R2, \ldots We studied rational functions in the previous section, but were not asked to graph them; in this section we will demonstrate the steps to be followed in order to sketch graphs of the functions. - + Remember from \vref{rat:def:function} that rational functions have the form \[ @@ -4583,7 +4583,7 @@ in this section \emph{will have a horizontal asymptote} (see \vref{rat:def:longrun}). The cases in which the degree of $p$ is greater than the degree of $q$ is covered in the next section. - + Before we begin, it is important to remember the following: \begin{itemize} \item Our sketches will give a good representation of the overall @@ -4612,10 +4612,10 @@ find the exact coordinates of local minimums, local maximums, and points of inflection. \end{pccspecialcomment} - + The examples that follow show how \crefrange{rat:step:first}{rat:step:last} can be applied to a variety of different rational functions. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4641,7 +4641,7 @@ \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4678,14 +4678,14 @@ \end{subfigure}% \caption{$y=\dfrac{1}{x-2}$} \end{figure} - + The function $r$ in \cref{rat:ex:1overxminus2p2} has a horizontal asymptote which has equation $y=0$. This asymptote lies on the horizontal axis, and you might (understandably) find it hard to distinguish between the two lines (\cref{rat:fig:1overxminus2p2}). When faced with such a situation, it is perfectly acceptable to draw the horizontal axis as a dashed line| just make sure to label it correctly. We will demonstrate this in the next example. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4711,12 +4711,12 @@ is, because we know what the overall shape will be. Let's compute $v(2)$ \begin{align*} v(2) & =\dfrac{10}{2} \\ - & = 5 + & = 5 \end{align*} We therefore mark the point $(2,5)$ on \cref{rat:fig:1overxp2}, and then complete the sketch using the details we found in the previous steps. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4760,7 +4760,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -4778,7 +4778,7 @@ \begin{align*} u(x) & =\frac{-4(x^2-9)}{x^2-8x+15} \\ & =\frac{-4(x+3)(x-3)}{(x-5)(x-3)} \\ - & =\frac{-4(x+3)}{x-5} + & =\frac{-4(x+3)}{x-5} \end{align*} provided that $x\ne 3$. Therefore $u$ has a vertical asymptote at $5$ and a hole at $3$. The curve of $u$ has $2$ branches. @@ -4788,7 +4788,7 @@ \item We put the details we have obtained so far on \cref{rat:fig:1overxminus2p1}. Notice that there is only one way to complete the graph, which we have done in \cref{rat:fig:1overxminus2p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4833,12 +4833,12 @@ \end{figure} \end{pccsolution} \end{pccexample} - + \Cref{rat:ex:1overxminus2p2,rat:ex:1overxp1,rat:ex:asympandholep1} have focused on functions that only have one vertical asymptote; the remaining examples in this section concern functions that have more than one vertical asymptote. We will demonstrate that \crefrange{rat:step:first}{rat:step:last} still apply. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4862,20 +4862,20 @@ of the numerator and denominator, we say that $w$ has a horizontal asymptote with equation $y=\frac{2}{1}=2$. \item We put the details we have obtained so far on \cref{rat:fig:sketchtwoasymptp1}. - + The function $w$ is a little more complicated than the functions that we have considered in the previous examples because the curve has $3$ branches. When graphing such functions, it is generally a good idea to start with the branch for which you have the most information| in this case, that is the \emph{middle} branch on the interval $(-5,4)$. - + Once we have drawn the middle branch, there is only one way to complete the graph (because of our observations about the behavior of $w$ around its vertical asymptotes), which we have done in \cref{rat:fig:sketchtwoasymptp2}. \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4921,12 +4921,12 @@ \end{subfigure}% \caption{$y=\dfrac{2(x+3)(x-5)}{(x+5)(x-4)}$} \end{figure} - + The rational functions that we have considered so far have had simple factors in the denominator; each function has behaved like $\frac{1}{x}$ around each of its vertical asymptotes. \Cref{rat:ex:2asympnozeros,rat:ex:2squaredasymp} consider functions that have a repeated factor in the denominator. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4949,17 +4949,17 @@ denominator of $f$ is $2$. $f$ has a horizontal asymptote with equation $y=0$. \item We put the details we have obtained so far on \cref{rat:fig:2asympnozerosp1}. - + The function $f$ is similar to the function $w$ that we considered in \cref{rat:ex:sketchtwoasymp}| it has two vertical asymptotes and $3$ branches, but in contrast to $w$ it does not have any zeros. - + We sketch $f$ in \cref{rat:fig:2asympnozerosp2}, using the middle branch as our guide because we have the most information about the function on the interval $(-5,4)$. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $f$ around its vertical asymptotes (it behaves like $\frac{1}{x}$), which we have done in \cref{rat:fig:2asympnozerosp2}. - + Note that we are not yet able to find the local minimum of $f$ algebraically on the interval $(-5,4)$, so we make a reasonable guess as to where it is| we can be confident that it is above the horizontal axis since $f$ has no zeros. You may think that this is unsatisfactory, but once we have the tools of calculus, we will @@ -4967,7 +4967,7 @@ \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5011,7 +5011,7 @@ \end{subfigure}% \caption{$y=\dfrac{100}{(x+5)(x-4)^2}$} \end{figure} - + %=================================== % Author: Hughes % Date: May 2012 @@ -5037,19 +5037,19 @@ \cref{rat:fig:2squaredasymp1}. The function $g$ is similar to the functions we considered in \cref{rat:ex:sketchtwoasymp,rat:ex:2asympnozeros} because it has $2$ vertical asymptotes and $3$ branches. - + We sketch $g$ using the middle branch as our guide because we have the most information about $g$ on the interval $(-3,5)$. Note that there is no other way to draw this branch without introducing other zeros which $g$ does not have. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $g$ around its vertical asymptotes| it behaves like $\frac{1}{x^2}$. - + \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5093,14 +5093,14 @@ \end{subfigure}% \caption{$y=\dfrac{50(2-x)}{(x+3)^2(x-5)^2}$} \end{figure} - + Each of the rational functions that we have considered so far has had either a \emph{simple} zero, or no zeros at all. Remember from our work on polynomial functions, and particularly \vref{poly:def:multzero}, that a \emph{repeated} zero corresponds to the curve of the function behaving differently at the zero when compared to how the curve behaves at a simple zero. \Cref{rat:ex:doublezero} details a function that has a non-simple zero. - + %=================================== % Author: Hughes % Date: June 2012 @@ -5127,20 +5127,20 @@ \cref{rat:fig:doublezerop1}. The function $h$ is different from the functions that we have considered in previous examples because of the multiplicity of the zero at $3$. - + We sketch $h$ using the middle branch as our guide because we have the most information about $h$ on the interval $(-4,6)$. Note that there is no other way to draw this branch without introducing other zeros which $h$ does not have| also note how the curve bounces off the horizontal axis at $3$. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $h$ around its vertical asymptotes| it behaves like $\frac{1}{x}$. - + \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5199,7 +5199,7 @@ at $b$, and a vertical asymptote at $c$. Furthermore, these functions behave like $\frac{1}{x}$ around their vertical asymptote, and the curve of each function will have $2$ branches. - + Katie has been working with $3$ functions that have the form given in \cref{rat:eq:deducecurve}, and has followed \crefrange{rat:step:first}{rat:step:penultimate}; her results are shown in \cref{rat:fig:deducecurve}. There is just one @@ -5207,7 +5207,7 @@ Help Katie finish each graph by deducing the curve of each function. \begin{shortsolution} \Vref{rat:fig:deducecurve1} - + \begin{tikzpicture}[/pgf/declare function={f=3*(x+4)/(x+5);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5222,9 +5222,9 @@ \addplot[pccplot] expression[domain=-4.76923:10,samples=50]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducecurve2} - + \begin{tikzpicture}[/pgf/declare function={f=-3*(x-2)/(x-4);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5239,9 +5239,9 @@ \addplot[pccplot] expression[domain=4.85714:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducecurve4} - + \begin{tikzpicture}[/pgf/declare function={f=2*(x-6)/(x-4);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5258,7 +5258,7 @@ \end{tikzpicture} \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -5316,7 +5316,7 @@ \label{rat:fig:deducecurve} \end{widepage} \end{figure} - + %=================================== % Author: Hughes % Date: June 2012 @@ -5331,13 +5331,13 @@ at $b$ and $c$, and vertical asymptotes at $d$ and $e$. Furthermore, these functions behave like $\frac{1}{x}$ around both vertical asymptotes, and the curve of the function will have $3$ branches. - + David has followed \crefrange{rat:step:first}{rat:step:penultimate} for $3$ separate functions, and drawn the results in \cref{rat:fig:deducehard}. Help David finish each graph by deducing the curve of each function. \begin{shortsolution} \Vref{rat:fig:deducehard1} - + \begin{tikzpicture}[/pgf/declare function={f=(x-6)*(x+3)/( (x-4)*(x+1));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5354,9 +5354,9 @@ \addplot[pccplot] expression[domain=4.24276:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducehard2} - + \begin{tikzpicture}[/pgf/declare function={f=3*(x-2)*(x+3)/( (x-6)*(x+5));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5373,9 +5373,9 @@ \addplot[pccplot] expression[domain=7.34324:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducehard3} - + \begin{tikzpicture}[/pgf/declare function={f=2*(x-7)*(x+3)/( (x+6)*(x-5));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5392,10 +5392,10 @@ \addplot[pccplot] expression[domain=5.25586:10]{f}; \end{axis} \end{tikzpicture} - + \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -5470,7 +5470,7 @@ $y=\dfrac{4}{x+2}$ \begin{shortsolution} Vertical intercept: $(0,2)$; vertical asymptote: $x=-2$, horizontal asymptote: $y=0$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5494,7 +5494,7 @@ Vertical intercept:$\left( 0,\frac{1}{9} \right)$; horizontal intercept: $\left( \frac{1}{2},0 \right)$; vertical asymptotes: $x=-3$, $x=3$, horizontal asymptote: $y=0$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5519,7 +5519,7 @@ \begin{shortsolution} Vertical intercept $\left( 0,-\frac{3}{5} \right)$; horizontal intercept: $(-3,0)$; vertical asymptote: $x=5$; horizontal asymptote: $y=1$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5544,7 +5544,7 @@ \begin{shortsolution} Vertical intercept: $(0,-3)$; horizontal intercept: $\left( -\frac{3}{2},0 \right)$; vertical asymptote: $x=\frac{1}{3}$, horizontal asymptote: $y=\frac{2}{3}$. - + \begin{tikzpicture}[/pgf/declare function={f=(2*x+3)/(3*x-1);}] \begin{axis}[ framed, @@ -5568,7 +5568,7 @@ Vertical intercept: $\left( 0,-\frac{4}{9} \right)$; horizontal intercepts: $(2,0)$, $(-2,0)$; vertical asymptotes: $x=-3$, $x=3$; horizontal asymptote: $y=-1$. - + \begin{tikzpicture}[/pgf/declare function={f=(4-x^2)/(x^2-9);}] \begin{axis}[ framed, @@ -5594,7 +5594,7 @@ Vertical intercept: $\left( 0,\frac{4}{5} \right)$; horizontal intercepts: $\left( -\frac{5}{4},0 \right)$, $\left( \frac{4}{3},0 \right)$; vertical asymptotes: $x=-\frac{5}{2}$, $x=5$; horizontal asymptote: $y=6$. - + \begin{tikzpicture}[/pgf/declare function={f=(4*x+5)*(3*x-4)/((2*x+5)*(x-5));}] \begin{axis}[ framed, @@ -5724,7 +5724,7 @@ R(x)= \begin{dcases} \frac{2}{x+3}, & x<-5 \\ - \frac{x-4}{x-10}, & x\geq -5 + \frac{x-4}{x-10}, & x\geq -5 \end{dcases} \] Evaluate each of the following. @@ -5762,7 +5762,7 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Graphing rational functions (oblique asymptotes)}\label{rat:sec:oblique} \begin{subproblem} $y=\dfrac{x^2+1}{x-4}$ @@ -5771,7 +5771,7 @@ \item $\left( 0,-\frac{1}{4} \right)$ \item Vertical asymptote: $x=4$. \item A graph of the function is shown below - + \begin{tikzpicture}[/pgf/declare function={f=(x^2+1)/(x-4);}] \begin{axis}[ framed, @@ -5798,7 +5798,7 @@ \item $(0,0)$, $(-3,0)$ \item Vertical asymptote: $x=5$, horizontal asymptote: none. \item A graph of the function is shown below - + \begin{tikzpicture}[/pgf/declare function={f=x^3*(x+3)/(x-5);}] \begin{axis}[ framed, diff --git a/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex b/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex index bf62bb9ee1f..ae704bd4bc1 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex @@ -25,7 +25,7 @@ a \emph{decreasing} function. Similarly, if $a>0$ then $g$ is \emph{concave up} and if $a<0$ then $g$ is \emph{concave down}. Graphical representations of these statements are given in \cref{poly:fig:linquad}. - + \begin{figure}[!htb] \setlength{\figurewidth}{.2\textwidth} \begin{subfigure}{\figurewidth} @@ -94,18 +94,18 @@ \caption{Typical graphs of linear and quadratic functions.} \label{poly:fig:linquad} \end{figure} - + Let's look a little more closely at the formulas for $f$ and $g$ in \cref{poly:eq:linquad}. Note that the \emph{degree} of $f$ is $1$ since the highest power of $x$ that is present in the formula for $f(x)$ is $1$. Similarly, the degree of $g$ is $2$ since the highest power of $x$ that is present in the formula for $g(x)$ is $2$. - + In this section we will build upon our knowledge of these elementary functions. In particular, we will generalize the functions $f$ and $g$ to a function $p$ that has any degree that we wish. - + %=================================== % Author: Hughes % Date: March 2012 @@ -161,7 +161,7 @@ \end{subproblem} \end{problem} \end{essentialskills} - + \subsection*{Power functions with positive exponents} The study of polynomials will rely upon a good knowledge of power functions| you may reasonably ask, what is a power function? @@ -171,17 +171,17 @@ f(x) = a_n x^n \] where $n$ can be any real number. - + Note that for this section we will only be concerned with the case when $n$ is a positive integer. \end{pccdefinition} - + You may find assurance in the fact that you are already very comfortable with power functions that have $n=1$ (linear) and $n=2$ (quadratic). Let's explore some power functions that you might not be so familiar with. As you read \cref{poly:ex:oddpow,poly:ex:evenpow}, try and spot as many patterns and similarities as you can. - + %=================================== % Author: Hughes % Date: March 2012 @@ -199,12 +199,12 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} f(x)\rightarrow\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty \end{align*} The same results hold for $g$ and $h$. \end{pccsolution} \end{pccexample} - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture} @@ -254,7 +254,7 @@ \label{poly:fig:evenpow} \end{minipage}% \end{figure} - + %=================================== % Author: Hughes % Date: March 2012 @@ -271,12 +271,12 @@ of each of the functions is the same, and in particular \begin{align*} F(x)\rightarrow\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} F(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} F(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty \end{align*} The same result holds for $G$ and $H$. \end{pccsolution} \end{pccexample} - + \begin{doyouunderstand} \begin{problem} Repeat \cref{poly:ex:oddpow,poly:ex:evenpow} using (respectively) @@ -285,7 +285,7 @@ \begin{shortsolution} The functions $f$, $g$, and $h$ have domain $(-\infty,\infty)$ and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -303,11 +303,11 @@ \legend{$f$,$g$,$h$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} f(x)\rightarrow-\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow\infty & \text{ as } x\rightarrow-\infty \end{align*} The same is true for $g$ and $h$. \end{shortsolution} @@ -317,7 +317,7 @@ \begin{shortsolution} The functions $F$, $G$, and $H$ have domain $(-\infty,\infty)$ and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -335,18 +335,18 @@ \legend{$F$,$G$,$H$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} F(x)\rightarrow-\infty & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} F(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} F(x)\rightarrow-\infty & \text{ as } x\rightarrow-\infty \end{align*} The same is true for $G$ and $H$. \end{shortsolution} \end{subproblem} \end{problem} \end{doyouunderstand} - + \subsection*{Polynomial functions} Now that we have a little more familiarity with power functions, we can define polynomial functions. Provided that you were comfortable @@ -357,7 +357,7 @@ and quadratic functions. Once you've studied the examples and problems in this section, you'll hopefully agree that polynomial functions are remarkably predictable. - + %=================================== % Author: Hughes % Date: May 2011 @@ -376,11 +376,11 @@ \end{itemize} In particular, we call $a_n$ the \emph{leading} coefficient, and $a_nx^n$ the \emph{leading term}. - + Note that if a polynomial is given in factored form, then the degree can be found by counting the number of linear factors. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: March 2012 @@ -416,7 +416,7 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: March 2012 @@ -440,7 +440,7 @@ shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. \end{itemize} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -536,7 +536,7 @@ \caption{Graphs to illustrate typical curves of polynomial functions.} \label{poly:fig:typical} \end{figure} - + %=================================== % Author: Hughes % Date: March 2012 @@ -550,7 +550,7 @@ to guide you. \begin{shortsolution} $a_1<0$: - + \begin{tikzpicture} \begin{axis}[ framed, @@ -563,9 +563,9 @@ \addplot expression[domain=-10:8]{-(x+2)}; \end{axis} \end{tikzpicture} - + $a_2<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -578,9 +578,9 @@ \addplot expression[domain=-4:4]{-(x^2-6)}; \end{axis} \end{tikzpicture} - + $a_3<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -593,9 +593,9 @@ \addplot expression[domain=-7.5:7.5]{-0.05*(x+6)*x*(x-6)}; \end{axis} \end{tikzpicture} - + $a_4<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -608,9 +608,9 @@ \addplot expression[domain=-2.35:5.35,samples=100]{-0.2*(x-5)*x*(x-3)*(x+2)}; \end{axis} \end{tikzpicture} - + $a_5<0$ - + \begin{tikzpicture} \begin{axis}[ framed, @@ -626,11 +626,11 @@ \end{shortsolution} \end{problem} \end{doyouunderstand} - + \fixthis{poly: Need a more basic example here- it can have a similar format to the multiple zeros example, but just keep it simple; it should be halfway between the 2 examples surrounding it} - + %=================================== % Author: Hughes % Date: May 2011 @@ -642,24 +642,24 @@ \begin{align*} p(x) & =(x-3)^2(x+4)^2 \\ q(x) & =x(x+2)^2(x-1)^2(x-3) \\ - r(x) & =x(x-3)^3(x+1)^2 + r(x) & =x(x-3)^3(x+1)^2 \end{align*} Find the degree of $p$, $q$, and $r$, and decide if the functions bounce off or cut through the horizontal axis at each of their zeros. \begin{pccsolution} The degree of $p$ is 4. Referring to \cref{poly:fig:bouncep}, the curve bounces off the horizontal axis at both zeros, $3$ and $4$. - + The degree of $q$ is 6. Referring to \cref{poly:fig:bounceq}, the curve bounces off the horizontal axis at $-2$ and $1$, and cuts through the horizontal axis at $0$ and $3$. - + The degree of $r$ is 6. Referring to \cref{poly:fig:bouncer}, the curve bounces off the horizontal axis at $-1$, and cuts through the horizontal axis at $0$ and at $3$, although is flattened immediately to the left and right of $3$. \end{pccsolution} \end{pccexample} - + \setlength{\figurewidth}{0.25\textwidth} \begin{figure}[!htb] \begin{subfigure}{\figurewidth} @@ -712,7 +712,7 @@ \caption{} \label{poly:fig:moremultiple} \end{figure} - + \begin{pccdefinition}[Multiple zeros]\label{poly:def:multzero} Let $p$ be a polynomial that has a repeated linear factor $(x-a)^n$. Then we say that $p$ has a multiple zero at $a$ of multiplicity $n$ and @@ -724,7 +724,7 @@ \end{itemize} If $n=1$, then we say that $p$ has a \emph{simple} zero at $a$. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: May 2011 @@ -786,7 +786,7 @@ Let's check if the formula we have written satisfies this requirement \begin{align*} p(1) & = (1)(4)(2)(-1) \\ - & = -8 + & = -8 \end{align*} which is clearly not correct| it is close though. We can correct this by multiplying $p$ by a constant $k$; so let's assume that @@ -807,7 +807,7 @@ evaluate $p(2)$ \begin{align*} p(2) & =k(4)^2(-1) \\ - & =-16k + & =-16k \end{align*} We solve the equation $4=-8k$ and obtain $k=-\frac{1}{4}$ and conclude that the formula for $q(x)$ is @@ -817,8 +817,8 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - - + + \fixthis{Chris: need sketching polynomial problems} \begin{pccspecialcomment}[Steps to follow when sketching polynomial functions] \begin{steps} @@ -865,12 +865,12 @@ \item We draw the details we have obtained so far on \cref{poly:fig:simplecubicp1}. Given that the curve of $p$ looks like the curve of $x^3$ in the long-run, we are able to complete a sketch of the graph of $p$ in \cref{poly:fig:simplecubicp2}. - + Note that we can not find the coordinates of the local minimums, local maximums, and inflection points| for the moment we make reasonable guesses as to where these points are (you'll find how to do this in calculus). \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -909,7 +909,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -934,7 +934,7 @@ \item We mark the details we have found so far on \cref{poly:fig:degree5p1}. Given that the curve of $q$ looks like the curve of $-x^5$ in the long-run, we can complete \cref{poly:fig:degree5p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -973,7 +973,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -1000,7 +1000,7 @@ the curve of $r$ looks like the curve of $x^6$ in the long-run, we complete the graph of $r$ in \cref{poly:fig:degree6p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -1038,7 +1038,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: March 2012 @@ -1058,7 +1058,7 @@ $x$ represents the length of a side, and $V(x)$ represents the volume of the box, we necessarily require both values to be positive; we illustrate the part of the curve that applies to this problem using a solid line. - + \begin{figure}[!htb] \centering \begin{tikzpicture} @@ -1080,21 +1080,21 @@ \caption{$y=V(x)$} \label{poly:fig:opentoppedbox} \end{figure} - + According to \cref{poly:fig:opentoppedbox}, the maximum volume of such a box is approximately $\unit[4000]{cm^2}$, and we achieve it using a base of length approximately $\unit[20]{cm}$. Since the base is square and each sheet of cardboard is $\unit[1200]{cm^2}$, we conclude that the dimensions of each box are $\unit[20]{cm}\times\unit[20]{cm}\times\unit[30]{cm}$. \end{pccsolution} \end{pccexample} - + \subsection*{Complex zeros} There has been a pattern to all of the examples that we have seen so far| the degree of the polynomial has dictated the number of \emph{real} zeros that the polynomial has. For example, the function $p$ in \cref{poly:ex:simplecubic} has degree $3$, and $p$ has $3$ real zeros; the function $q$ in \cref{poly:ex:degree5} has degree $5$ and $q$ has $5$ real zeros. - + You may wonder if this result can be generalized| does every polynomial that has degree $n$ have $n$ real zeros? Before we tackle the general result, let's consider an example that may help motivate it. @@ -1113,7 +1113,7 @@ x^2+1=0 \end{equation} The solutions to \cref{poly:eq:complx} are $\pm i$. - + We conclude that $c$ has $3$ zeros: $0$ and $\pm i$; we note that \emph{not all of them are real}. \end{pccexample} @@ -1143,7 +1143,7 @@ We begin by factoring $p$ \begin{align*} p(x) & =x^4-2x^3+5x^2 \\ - & =x^2(x^2-2x+5) + & =x^2(x^2-2x+5) \end{align*} We note that $0$ is a zero of $p$ with multiplicity $2$. The other zeros of $p$ can be found by solving the equation @@ -1154,7 +1154,7 @@ \begin{align*} x & =\frac{2\pm\sqrt{(-2)^2}-20}{2(1)} \\ & =\frac{2\pm\sqrt{-16}}{2} \\ - & =1\pm 2i + & =1\pm 2i \end{align*} We conclude that $p$ has $4$ zeros: $0$ (multiplicity $2$), and $1\pm 2i$ (simple). \end{pccsolution} @@ -1169,13 +1169,13 @@ We know that the zeros of a polynomial can be found by analyzing the linear factors. We are given the zeros, and have to work backwards to find the linear factors. - + We begin by assuming that $p$ has the form \begin{align*} p(x) & =(x-(2-i\sqrt{2}))(x-(2+i\sqrt{2})) \\ & =x^2-x(2+i\sqrt{2})-x(2-i\sqrt{2})+(2-i\sqrt{2})(2+i\sqrt{2}) \\ & =x^2-4x+(4-2i^2) \\ - & =x^2-4x+6 + & =x^2-4x+6 \end{align*} We conclude that a possible formula for a polynomial function, $p$, that has zeros at $2\pm i\sqrt{2}$ is @@ -1235,8 +1235,8 @@ \end{enumerate} \end{shortsolution} \end{problem} - - + + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -1287,10 +1287,10 @@ \caption{} \label{poly:fig:findformula} \end{figure} - - - - + + + + \begin{exercises} %=================================== % Author: Hughes @@ -1459,14 +1459,14 @@ \begin{align*} p(x) & = (x-1)(x+2)(x-3) \\ m(x) & = -(x-1)(x+2)(x-3) \\ - n(x) & = (x-1)(x+2)(x-3)(x+1)(x+4) + n(x) & = (x-1)(x+2)(x-3)(x+1)(x+4) \end{align*} Note that for our present purposes we are not concerned with the vertical scale of the graphs. \begin{subproblem} Identify both on the graph {\em and} algebraically, the zeros of each polynomial. \begin{shortsolution} $y=p(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1477,9 +1477,9 @@ \addplot[soldot] coordinates{(-2,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + $y=m(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1490,9 +1490,9 @@ \addplot[soldot] coordinates{(-2,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + $y=n(x)$ is shown below. - + \begin{tikzpicture} \begin{axis}[ xmin=-5,xmax=5, @@ -1503,7 +1503,7 @@ \addplot[soldot] coordinates{(-4,0)(-2,0)(-1,0)(1,0)(3,0)}; \end{axis} \end{tikzpicture} - + The zeros of $p$ are $-2$, $1$, and $3$; the zeros of $m$ are $-2$, $1$, and $3$; the zeros of $n$ are $-4$, $-2$, $-1$, and $3$. \end{shortsolution} @@ -1520,7 +1520,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -1773,7 +1773,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -1792,7 +1792,7 @@ $\dd\lim_{x\rightarrow\infty}s(x)=\infty$, \end{shortsolution} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -1917,7 +1917,7 @@ is positive. \begin{shortsolution} Assuming that $a_3>0$: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1937,7 +1937,7 @@ is negative. \begin{shortsolution} Assuming that $a_3<0$: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1961,7 +1961,7 @@ coefficient of $q$ is positive. Hint: only one of the zeros is simple. \begin{shortsolution} Assuming that $a_4>0$ there are $2$ different options: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -1982,7 +1982,7 @@ coefficient of $q$ is negative. \begin{shortsolution} Assuming that $a_4<0$ there are $2$ different options: - + \begin{tikzpicture} \begin{axis}[ xmin=-10,xmax=10, @@ -2194,7 +2194,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -2238,7 +2238,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -2290,7 +2290,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2298,7 +2298,7 @@ \begin{problem}[Find a formula from a table]\label{poly:prob:findformula} \Crefrange{poly:tab:findformulap}{poly:tab:findformulas} show values of polynomial functions, $p$, $q$, $r$, and $s$. - + \begin{table}[!htb] \centering \begin{widepage} @@ -2382,7 +2382,7 @@ \end{subtable} \end{widepage} \end{table} - + \begin{subproblem} Assuming that all of the zeros of $p$ are shown (in \cref{poly:tab:findformulap}), how many zeros does $p$ have? \begin{shortsolution} @@ -2433,7 +2433,7 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Rational functions} \subsection*{Power functions with negative exponents} The study of rational functions will rely upon a good knowledge @@ -2455,21 +2455,21 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} f(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \end{align*} The same results hold for $g$ and $h$. Note also that each of the functions has a \emph{vertical asymptote} at $0$. We see that \begin{align*} f(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} f(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} f(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ \end{align*} The same results hold for $g$ and $h$. - + The curve of a function that has a vertical asymptote is necessarily separated into \emph{branches}| each of the functions $f$, $g$, and $h$ have $2$ branches. \end{pccsolution} \end{pccexample} - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture} @@ -2525,8 +2525,8 @@ \label{rat:fig:evenpow} \end{minipage}% \end{figure} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -2543,7 +2543,7 @@ the long-run behavior of each of the functions is the same, and in particular \begin{align*} F(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ - \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty + \mathllap{\text{and }} f(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \end{align*} As in \cref{rat:ex:oddpow}, $F$ has a horizontal asymptote that has equation $y=0$. @@ -2551,7 +2551,7 @@ has a \emph{vertical asymptote} at $0$. We see that \begin{align*} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} F(x)\rightarrow \infty & \text{ as } x\rightarrow 0^+ \end{align*} The same results hold for $G$ and $H$. Each of the functions $F$, $G$, and $H$ have $2$ branches. @@ -2569,7 +2569,7 @@ \begin{shortsolution} The functions $k$, $m$, and $n$ have domain $(-\infty,0)\cup (0,\infty)$, and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -2590,14 +2590,14 @@ \legend{$k$,$m$,$n$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} k(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ \mathllap{\text{and }} k(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \\ \intertext{and also} k(x)\rightarrow \infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} k(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} k(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ \end{align*} The same are true for $m$ and $n$. \end{shortsolution} @@ -2607,7 +2607,7 @@ \begin{shortsolution} The functions $K$, $M$, and $N$ have domain $(-\infty,0)\cup (0,\infty)$, and are graphed below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -2628,21 +2628,21 @@ \legend{$K$,$M$,$N$} \end{axis} \end{tikzpicture} - + Note that \begin{align*} K(x)\rightarrow 0 & \text{ as } x\rightarrow\infty \\ \mathllap{\text{and }} K(x)\rightarrow 0 & \text{ as } x\rightarrow-\infty \\ \intertext{and also} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^- \\ - \mathllap{\text{and }} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ + \mathllap{\text{and }} K(x)\rightarrow -\infty & \text{ as } x\rightarrow 0^+ \end{align*} The same are true for $M$ and $N$. \end{shortsolution} \end{subproblem} \end{problem} \end{doyouunderstand} - + \subsection*{Rational functions} \begin{pccdefinition}[Rational functions]\label{rat:def:function} Rational functions have the form @@ -2650,7 +2650,7 @@ r(x) = \frac{p(x)}{q(x)} \] where both $p$ and $q$ are polynomials. - + Note that \begin{itemize} \item the domain or $r$ will be all real numbers, except those that @@ -2658,13 +2658,13 @@ \item the zeros of $r$ are the zeros of $p$, i.e the real numbers that make the \emph{numerator}, $p(x)$, equal to $0$. \end{itemize} - + \Cref{rat:ex:oddpow,rat:ex:evenpow} are particularly important because $r$ will behave like $\frac{1}{x}$, or $\frac{1}{x^2}$ around its vertical asymptotes, depending on the power that the relevant term is raised to| we will demonstrate this in what follows. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2699,7 +2699,7 @@ \end{enumerate} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2779,7 +2779,7 @@ \caption{} \label{rat:fig:whichiswhich} \end{figure} - + \begin{pccsolution} Let's start with the function $r$. Note that domain of $r$ is $(-\infty,3)\cup(0,3)$, so we search for a function that has a vertical asymptote at $3$. There @@ -2787,18 +2787,18 @@ but note that the function in \cref{rat:fig:which3} also has a vertical asymptote at $-2$ which is not consistent with the formula for $r(x)$. Therefore, $y=r(x)$ is graphed in \cref{rat:fig:which2}. - + The function $q$ has domain $(-\infty,-5)\cup(-5,\infty)$, so we search for a function that has a vertical asymptote at $-5$. The only candidate is the curve shown in \cref{rat:fig:which1}; note that the curve also goes through $(2,0)$, which is consistent with the formula for $q(x)$, since $q(2)=0$, i.e $q$ has a zero at $2$. - + The function $k$ has domain $(-\infty,-2)\cup(-2,3)\cup(3,\infty)$, and has vertical asymptotes at $-2$ and $3$. This is consistent with the graph in \cref{rat:fig:which3} (and is the only curve that has $3$ branches). - + We note that each function behaves like $\frac{1}{x}$ around its vertical asymptotes, because each linear factor in each denominator is raised to the power $1$; if (for example) the definition of $r$ was instead @@ -2809,7 +2809,7 @@ the graph of $r$ would be very different. We will deal with these cases in the examples that follow. \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -2827,7 +2827,7 @@ so we are not surprised to see that each curve has $3$ branches. We also note that the numerator of each function is the same, which tells us that each function has only $1$ zero at $2$. - + The functions $g$ and $h$ are different from those that we have considered previously, because they have a repeated factor in the denominator. Notice in particular the way that the functions behave around their asymptotes: @@ -2910,7 +2910,7 @@ \caption{} \label{rat:fig:repfactd} \end{figure} - + \Cref{rat:def:function} says that the zeros of the rational function $r$ that has formula $r(x)=\frac{p(x)}{q(x)}$ are the zeros of $p$. Let's explore this a little more. @@ -2929,9 +2929,9 @@ x+5=0 \] The zero of $\alpha$ is $-5$. - + Similarly, we may solve $9-x=0$ to find the zero of $\beta$, which is clearly $9$. - + The zeros of $\gamma$ satisfy the equation \[ 17x^2-10=0 @@ -2943,7 +2943,7 @@ The zeros of $\gamma$ are $\pm\frac{10}{17}$. \end{pccsolution} \end{pccexample} - + \subsection*{Long-run behavior} Our focus so far has been on the behavior of rational functions around their \emph{vertical} asymptotes. In fact, rational functions also @@ -2966,7 +2966,7 @@ \end{pccdefinition} We will concentrate on functions that have horizontal asymptotes until we reach \cref{rat:sec:oblique}. - + %=================================== % Author: Hughes % Date: May 2012 @@ -2979,7 +2979,7 @@ and obtained the curves shown in \cref{rat:fig:horizasymp}. Kebede decides to test his knowledgeable friend \pccname{Oscar}, and asks him to match the formulas to the graphs. - + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -3050,7 +3050,7 @@ \caption{Horizontal asymptotes} \label{rat:fig:horizasymp} \end{figure} - + Oscar notices that each function has a vertical asymptote at $3$ and a zero at $-1$. The main thing that catches Oscar's eye is that each function has a different coefficient in the numerator, and that each curve has a different horizontal asymptote. @@ -3064,14 +3064,14 @@ that since the degree of the numerator and the degree of the denominator is the same for each of the functions $r$, $s$, and $t$, the horizontal asymptote will be determined by evaluating the ratio of their leading coefficients. - + Oscar therefore says that $r$ should have a horizontal asymptote $y=\frac{1}{1}=1$, $s$ should have a horizontal asymptote $y=\frac{2}{1}=2$, and $t$ should have a horizontal asymptote $y=\frac{3}{1}=3$. Kebede is able to finish the problem from here, and says that $r$ is shown in \cref{rat:fig:horizasymp2}, $s$ is shown in \cref{rat:fig:horizasymp1}, and $t$ is shown in \cref{rat:fig:horizasymp3}. \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -3080,7 +3080,7 @@ \pccname{Xiao} and \pccname{Dwayne} saw \cref{rat:ex:horizasymp} but are a little confused about horizontal asymptotes. What does it mean to say that a function $r$ has a horizontal asymptote? - + They decide to explore the concept by constructing a table of values for the rational functions $R$ and $S$ that have formulas \[ @@ -3119,13 +3119,13 @@ \end{tabular} \end{minipage} \end{table} - + Xiao and Dwayne study \cref{rat:tab:plusinfty,rat:tab:minusinfty} and decide that the functions $R$ and $S$ never actually touch their horizontal asymptotes, but they do get infinitely close. They also feel as if they have a better understanding of what it means to study the behavior of a function as $x\rightarrow\pm\infty$. \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3142,7 +3142,7 @@ \] We also notice that the numerators of each function are quite similar| indeed, each function has a zero at $2$, but how does each function behave around their zero? - + Using \cref{rat:fig:repfactn} to guide us, we note that \begin{itemize} \item $f$ has a horizontal intercept $(2,0)$, but the curve of @@ -3152,7 +3152,7 @@ \item $h$ has a horizontal intercept $(2,0)$, and the curve of $h$ also cuts the axis, but appears flattened as it does so. \end{itemize} - + We can further enrich our study by discussing the long-run behavior of each function. Using the tools of \cref{rat:def:longrun}, we can deduce that \begin{itemize} @@ -3162,7 +3162,7 @@ study this more in \cref{rat:sec:oblique}). \end{itemize} \end{pccexample} - + \begin{figure}[!htb] \setlength{\figurewidth}{0.3\textwidth} \begin{subfigure}{\figurewidth} @@ -3235,7 +3235,7 @@ \caption{} \label{rat:fig:repfactn} \end{figure} - + \subsection*{Holes} Rational functions have a vertical asymptote at $a$ if the denominator is $0$ at $a$. What happens if the numerator is $0$ at the same place? In this case, we say that the rational @@ -3250,7 +3250,7 @@ $(a,r(a))$ on the curve $y=r(x)$ by using a hollow circle, $\circ$. \end{pccdefinition} - + %=================================== % Author: Hughes % Date: March 2012 @@ -3262,12 +3262,12 @@ \] in their calculators, and can not decide if the correct graph is \cref{rat:fig:hole} or \cref{rat:fig:hole1}. - + Luckily for them, Oscar is nearby, and can help them settle the debate. Oscar demonstrates that \begin{align*} r(x) & =\frac{(x+3)(x-2)}{(x-2)} \\ - & = x+3 + & = x+3 \end{align*} but only when $x\ne 2$, because the function is undefined at $2$. Oscar says that this necessarily means that the domain or $r$ is @@ -3275,7 +3275,7 @@ (-\infty,2)\cup(2,\infty) \] and that $r$ must have a hole at $2$. - + Mohammed and Sue are very grateful for the clarification, and conclude that the graph of $r$ is shown in \cref{rat:fig:hole1}. \begin{figure}[!htb] @@ -3319,7 +3319,7 @@ \end{minipage}% \end{figure} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3333,12 +3333,12 @@ make the denominator equal to $0$. Notice that \begin{align*} f(x) & = \frac{x(x+3)}{x(x-4)} \\ - & = \frac{x+3}{x-4} + & = \frac{x+3}{x-4} \end{align*} provided that $x\ne 0$. Since $0$ makes the numerator and the denominator 0 at the same time, we say that $f$ has a hole at $(0,-\nicefrac{3}{4})$. Note that this necessarily means that $f$ does not have a vertical intercept. - + We also note $f$ has a vertical asymptote at $4$; the function is graphed in \cref{rat:fig:holeex}. \begin{figure}[!htb] \centering @@ -3362,9 +3362,9 @@ \label{rat:fig:holeex} \end{figure} \end{pccexample} - - - + + + %=================================== % Author: Hughes % Date: March 2012 @@ -3374,7 +3374,7 @@ if a rational function has a vertical asymptote, then it can not possibly have local minimums and maximums, nor can it have global minimums and maximums. - + Trang says this statement is not always true. She plots the functions $f$ and $g$ that have formulas \[ @@ -3383,7 +3383,7 @@ in \cref{rat:fig:minmax1,rat:fig:minmax2} and shows them to Seamus. On seeing the graphs, Seamus quickly corrects himself, and says that $f$ has a local (and global) maximum of $2$ at $0$, and that $g$ has a local (and global) minimum of $-2$ at $0$. - + \begin{figure}[!htb] \begin{minipage}{.45\textwidth} \begin{tikzpicture}[/pgf/declare function={f=-32*(x-1)*(x+1)/(( x-2)^2*(x+2)^2);}] @@ -3427,19 +3427,19 @@ \label{rat:fig:minmax2} \end{minipage}% \end{figure} - + Seamus also notes that (in its domain) the function $f$ is always concave down, and that (in its domain) the function $g$ is always concave up. Furthermore, Trang observes that each function behaves like $\frac{1}{x^2}$ around each of its vertical asymptotes, because each linear factor in the denominator is raised to the power $2$. - + \pccname{Oscar} stops by and reminds both students about the long-run behavior; according to \cref{rat:def:longrun} since the degree of the denominator is greater than the degree of the numerator (in both functions), each function has a horizontal asymptote at $y=0$. \end{pccexample} - - + + \investigation*{} %=================================== % Author: Pettit/Hughes @@ -3448,12 +3448,12 @@ \begin{problem}[The spaghetti incident] The same Queen from \vref{exp:prob:queenschessboard} has recovered from the rice experiments, and has called her loyal jester for another challenge. - + The jester has an $11-$inch piece of uncooked spaghetti that he puts on a table; he uses a book to cover $\unit[1]{inch}$ of it so that $\unit[10]{inches}$ hang over the edge. The jester then produces a box of $\unit{mg}$ weights that can be hung from the spaghetti. - + The jester says it will take $\unit[y]{mg}$ to break the spaghetti when hung $\unit[x]{inches}$ from the edge, according to the rule $y=\frac{100}{x}$. \begin{margintable} @@ -3537,7 +3537,7 @@ note that this necessarily means that you will not be able to plot all of the points. \begin{shortsolution} The graph of $y=\frac{100}{x}$ is shown below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -3567,9 +3567,9 @@ \end{subproblem} The Queen looks forward to more food-related investigations from her jester. \end{problem} - - - + + + %=================================== % Author: Adams (Hughes) % Date: March 2012 @@ -3593,17 +3593,17 @@ Paying off the debt in $2$ years, we use \begin{align*} M & = \frac{2000\cdot 0.015}{1-(1+0.015)^{-24}} \\ - & \approx 99.85 + & \approx 99.85 \end{align*} The monthly payments are \$99.85. - + Paying off the debt in $1$ year, we use \begin{align*} M & = \frac{2000\cdot 0.015}{1-(1+0.015)^{-12}} \\ - & \approx 183.36 + & \approx 183.36 \end{align*} The monthly payments are \$183.36 - + In the $2$-year model we would pay a total of $\$99.85\cdot 12=\$2396.40$. In the $1$-year model we would pay a total of $\$183.36\cdot 12=\$2200.32$. We would therefore save $\$196.08$ if we went with the $1$-year model instead of the $2$-year model. @@ -3619,20 +3619,20 @@ For the $20$-year loan we use \begin{align*} M & = \frac{300000\cdot \frac{0.052}{12}}{1-\left( 1+\frac{0.052}{12} \right)^{-12\cdot 20}} \\ - & \approx 2013.16 + & \approx 2013.16 \end{align*} The monthly payments are \$2013.16. - + For the $30$-year loan we use \begin{align*} M & = \frac{300000\cdot \frac{0.052}{12}}{1-\left( 1+\frac{0.052}{12} \right)^{-12\cdot 30}} \\ - & \approx 1647.33 + & \approx 1647.33 \end{align*} The monthly payments are \$1647.33. - + The total amount paid during the $20$-year loan is $\$2013.16\cdot 12\cdot 20=\$483,158.40$. The total amount paid during the $30$-year loan is $\$1647.33\cdot 12\cdot 30=\$593,038.80$. - + Recommendation: if you can afford the payments, choose the $20$-year loan. \end{shortsolution} \end{subproblem} @@ -3662,7 +3662,7 @@ This means that the monthly payments will be calculated using \begin{align*} M & = \frac{14000\cdot \frac{0.04}{12}}{1-\left( 1+\frac{0.04}{12} \right)^{-12\cdot 5}} \\ - & \approx 257.83 + & \approx 257.83 \end{align*} The monthly payments will be $\$257.83$. The total amount paid will be $\$257.83\cdot 5\cdot 12=\$15,469.80$, of which $\$1469.80$ is interest. @@ -3670,7 +3670,7 @@ This means that the monthly payments will be calculated using \begin{align*} M & = \frac{12000\cdot \frac{0.08}{12}}{1-\left( 1+\frac{0.08}{12} \right)^{-12\cdot 5}} \\ - & \approx 243.32 + & \approx 243.32 \end{align*} The monthly payments will be $\$243.32$. The total amount paid will be $\$243.32\cdot 5\cdot 12 =\$14,599.20$, of which $\$2599.2$ is @@ -3681,7 +3681,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + \begin{exercises} %=================================== % Author: Hughes @@ -3783,7 +3783,7 @@ $\begin{aligned}[t] r(0) & =\frac{(0-2)(0+3)}{(0+5)(0-7)} \\ & =\frac{-6}{-35} \\ - & =\frac{6}{35} + & =\frac{6}{35} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3793,7 +3793,7 @@ $\begin{aligned}[t] r(1) & =\frac{(1-2)(1+3)}{(1+5)(1-7)} \\ & =\frac{-4}{-36} \\ - & =\frac{1}{9} + & =\frac{1}{9} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3803,7 +3803,7 @@ $\begin{aligned}[t] r(2) & =\frac{(2-2)(2+3)}{(2+5)(2-7)} \\ & = \frac{0}{-50} \\ - & =0 + & =0 \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3813,7 +3813,7 @@ $\begin{aligned}[t] r(4) & =\frac{(4-2)(4+3)}{(4+5)(4-7)} \\ & =\frac{14}{-27} \\ - & =-\frac{14}{27} + & =-\frac{14}{27} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3822,9 +3822,9 @@ \begin{shortsolution} $\begin{aligned}[t] r(7) & =\frac{(7-2)(7+3)}{(7+5)(7-7)} \\ - & =\frac{50}{0} + & =\frac{50}{0} \end{aligned}$ - + $r(7)$ is undefined. \end{shortsolution} \end{subproblem} @@ -3834,7 +3834,7 @@ $\begin{aligned}[t] r(-3) & =\frac{(-3-2)(-3+3)}{(-3+5)(-3-7)} \\ & =\frac{0}{-20} \\ - & =0 + & =0 \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3843,9 +3843,9 @@ \begin{shortsolution} $\begin{aligned}[t] r(-5) & =\frac{(-5-2)(-5+3)}{(-5+5)(-5-7)} \\ - & =\frac{14}{0} + & =\frac{14}{0} \end{aligned}$ - + $r(-5)$ is undefined. \end{shortsolution} \end{subproblem} @@ -3856,7 +3856,7 @@ r\left( \frac{1}{2} \right) & = \frac{\left( \frac{1}{2}-2 \right)\left( \frac{1}{2}+3 \right)}{\left( \frac{1}{2}+5 \right)\left( \frac{1}{2}-7 \right)} \\ & =\frac{-\frac{3}{2}\cdot\frac{7}{2}}{\frac{11}{2}\left( -\frac{13}{2} \right)} \\ & =\frac{-\frac{21}{4}}{-\frac{143}{4}} \\ - & =\frac{37}{143} + & =\frac{37}{143} \end{aligned}$ \end{shortsolution} \end{subproblem} @@ -3908,7 +3908,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -3925,7 +3925,7 @@ \end{itemize} \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -3997,7 +3997,7 @@ \label{rat:fig:findformula} \end{widepage} \end{figure} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4034,7 +4034,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4099,7 +4099,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2012 @@ -4181,7 +4181,7 @@ \end{subproblem} \end{multicols} \end{problem} - + %=================================== % Author: Hughes % Date: May 2011 @@ -4212,7 +4212,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: Feb 2011 @@ -4265,8 +4265,8 @@ \end{shortsolution} \end{subproblem} \end{problem} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -4309,7 +4309,7 @@ Sketch a graph of $r$. \begin{shortsolution} A graph of $r$ is shown below. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -4329,7 +4329,7 @@ \end{shortsolution} \end{subproblem} \end{problem} - + %=================================== % Author: Hughes % Date: July 2012 @@ -4367,8 +4367,8 @@ \end{subproblem} \end{multicols} \end{problem} - - + + %=================================== % Author: Hughes % Date: July 2012 @@ -4419,8 +4419,8 @@ \end{subproblem} \end{multicols} \end{problem} - - + + %=================================== % Author: Hughes % Date: May 2011 @@ -4428,7 +4428,7 @@ \begin{problem}[Find a formula from a table]\label{rat:prob:findformula} \Crefrange{rat:tab:findformular}{rat:tab:findformulau} show values of rational functions $r$, $q$, $s$, and $t$. Assume that any values marked with an X are undefined. - + \begin{table}[!htb] \begin{widepage} \centering @@ -4525,7 +4525,7 @@ r(-4) & = \frac{-4-3}{-4+2} \\ & = \frac{7}{2} \\ \end{aligned}$ - + $r(-3)=\ldots$ etc \end{shortsolution} \end{subproblem} @@ -4541,9 +4541,9 @@ \begin{shortsolution} $\begin{aligned}[t] s(-4) & =\frac{-4+2}{(-4-3)(-4+1)} \\ - & =-\frac{2}{21} + & =-\frac{2}{21} \end{aligned}$ - + $s(-3)=\ldots$ etc \end{shortsolution} \end{subproblem} @@ -4563,13 +4563,13 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Graphing rational functions (horizontal asymptotes)} \reformatstepslist{R} % the steps list should be R1, R2, \ldots We studied rational functions in the previous section, but were not asked to graph them; in this section we will demonstrate the steps to be followed in order to sketch graphs of the functions. - + Remember from \vref{rat:def:function} that rational functions have the form \[ @@ -4583,7 +4583,7 @@ in this section \emph{will have a horizontal asymptote} (see \vref{rat:def:longrun}). The cases in which the degree of $p$ is greater than the degree of $q$ is covered in the next section. - + Before we begin, it is important to remember the following: \begin{itemize} \item Our sketches will give a good representation of the overall @@ -4612,10 +4612,10 @@ find the exact coordinates of local minimums, local maximums, and points of inflection. \end{pccspecialcomment} - + The examples that follow show how \crefrange{rat:step:first}{rat:step:last} can be applied to a variety of different rational functions. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4641,7 +4641,7 @@ \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4678,14 +4678,14 @@ \end{subfigure}% \caption{$y=\dfrac{1}{x-2}$} \end{figure} - + The function $r$ in \cref{rat:ex:1overxminus2p2} has a horizontal asymptote which has equation $y=0$. This asymptote lies on the horizontal axis, and you might (understandably) find it hard to distinguish between the two lines (\cref{rat:fig:1overxminus2p2}). When faced with such a situation, it is perfectly acceptable to draw the horizontal axis as a dashed line| just make sure to label it correctly. We will demonstrate this in the next example. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4711,12 +4711,12 @@ is, because we know what the overall shape will be. Let's compute $v(2)$ \begin{align*} v(2) & =\dfrac{10}{2} \\ - & = 5 + & = 5 \end{align*} We therefore mark the point $(2,5)$ on \cref{rat:fig:1overxp2}, and then complete the sketch using the details we found in the previous steps. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4760,7 +4760,7 @@ \end{figure} \end{pccsolution} \end{pccexample} - + %=================================== % Author: Hughes % Date: May 2012 @@ -4778,7 +4778,7 @@ \begin{align*} u(x) & =\frac{-4(x^2-9)}{x^2-8x+15} \\ & =\frac{-4(x+3)(x-3)}{(x-5)(x-3)} \\ - & =\frac{-4(x+3)}{x-5} + & =\frac{-4(x+3)}{x-5} \end{align*} provided that $x\ne 3$. Therefore $u$ has a vertical asymptote at $5$ and a hole at $3$. The curve of $u$ has $2$ branches. @@ -4788,7 +4788,7 @@ \item We put the details we have obtained so far on \cref{rat:fig:1overxminus2p1}. Notice that there is only one way to complete the graph, which we have done in \cref{rat:fig:1overxminus2p2}. \end{steps} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4833,12 +4833,12 @@ \end{figure} \end{pccsolution} \end{pccexample} - + \Cref{rat:ex:1overxminus2p2,rat:ex:1overxp1,rat:ex:asympandholep1} have focused on functions that only have one vertical asymptote; the remaining examples in this section concern functions that have more than one vertical asymptote. We will demonstrate that \crefrange{rat:step:first}{rat:step:last} still apply. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4862,20 +4862,20 @@ of the numerator and denominator, we say that $w$ has a horizontal asymptote with equation $y=\frac{2}{1}=2$. \item We put the details we have obtained so far on \cref{rat:fig:sketchtwoasymptp1}. - + The function $w$ is a little more complicated than the functions that we have considered in the previous examples because the curve has $3$ branches. When graphing such functions, it is generally a good idea to start with the branch for which you have the most information| in this case, that is the \emph{middle} branch on the interval $(-5,4)$. - + Once we have drawn the middle branch, there is only one way to complete the graph (because of our observations about the behavior of $w$ around its vertical asymptotes), which we have done in \cref{rat:fig:sketchtwoasymptp2}. \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -4921,12 +4921,12 @@ \end{subfigure}% \caption{$y=\dfrac{2(x+3)(x-5)}{(x+5)(x-4)}$} \end{figure} - + The rational functions that we have considered so far have had simple factors in the denominator; each function has behaved like $\frac{1}{x}$ around each of its vertical asymptotes. \Cref{rat:ex:2asympnozeros,rat:ex:2squaredasymp} consider functions that have a repeated factor in the denominator. - + %=================================== % Author: Hughes % Date: May 2012 @@ -4949,17 +4949,17 @@ denominator of $f$ is $2$. $f$ has a horizontal asymptote with equation $y=0$. \item We put the details we have obtained so far on \cref{rat:fig:2asympnozerosp1}. - + The function $f$ is similar to the function $w$ that we considered in \cref{rat:ex:sketchtwoasymp}| it has two vertical asymptotes and $3$ branches, but in contrast to $w$ it does not have any zeros. - + We sketch $f$ in \cref{rat:fig:2asympnozerosp2}, using the middle branch as our guide because we have the most information about the function on the interval $(-5,4)$. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $f$ around its vertical asymptotes (it behaves like $\frac{1}{x}$), which we have done in \cref{rat:fig:2asympnozerosp2}. - + Note that we are not yet able to find the local minimum of $f$ algebraically on the interval $(-5,4)$, so we make a reasonable guess as to where it is| we can be confident that it is above the horizontal axis since $f$ has no zeros. You may think that this is unsatisfactory, but once we have the tools of calculus, we will @@ -4967,7 +4967,7 @@ \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5011,7 +5011,7 @@ \end{subfigure}% \caption{$y=\dfrac{100}{(x+5)(x-4)^2}$} \end{figure} - + %=================================== % Author: Hughes % Date: May 2012 @@ -5037,19 +5037,19 @@ \cref{rat:fig:2squaredasymp1}. The function $g$ is similar to the functions we considered in \cref{rat:ex:sketchtwoasymp,rat:ex:2asympnozeros} because it has $2$ vertical asymptotes and $3$ branches. - + We sketch $g$ using the middle branch as our guide because we have the most information about $g$ on the interval $(-3,5)$. Note that there is no other way to draw this branch without introducing other zeros which $g$ does not have. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $g$ around its vertical asymptotes| it behaves like $\frac{1}{x^2}$. - + \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5093,14 +5093,14 @@ \end{subfigure}% \caption{$y=\dfrac{50(2-x)}{(x+3)^2(x-5)^2}$} \end{figure} - + Each of the rational functions that we have considered so far has had either a \emph{simple} zero, or no zeros at all. Remember from our work on polynomial functions, and particularly \vref{poly:def:multzero}, that a \emph{repeated} zero corresponds to the curve of the function behaving differently at the zero when compared to how the curve behaves at a simple zero. \Cref{rat:ex:doublezero} details a function that has a non-simple zero. - + %=================================== % Author: Hughes % Date: June 2012 @@ -5127,20 +5127,20 @@ \cref{rat:fig:doublezerop1}. The function $h$ is different from the functions that we have considered in previous examples because of the multiplicity of the zero at $3$. - + We sketch $h$ using the middle branch as our guide because we have the most information about $h$ on the interval $(-4,6)$. Note that there is no other way to draw this branch without introducing other zeros which $h$ does not have| also note how the curve bounces off the horizontal axis at $3$. - + Once we have drawn the middle branch, there is only one way to complete the graph because of our observations about the behavior of $h$ around its vertical asymptotes| it behaves like $\frac{1}{x}$. - + \end{steps} \end{pccsolution} \end{pccexample} - + \begin{figure}[!htbp] \begin{subfigure}{.45\textwidth} \begin{tikzpicture} @@ -5199,7 +5199,7 @@ at $b$, and a vertical asymptote at $c$. Furthermore, these functions behave like $\frac{1}{x}$ around their vertical asymptote, and the curve of each function will have $2$ branches. - + Katie has been working with $3$ functions that have the form given in \cref{rat:eq:deducecurve}, and has followed \crefrange{rat:step:first}{rat:step:penultimate}; her results are shown in \cref{rat:fig:deducecurve}. There is just one @@ -5207,7 +5207,7 @@ Help Katie finish each graph by deducing the curve of each function. \begin{shortsolution} \Vref{rat:fig:deducecurve1} - + \begin{tikzpicture}[/pgf/declare function={f=3*(x+4)/(x+5);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5222,9 +5222,9 @@ \addplot[pccplot] expression[domain=-4.76923:10,samples=50]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducecurve2} - + \begin{tikzpicture}[/pgf/declare function={f=-3*(x-2)/(x-4);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5239,9 +5239,9 @@ \addplot[pccplot] expression[domain=4.85714:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducecurve4} - + \begin{tikzpicture}[/pgf/declare function={f=2*(x-6)/(x-4);}] \begin{axis}[ xmin=-10,xmax=10, @@ -5258,7 +5258,7 @@ \end{tikzpicture} \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -5316,7 +5316,7 @@ \label{rat:fig:deducecurve} \end{widepage} \end{figure} - + %=================================== % Author: Hughes % Date: June 2012 @@ -5331,13 +5331,13 @@ at $b$ and $c$, and vertical asymptotes at $d$ and $e$. Furthermore, these functions behave like $\frac{1}{x}$ around both vertical asymptotes, and the curve of the function will have $3$ branches. - + David has followed \crefrange{rat:step:first}{rat:step:penultimate} for $3$ separate functions, and drawn the results in \cref{rat:fig:deducehard}. Help David finish each graph by deducing the curve of each function. \begin{shortsolution} \Vref{rat:fig:deducehard1} - + \begin{tikzpicture}[/pgf/declare function={f=(x-6)*(x+3)/( (x-4)*(x+1));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5354,9 +5354,9 @@ \addplot[pccplot] expression[domain=4.24276:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducehard2} - + \begin{tikzpicture}[/pgf/declare function={f=3*(x-2)*(x+3)/( (x-6)*(x+5));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5373,9 +5373,9 @@ \addplot[pccplot] expression[domain=7.34324:10]{f}; \end{axis} \end{tikzpicture} - + \Vref{rat:fig:deducehard3} - + \begin{tikzpicture}[/pgf/declare function={f=2*(x-7)*(x+3)/( (x+6)*(x-5));}] \begin{axis}[ xmin=-10,xmax=10, @@ -5392,10 +5392,10 @@ \addplot[pccplot] expression[domain=5.25586:10]{f}; \end{axis} \end{tikzpicture} - + \end{shortsolution} \end{problem} - + \begin{figure}[!htb] \begin{widepage} \setlength{\figurewidth}{0.3\textwidth} @@ -5470,7 +5470,7 @@ $y=\dfrac{4}{x+2}$ \begin{shortsolution} Vertical intercept: $(0,2)$; vertical asymptote: $x=-2$, horizontal asymptote: $y=0$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5494,7 +5494,7 @@ Vertical intercept:$\left( 0,\frac{1}{9} \right)$; horizontal intercept: $\left( \frac{1}{2},0 \right)$; vertical asymptotes: $x=-3$, $x=3$, horizontal asymptote: $y=0$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5519,7 +5519,7 @@ \begin{shortsolution} Vertical intercept $\left( 0,-\frac{3}{5} \right)$; horizontal intercept: $(-3,0)$; vertical asymptote: $x=5$; horizontal asymptote: $y=1$. - + \begin{tikzpicture} \begin{axis}[ framed, @@ -5544,7 +5544,7 @@ \begin{shortsolution} Vertical intercept: $(0,-3)$; horizontal intercept: $\left( -\frac{3}{2},0 \right)$; vertical asymptote: $x=\frac{1}{3}$, horizontal asymptote: $y=\frac{2}{3}$. - + \begin{tikzpicture}[/pgf/declare function={f=(2*x+3)/(3*x-1);}] \begin{axis}[ framed, @@ -5568,7 +5568,7 @@ Vertical intercept: $\left( 0,-\frac{4}{9} \right)$; horizontal intercepts: $(2,0)$, $(-2,0)$; vertical asymptotes: $x=-3$, $x=3$; horizontal asymptote: $y=-1$. - + \begin{tikzpicture}[/pgf/declare function={f=(4-x^2)/(x^2-9);}] \begin{axis}[ framed, @@ -5594,7 +5594,7 @@ Vertical intercept: $\left( 0,\frac{4}{5} \right)$; horizontal intercepts: $\left( -\frac{5}{4},0 \right)$, $\left( \frac{4}{3},0 \right)$; vertical asymptotes: $x=-\frac{5}{2}$, $x=5$; horizontal asymptote: $y=6$. - + \begin{tikzpicture}[/pgf/declare function={f=(4*x+5)*(3*x-4)/((2*x+5)*(x-5));}] \begin{axis}[ framed, @@ -5724,7 +5724,7 @@ R(x)= \begin{dcases} \frac{2}{x+3}, & x<-5 \\ - \frac{x-4}{x-10}, & x\geq -5 + \frac{x-4}{x-10}, & x\geq -5 \end{dcases} \] Evaluate each of the following. @@ -5762,7 +5762,7 @@ \end{subproblem} \end{problem} \end{exercises} - + \section{Graphing rational functions (oblique asymptotes)}\label{rat:sec:oblique} \begin{subproblem} $y=\dfrac{x^2+1}{x-4}$ @@ -5771,7 +5771,7 @@ \item $\left( 0,-\frac{1}{4} \right)$ \item Vertical asymptote: $x=4$. \item A graph of the function is shown below - + \begin{tikzpicture}[/pgf/declare function={f=(x^2+1)/(x-4);}] \begin{axis}[ framed, @@ -5798,7 +5798,7 @@ \item $(0,0)$, $(-3,0)$ \item Vertical asymptote: $x=5$, horizontal asymptote: none. \item A graph of the function is shown below - + \begin{tikzpicture}[/pgf/declare function={f=x^3*(x+3)/(x-5);}] \begin{axis}[ framed, diff --git a/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex b/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex index 1fd497c1e2f..c7e3cce3730 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex @@ -45,89 +45,91 @@ Another tabbing mechanism]\relax \advance\CurrentLineWidth -2em \advance\CurrentLineWidth -\displayindent \advance\CurrentLineWidth -\leftskip - \fi\fi - \ifdim\CurrentLineWidth<\z@ \CurrentLineWidth\z@\fi - % Enshrine the tab-to position; #1 might reference \CurrentLineWidth - \@tempdimb=#1\relax - \message{*** Tab to \the\@tempdimb, previous width is \the\CurrentLineWidth. ***}% - % Save width for possible return use - \xdef\TabPrevPos{\the\CurrentLineWidth}% - % Build the action to perform - \protected@xdef\TTo@action{% - \vrule\@width\z@\@depth\the\prevdepth - \ifdim\CurrentLineWidth>\@tempdimb - \ifTTo@overlap\else - \protect\newline \protect\null - \fi\fi - \protect\nobreak - \protect\hskip\the\@tempdimb\relax - }% - %\message{\string\TTo@action: \meaning \TTo@action. }% - % get back to the baseline, regardless of its depth. - \vskip-\prevdepth - \prevdepth-99\p@ - \vskip\prevdepth - }}% - $$ - % Don't count the display as lines in the paragraph - \count@\prevgraf \advance\count@-4 \prevgraf\count@ - \TTo@action - %% \penalty\@m % to allow a penalized line break - \fi - \endgroup - \TTo@overlapfalse - \ignorespaces + \fi \fi - } + \ifdim\CurrentLineWidth<\z@ \CurrentLineWidth\z@\fi + % Enshrine the tab-to position; #1 might reference \CurrentLineWidth + \@tempdimb=#1\relax + \message{*** Tab to \the\@tempdimb, previous width is \the\CurrentLineWidth. ***}% + % Save width for possible return use + \xdef\TabPrevPos{\the\CurrentLineWidth}% + % Build the action to perform + \protected@xdef\TTo@action{% + \vrule\@width\z@\@depth\the\prevdepth + \ifdim\CurrentLineWidth>\@tempdimb + \ifTTo@overlap\else + \protect\newline \protect\null + \fi + \fi + \protect\nobreak + \protect\hskip\the\@tempdimb\relax + }% + %\message{\string\TTo@action: \meaning \TTo@action. }% + % get back to the baseline, regardless of its depth. + \vskip-\prevdepth + \prevdepth-99\p@ + \vskip\prevdepth + }}% + $$ + % Don't count the display as lines in the paragraph + \count@\prevgraf \advance\count@-4 \prevgraf\count@ + \TTo@action + %% \penalty\@m % to allow a penalized line break + \fi + \endgroup + \TTo@overlapfalse + \ignorespaces + \fi +} - % \tab -- to the next position - % \hskip so \tab\tab moves two positions - % Allow a (penalized but flexible) line-break right after the tab. - % - \newcommand\tab{\leavevmode\hskip2sp\tabto{\NextTabStop}% - \nobreak\hskip\z@\@plus 30\p@\penalty4000\hskip\z@\@plus-30\p@\relax} +% \tab -- to the next position +% \hskip so \tab\tab moves two positions +% Allow a (penalized but flexible) line-break right after the tab. +% +\newcommand\tab{\leavevmode\hskip2sp\tabto{\NextTabStop}% + \nobreak\hskip\z@\@plus 30\p@\penalty4000\hskip\z@\@plus-30\p@\relax} - % Expandable macro to select the next tab position from the list +% Expandable macro to select the next tab position from the list - \newcommand\NextTabStop{% - \expandafter \TTo@nexttabstop \TabStopList,\maxdimen,>% - } +\newcommand\NextTabStop{% + \expandafter \TTo@nexttabstop \TabStopList,\maxdimen,>% +} - \def\TTo@nexttabstop #1,{% - \ifdim#1<\CurrentLineWidth - \expandafter\TTo@nexttabstop - \else - \ifdim#1<0.9999\linewidth#1\else\z@\fi - \expandafter\strip@prefix - \fi - } - \def\TTo@foundtabstop#1>{} +\def\TTo@nexttabstop #1,{% + \ifdim#1<\CurrentLineWidth + \expandafter\TTo@nexttabstop + \else + \ifdim#1<0.9999\linewidth#1\else\z@\fi + \expandafter\strip@prefix + \fi +} +\def\TTo@foundtabstop#1>{} - \newcommand\TabPositions[1]{\def\TabStopList{\z@,#1}} +\newcommand\TabPositions[1]{\def\TabStopList{\z@,#1}} - \newcommand\NumTabs[1]{% - \def\TabStopList{}% - \@tempdimb\linewidth - \divide\@tempdimb by#1\relax - \advance\@tempdimb 1sp % counteract rounding-down by \divide - \CurrentLineWidth\z@ - \@whiledim\CurrentLineWidth<\linewidth\do {% - \edef\TabStopList{\TabStopList\the\CurrentLineWidth,}% - \advance\CurrentLineWidth\@tempdimb - }% - \edef\TabStopList{\TabStopList\linewidth}% - } +\newcommand\NumTabs[1]{% + \def\TabStopList{}% + \@tempdimb\linewidth + \divide\@tempdimb by#1\relax + \advance\@tempdimb 1sp % counteract rounding-down by \divide + \CurrentLineWidth\z@ + \@whiledim\CurrentLineWidth<\linewidth\do {% + \edef\TabStopList{\TabStopList\the\CurrentLineWidth,}% + \advance\CurrentLineWidth\@tempdimb + }% + \edef\TabStopList{\TabStopList\linewidth}% +} - % default setting of tab positions: - \TabPositions{\parindent,.5\linewidth} +% default setting of tab positions: +\TabPositions{\parindent,.5\linewidth} - \newif\ifTTo@overlap \TTo@overlapfalse +\newif\ifTTo@overlap \TTo@overlapfalse - \@ifundefined{predisplaydirection}{ - \let\TTo@Direction\predisplaysize - \let\predisplaydirection\@undefined - } - { - \let\TTo@Direction\predisplaydirection - } +\@ifundefined{predisplaydirection}{ + \let\TTo@Direction\predisplaysize + \let\predisplaydirection\@undefined +} +{ + \let\TTo@Direction\predisplaydirection +} diff --git a/Master/texmf-dist/doc/support/latexindent/success/table4.tex b/Master/texmf-dist/doc/support/latexindent/success/table4.tex new file mode 100644 index 00000000000..6f6e71323ce --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/table4.tex @@ -0,0 +1,22 @@ +% arara: indent: {overwrite: true, silent: on, localSettings: on} +\documentclass{article} +\usepackage{siunitx} + +\begin{document} +\begin{tabular}{% + l + S[table-format=3.0] + S[table-format=3.2] + S[table-format=2.2] + S[table-format=3.2] + S[table-format=-2.2] + S[table-format=3.2] + } + Latex & 360 & 101.77 & 10.71 & 101.86 & 64.60 & 127.20 \\ + Manufacturing & 360 & -7.33 & 12.59 & -7.24 & -49.00 & 22.00 \\ + Cons & 360 & -17.19 & 23.4 & -17.22 & -79.00 & 43.00 \\ + Apple and Orange & 360 & 3.38 & 13.84 & 3.60 & -47.00 & 29.00 \\ + Services and Harry & 104 & -4.96 & 20.8 & -4.81 & -57.00 & 30.00 \\ + Manchester & 360 & -9.29 & 8.64 & -9.26 & -35.00 & 8.00 \\ +\end{tabular} +\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/table5.tex b/Master/texmf-dist/doc/support/latexindent/success/table5.tex new file mode 100644 index 00000000000..e2750f40d78 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/table5.tex @@ -0,0 +1,35 @@ +\documentclass{article} + +\begin{document} + +\begin{tabular}{M|MMMMMMMMM} + & A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\\hline + A_1 & 0 & & & & & & & & \\ + A_2 & & 0 & & & & & & & \\ + A_3 & & & 0 & & & & & & \\ + A_4 & & & & 0 & & & & & \\ + A_5 & & & & & 0 & & & & \\ + A_6 & & & & & & 0 & & & \\ + A_7 & & & & & & & 0 & & \\ + A_8 & & & & & & & & 0 & \\ + A_9 & & & & & & & & & 0 \\ +\end{tabular} +\begin{tabularx}{M|MMMMMMMMM} + & A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\\hline + A_1 & 0 & & & & & & & & \\ + A_2 & & 0 & & & & & & & \\ + A_3 & & & 0 & & & & & & \\ + A_4 & & & & 0 & & & & & \\ + A_5 & & & & & 0 & & & & \\ + A_6 & & & & & & 0 & & & \\ + A_7 & & & & & & & 0 & & \\ + A_8 & & & & & & & & 0 & \\ + A_9 & & & & & & & & & 0 \\ +\end{tabularx} +\begin{align*} + CCI_n & = \frac{p_n-SMA(p_n)}{0.015 \cdot \sigma(p_n)}\\ + \textrm{wobei} & n = \textrm{Perioden, i.\,d.\,R. 20};\p_n = \textrm{Typischer Preis/Kurs};\ SMA(p_n) = \textrm{SMA der typischen Preise};\\ + & \sigma(p_n) = \textrm{Standardabweichung}\\ +\end{align*} +\end{document} + diff --git a/Master/texmf-dist/doc/support/latexindent/success/testHeadings-simple.tex b/Master/texmf-dist/doc/support/latexindent/success/testHeadings-simple.tex new file mode 100644 index 00000000000..565157dcaca --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/testHeadings-simple.tex @@ -0,0 +1,56 @@ +% arara: indent: {onlyDefault: no, overwrite: true, trace: on, silent: yes, localSettings: true} +\part{part} + part text + part text + \chapter{chapter long title} + chapter text + chapter text + \section[for the toc]{section} + section text + section text + \section[for the toc]{section} + section text + section text + \subsection[for the toc]{subsection} + subsection text + subsection text + \subsection[for the toc]{subsection} + subsection text + subsection text + \section[for the toc]{section} + section text + section text + \chapter{chapter} + chapter text + chapter text +\part{part} + part text + part text + \chapter[toc]{chapter title} + chapter text + chapter text + \section[for the toc]{section} + section text + section text + \subsubsection[for the toc]{subsubsection} + subsubsection text + subsubsection text + \paragraph{paragraph} + paragraph text + paragraph text + \subparagraph{subparagraph} + subparagraph text + subparagraph text + \section[for the toc]{section} + section text + section text + \subsubsection[for the toc]{subsubsection} + subsubsection text + subsubsection text + \paragraph{paragraph} + paragraph text + paragraph text + \subparagraph{subparagraph} + subparagraph text + subparagraph text + \chapter[somethingelse]{goes here} diff --git a/Master/texmf-dist/doc/support/latexindent/success/testItems.tex b/Master/texmf-dist/doc/support/latexindent/success/testItems.tex index 32e153eb19a..fba97784548 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/testItems.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/testItems.tex @@ -70,7 +70,7 @@ regular text some other stuff % here's a comment \end{list} - + \item some text some text some text some text some text some text diff --git a/Master/texmf-dist/doc/support/latexindent/success/testcls.cls b/Master/texmf-dist/doc/support/latexindent/success/testcls.cls index 8b0d1a0e73a..d4c23660c5a 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/testcls.cls +++ b/Master/texmf-dist/doc/support/latexindent/success/testcls.cls @@ -187,12 +187,14 @@ % - Page break after % - TODO: couldn't get pdfbookmark to point to this page instead of the % first page so it was removed. +%\begin{noindent} \xpretocmd{\tableofcontents}{% \begin{singlespace}}{}{} - \xapptocmd{\tableofcontents}{% - \end{singlespace}% - \pagestyle{plain}% - \clearpage}{}{} +\xapptocmd{\tableofcontents}{% +\end{singlespace}% +\pagestyle{plain}% +\clearpage}{}{} +%\end{noindent} % - Add dot leader for chapter levels \renewcommand\cftchapdotsep{\cftdotsep} @@ -201,23 +203,23 @@ % - Adjust indentation of levels % - Capitalize title entries, if requested \if@isu@capstoc -\renewcommand\cftchappresnum{\MakeUppercase{\chaptertitlename} } -\cftsetindents{chapter}{0em}{8em} -\cftsetindents{section}{2em}{0em} -\cftsetindents{subsection}{3em}{0em} -\renewcommand{\cftchapfont}{\MakeUppercase} + \renewcommand\cftchappresnum{\MakeUppercase{\chaptertitlename} } + \cftsetindents{chapter}{0em}{8em} + \cftsetindents{section}{2em}{0em} + \cftsetindents{subsection}{3em}{0em} + \renewcommand{\cftchapfont}{\MakeUppercase} \else -\renewcommand\cftchappresnum{\chaptertitlename\ } -\cftsetindents{chapter}{0em}{6em} -\cftsetindents{section}{1em}{0em} -\cftsetindents{subsection}{2em}{0em} + \renewcommand\cftchappresnum{\chaptertitlename\ } + \cftsetindents{chapter}{0em}{6em} + \cftsetindents{section}{1em}{0em} + \cftsetindents{subsection}{2em}{0em} \fi % - Remove section/subsection numbers from ToC by capturing % see idea at http://tex.stackexchange.com/questions/71123/remove-section-number-toc-entries-with-tocloft \if@isu@tocnumbersections@\else -\renewcommand{\cftsecpresnum}{\begin{lrbox}{\@tempboxa}} -\renewcommand{\cftsecaftersnum}{\end{lrbox}} + \renewcommand{\cftsecpresnum}{\begin{lrbox}{\@tempboxa}} + \renewcommand{\cftsecaftersnum}{\end{lrbox}} \fi \if@isu@tocnumbersubsections@\else @@ -229,10 +231,12 @@ % List of Figures: % - Single space % - Page break after +%\begin{noindent} \xpretocmd{\listoffigures}{% - \begin{singlespace}}{}{} - \xapptocmd{\listoffigures}{% - \end{singlespace}\clearpage}{}{} +\begin{singlespace}}{}{} +\xapptocmd{\listoffigures}{% +\end{singlespace}\clearpage}{}{} +%\end{noindent} % - Prepend the word "Figure" to the number \renewcommand\cftfigpresnum{Figure } @@ -242,10 +246,12 @@ % List of Tables: % - Single space % - Page break after +%\begin{noindent} \xpretocmd{\listoftables}{% \begin{singlespace}}{}{} - \xapptocmd{\listoftables}{% - \end{singlespace}\clearpage}{}{} +\xapptocmd{\listoftables}{% + \end{singlespace}\clearpage}{}{} +%\end{noindent} % - Prepend the word "Table" to the number \renewcommand\cfttabpresnum{Table } @@ -279,13 +285,13 @@ % Verify that we actually got some main matter \AfterEndDocument{ \if@isu@errormissingmainmatter@ - \ifdefined\@isu@gottitle - \ClassInfo{\@isu@classname}{Full dissertation mode} - \unless\ifdefined\@isu@gotmainmatter@ - \ClassError{\@isu@classname}{Missing \protect\mainmatter\space before your first real chapter!}{Missing mainmatter} - % \ClassError{\@isu@classname}{% - % \protect\mainmatter\space not called in your document expected before your first real chapter}{% - % You need to put \protect\mainmatter\space before your first real numbered chapter, typically your introduction.} + \ifdefined\@isu@gottitle + \ClassInfo{\@isu@classname}{Full dissertation mode} + \unless\ifdefined\@isu@gotmainmatter@ + \ClassError{\@isu@classname}{Missing \protect\mainmatter\space before your first real chapter!}{Missing mainmatter} + % \ClassError{\@isu@classname}{% + % \protect\mainmatter\space not called in your document expected before your first real chapter}{% + % You need to put \protect\mainmatter\space before your first real numbered chapter, typically your introduction.} \fi \fi \fi @@ -318,13 +324,13 @@ All rights reserved.} \renewcommand{\maketitle}{ \newcommand{\@isu@gottitle}{} % Assume that \maketitle implies typesetting a full thesis, not just a chapter. \ClassInfo{\@isu@classname}{Generating title page -- assuming we are typesetting a full dissertation.} - + \begin{titlepage} \setlength{\parindent}{0pt} % Don't you dare try to indent! \vbox to \textheight{ % Full-page box to contain everything and stretch everything. \begin{center} % Center this whole page \vspace*{12pt} % Designated blank line at the top of the page. - + \begin{singlespace} % Single-space this section, we manually add spacing. \textbf{\@title}\\ % Title in bold \@isu@maketwoblanklines % "two blank lines" @@ -332,34 +338,34 @@ All rights reserved.} \@isu@maketwoblanklines % "two blank lines" \textbf{\@author} % Author in bold \end{singlespace} - + \vfill{} % let LaTeX decide what "4-6 blank lines" should be. - + \begin{\isu@space} % Normal document spacing here. A \isu@submissiontype\ submitted to the graduate faculty\\ in partial fulfillment of the requirements of the degree of\\ \MakeUppercase{\isu@degree} % Doctor of Philosophy, etc. We enforce caps so they don't have to. \end{\isu@space} - + \@isu@maketwoblanklines % "two blank lines" - + \begin{singlespace} % Committee is single-spaced, looks like really long majors would be too. \isu@majorline\\ % "Major: MAJ (CONC)" or "Co-majors: MAJ; MAJ; \medskip % Unspecified space here, looks like just "one blank line" on sample Program of Study Committee:\\ \isu@committee % Committee, user-delimited with \\ and user-annoted with ", Major Professor" or "Co-major Professor" \end{singlespace} - + \vfill{} % let LaTeX decide what "7-8 blank lines" should be. \@isu@maketwoblanklines % Suggest it's a little longer than the other vfill. - + \begin{\isu@space} % Normal document spacing here Iowa State University\\ Ames, Iowa\\ \isu@gradyear % Newline after here, if needed, is in the copyright notice macro. \isu@copyrightnotice % Copyright line optional if copyright not formally filed. \end{\isu@space} - + \end{center} } \end{titlepage} diff --git a/Master/texmf-dist/doc/support/latexindent/success/theorem.tex b/Master/texmf-dist/doc/support/latexindent/success/theorem.tex index dcf9fe05a23..6541ed31ceb 100644 --- a/Master/texmf-dist/doc/support/latexindent/success/theorem.tex +++ b/Master/texmf-dist/doc/support/latexindent/success/theorem.tex @@ -32,7 +32,7 @@ \begin{document} \section{Introduction} Lorem ipsum sed nulla id risus adipiscing vulputate. - + \begin{example} Um consumidor financiou a compra de um veÃculo pagando 48 parcelas de \$800,00 mensais e a taxa de juros cobrada pela concessionária foi de 1,2\% a.m.. Qual era o valor à vista do automóvel adquirido? \newline @@ -42,6 +42,6 @@ PV = 800 \times \left[ \dfrac{0,772820}{0,021274} \right] \newline PV = \$29.061,79$ \end{example} - + Lorem ipsum sed nulla id risus adipiscing vulputate. \end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex b/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex new file mode 100644 index 00000000000..635192051f2 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex @@ -0,0 +1,21 @@ +% arara: indent: {overwrite: true, silent: on} +\documentclass{article} + +\begin{document} +\begin{verbatim}{% + l + S[table-format=3.0] + S[table-format=3.2] + S[table-format=2.2] + S[table-format=3.2] + S[table-format=-2.2] + S[table-format=3.2] + } + Latex & 360 & 101.77 & 10.71 & 101.86 & 64.60 & 127.20 \\ +Manufacturing & 360 & -7.33 & 12.59 & -7.24 & -49.00 & 22.00 \\ + Cons & 360 & -17.19 & 23.4 & -17.22 & -79.00 & 43.00 \\ + Apple and Orange & 360 & 3.38 & 13.84 & 3.60 & -47.00 & 29.00 \\ + Services and Harry & 104 & -4.96 & 20.8 & -4.81 & -57.00 & 30.00 \\ + Manchester & 360 & -9.29 & 8.64 & -9.26 & -35.00 & 8.00 \\ +\end{verbatim} +\end{document} 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 <<ENDQUOTE latexindent.pl version $versionNumber usage: latexindent.pl [options] [file][.tex] - -h help (see the documentation for detailed instructions and examples) - -o output to another file; sample usage + -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 the current file- a backup will be made, but still be careful - -s silent mode- no output will be given to the terminal - -t tracing mode- verbose information given to the log file - -l use localSettings.yaml (assuming it exists in the directory of your file) - -d ONLY use defaultSettings.yaml, ignore ALL user files - -c=cruft directory used to specify the location of backup files and indent.log + -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); @@ -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 <<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, @@ -127,23 +174,17 @@ ENDQUOTE } # output location of modules -if($FindBin::Script eq 'latexindent.pl' or ($FindBin::Script eq 'latexindent.exe' and $tracingMode )) -{ +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) - { + foreach my $moduleName (@listOfModules) { (my $file = $moduleName) =~ s|::|/|g; require $file . '.pm'; print $logfile "\t",$INC{$file .'.pm'},"\n"; } } -# cruft directory -print $logfile "Directory for backup files and indent.log: $cruftDirectory\n"; - # a quick options check -if($outputToFile and $overwrite) -{ +if($outputToFile and $overwrite) { print $logfile <<ENDQUOTE WARNING: @@ -156,8 +197,7 @@ ENDQUOTE } # can't call the script with MORE THAN 2 files -if(scalar(@ARGV)>2) -{ +if(scalar(@ARGV)>2) { for my $fh ($out,$logfile) {print $fh <<ENDQUOTE ERROR: @@ -194,8 +234,7 @@ ENDQUOTE # 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) -{ +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 @@ -208,24 +247,25 @@ ENDQUOTE exit(2); } +# 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 "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 <<ENDQUOTE ERROR There seems to be a yaml formatting error in defaultSettings.yaml @@ -238,50 +278,9 @@ ENDQUOTE exit(2); } -# setup the DEFAULT variables and hashes from the YAML file - -# scalar variables -my $defaultIndent = $defaultSettings->[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 <<ENDQUOTE WARNING: $indentconfig contains some invalid .yaml formatting- unable to read from it. @@ -332,144 +321,180 @@ WARNING: $indentconfig ENDQUOTE ; } -} -else -{ - if($onlyDefault) - { - print $logfile "Only default settings requested, not reading USER settings from $indentconfig\n"; - print $logfile "Ignoring localSettings.yaml\n" if($readLocalSettings); +} 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 - { + } else { # give the user instructions on where to put indentconfig.yaml or .indentconfig.yaml - print $logfile "Home directory is ",File::HomeDir->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 <<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"; - # original name of file - my $filename = $ARGV[0]; + # cruft directory + print $logfile "\tDirectory for backup files and indent.log: $cruftDirectory\n\n"; - # get the base file name, allowing for different extensions - my $backupFile = basename($filename,(".tex",".sty",".cls")); + 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) - { + 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=<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(<MAINFILE>) -{ +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 "\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(<MAINFILE>) # \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(<MAINFILE>) # 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(<MAINFILE>) # back on after the counting # # note the use of (?<!\\)% so that we don't match \% - if ( $_=~ m/(?<!\\)%.*/) - { + if ( $_=~ m/(?<!\\)%.*/) { s/((?<!\\)%.*)//; $trailingcomments=$1; @@ -757,8 +746,7 @@ while(<MAINFILE>) &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(<MAINFILE>) } # 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(<MAINFILE>) # 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(<MAINFILE>) # %* \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(<MAINFILE>) 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(<MAINFILE>) 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 <<ENDQUOTE @@ -901,57 +899,59 @@ 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"; +} 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,">",$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*(?<!\\)\[)/ - and (scalar($checkunmatchedbracket{$2}) - or $alwaysLookforSplitBrackets) - ) - { + and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets)) { # store the command name, because $2 # will not exist after the next match - $commandname = $2; - $matchedBRACKETS=0; + my $commandname = $2; + my $matchedBRACKETS=0; # match [ but don't match \[ $matchedBRACKETS++ while ($_ =~ /(?<!\\)\[/g); @@ -1258,18 +1245,11 @@ sub start_command_or_key_unmatched_brackets{ $matchedBRACKETS-- while ($_ =~ /(?<!\\)\]/g); # set the indentation - if($matchedBRACKETS != 0 ) - { + if($matchedBRACKETS != 0 ) { # tracing mode print $logfile "Line $lineCounter\t Found opening BRACKET [ $commandname\n" if($tracingMode); - &increase_indent($commandname); - - # store the command name - # and the value of $matchedBRACKETS - push(@commandstorebrackets,{commandname=>$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/(?<!\\)\[/g); @@ -1309,21 +1289,18 @@ sub end_command_or_key_unmatched_brackets{ # if we've matched up the BRACKETS then # we can decrease the indent by 1 level - if($matchedBRACKETS == 0) - { + 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 - { + } else { # otherwise we need to enter the new value # of $matchedBRACKETS and the value of $command # back into storage - push(@commandstorebrackets,{commandname=>$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 ($_ =~ /(?<!\\){/g); @@ -1378,50 +1349,46 @@ sub start_command_or_key_unmatched_braces{ print $logfile "Line $lineCounter\t matchedbraces = $matchedbraces\n" if($tracingMode); # set the indentation - if($matchedbraces > 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/(((?<!\\){)|((?<!\\)}))/g) - { + while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) { # store the match, either { or } my $braceType = $1; - # exit the loop if @commandstore is empty - last if(!@commandstore); + # 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 - $commanddetails = pop(@commandstore); - $commandname = $commanddetails->{'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/(((?<!\\){)|((?<!\\)}))/g) - { + while ($_ =~ m/(((?<!\\){)|((?<!\\)}))/g) { # store the match, either { or } my $braceType = $1; - # exit the loop if @commandstore is empty - last if(!@commandstore); + # 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 - $commanddetails = pop(@commandstore); - $commandname = $commanddetails->{'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/((?<!\\)%.*$)/) - { + if($row =~ m/((?<!\\)%.*$)/) { $row =~ s/((?<!\\)%.*)/%TC/; $trailingcomments=$1; } @@ -1864,8 +1781,7 @@ sub format_block{ $maxNumberAmpersands = $currentNumberAmpersands if($currentNumberAmpersands > $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/((?<!\\)%.*$)/) - { + if($row =~ m/((?<!\\)%.*$)/) { $row =~ s/((?<!\\)%.*)/%TC/; $trailingcomments=$1; } @@ -1916,8 +1828,7 @@ sub format_block{ # loop through each column element # removing leading and trailing space - foreach $column (@tmprow) - { + foreach $column (@tmprow) { # increment column counter $aligncolcounter++; @@ -1927,18 +1838,14 @@ sub format_block{ # assign string size to the array $stringsize{$alignrowcounter.$aligncolcounter}=length($column); - if(length($column)==0) - { + if(length($column)==0){ $column=" "; } # put the row back together - if ($aligncolcounter ==0) - { + if ($aligncolcounter ==0){ $tmpstring = $column; - } - else - { + } else { $tmpstring .= "&".$column; } } @@ -1949,15 +1856,12 @@ sub format_block{ $tmpstring .= $linebreak; # put trailing comments back on - if($trailingcomments) - { + if($trailingcomments) { $tmpstring =~ s/%TC/$trailingcomments/; } push(@tmpblock,$tmpstring); - } - else - { + } else { # if there are no & then use the # NOFORMATTING token # remove leading space @@ -1967,16 +1871,12 @@ sub format_block{ } # calculate the maximum string size of each column - for($j=0;$j<=$aligncolcounter;$j++) - { + for($j=0;$j<=$aligncolcounter;$j++) { $maxmcolstrlength=0; - for($i=0; $i<=$alignrowcounter;$i++) - { + for($i=0; $i<=$alignrowcounter;$i++) { # make sure the stringsize is defined - if(defined $stringsize{$i.$j}) - { - if ($stringsize{$i.$j}>$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/((?<!\\)%.*$)/) - { + 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) - { + 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}; + } + +} |