From 990e60c6ed4437e5b632b7c9acf7f2237bbda871 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 24 Feb 2017 22:07:42 +0000 Subject: latexindent (23feb17) git-svn-id: svn://tug.org/texlive/trunk@43326 c570f23f-e606-0410-a88d-b1316a301751 --- .../linked_scripts/latexindent/latexindent.pl | 2132 +------ Master/bin/win32/latexindent.exe | Bin 5424173 -> 5578613 bytes Master/texmf-dist/doc/support/latexindent/README | 4 +- .../doc/support/latexindent/appendices.tex | 192 + .../latexindent/documentation/latexindent.pdf | Bin 280224 -> 0 bytes .../latexindent/documentation/latexindent.tex | 1512 ----- .../texmf-dist/doc/support/latexindent/indent.yaml | 38 - .../doc/support/latexindent/latexindent.pdf | Bin 0 -> 524530 bytes .../doc/support/latexindent/latexindent.tex | 467 ++ Master/texmf-dist/doc/support/latexindent/logo.tex | 20 + .../doc/support/latexindent/references.tex | 4 + .../sec-conclusions-know-limitations.tex | 38 + .../support/latexindent/sec-default-user-local.tex | 492 ++ .../doc/support/latexindent/sec-demonstration.tex | 40 + .../doc/support/latexindent/sec-how-to-use.tex | 248 + .../latexindent/sec-indent-config-and-settings.tex | 154 + .../doc/support/latexindent/sec-introduction.tex | 47 + .../doc/support/latexindent/sec-the-m-switch.tex | 555 ++ .../subsec-commands-and-their-options.tex | 139 + .../subsec-conflicting-poly-switches.tex | 137 + .../subsec-noAdditionalIndent-indentRules.tex | 24 + .../subsec-partnering-poly-switches.tex | 47 + .../subsubsec-commands-with-arguments.tex | 100 + .../subsubsec-environments-and-their-arguments.tex | 255 + .../subsubsec-environments-with-items.tex | 59 + .../doc/support/latexindent/subsubsec-headings.tex | 93 + .../doc/support/latexindent/subsubsec-ifelsefi.tex | 70 + .../subsubsec-no-add-remaining-code-blocks.tex | 109 + .../doc/support/latexindent/subsubsec-special.tex | 60 + .../success/alignmentoutsideEnvironments.tex | 29 - .../doc/support/latexindent/success/bigTest.tex | 293 - .../doc/support/latexindent/success/braceTest.tex | 57 - .../support/latexindent/success/braceTestsmall.tex | 31 - .../support/latexindent/success/bracketTest.tex | 6 - .../support/latexindent/success/conditional.tex | 12 - .../support/latexindent/success/environments.tex | 39 - .../support/latexindent/success/figureValign.tex | 124 - .../support/latexindent/success/filecontents.tex | 73 - .../support/latexindent/success/filecontents1.tex | 18 - .../support/latexindent/success/filecontents2.tex | 21 - .../doc/support/latexindent/success/ifelsefi.tex | 103 - .../support/latexindent/success/ifelsefiONE.tex | 43 - .../support/latexindent/success/ifelsefiSmall.tex | 10 - .../doc/support/latexindent/success/items1.tex | 10 - .../doc/support/latexindent/success/items2.tex | 21 - .../doc/support/latexindent/success/items3.tex | 22 - .../doc/support/latexindent/success/items4.tex | 22 - .../doc/support/latexindent/success/matrix.tex | 14 - .../support/latexindent/success/multipleBraces.tex | 15 - .../latexindent/success/nestedalignment.tex | 33 - .../latexindent/success/nestedalignment1.tex | 25 - .../doc/support/latexindent/success/outputfile.tex | 57 - .../doc/support/latexindent/success/preamble.tex | 29 - .../doc/support/latexindent/success/pstricks1.tex | 26 - .../doc/support/latexindent/success/pstricks2.tex | 68 - .../doc/support/latexindent/success/pstricks3.tex | 49 - .../support/latexindent/success/sampleAFTER.tex | 5819 -------------------- .../support/latexindent/success/sampleBEFORE.tex | 5819 -------------------- .../doc/support/latexindent/success/stylefile.tex | 135 - .../doc/support/latexindent/success/table1.tex | 22 - .../doc/support/latexindent/success/table2.tex | 26 - .../doc/support/latexindent/success/table3.tex | 26 - .../doc/support/latexindent/success/table4.tex | 22 - .../doc/support/latexindent/success/table5.tex | 35 - .../latexindent/success/testHeadings-simple.tex | 56 - .../support/latexindent/success/testHeadings.tex | 59 - .../support/latexindent/success/testHeadings1.tex | 25 - .../doc/support/latexindent/success/testItems.tex | 94 - .../doc/support/latexindent/success/testcls.cls | 375 -- .../doc/support/latexindent/success/theorem.tex | 47 - .../doc/support/latexindent/success/tikz1.tex | 88 - .../doc/support/latexindent/success/tikz2.tex | 61 - .../doc/support/latexindent/success/tikz3.tex | 53 - .../doc/support/latexindent/success/tikz4.tex | 27 - .../doc/support/latexindent/success/tikz5.tex | 34 - .../doc/support/latexindent/success/torusPGF.tex | 20 - .../support/latexindent/success/torusPSTricks.tex | 18 - .../latexindent/success/trailingComments.tex | 7 - .../doc/support/latexindent/success/verbatim1.tex | 21 - .../LatexIndent/AlignmentAtAmpersand.pm | 255 + .../scripts/latexindent/LatexIndent/Arguments.pm | 380 ++ .../latexindent/LatexIndent/BackUpFileProcedure.pm | 135 + .../scripts/latexindent/LatexIndent/BlankLines.pm | 108 + .../scripts/latexindent/LatexIndent/Braces.pm | 188 + .../scripts/latexindent/LatexIndent/Command.pm | 178 + .../scripts/latexindent/LatexIndent/Document.pm | 335 ++ .../latexindent/LatexIndent/DoubleBackSlash.pm | 45 + .../scripts/latexindent/LatexIndent/Environment.pm | 128 + .../latexindent/LatexIndent/FileContents.pm | 230 + .../latexindent/LatexIndent/FileExtension.pm | 99 + .../latexindent/LatexIndent/GetYamlSettings.pm | 471 ++ .../scripts/latexindent/LatexIndent/Heading.pm | 240 + .../latexindent/LatexIndent/HiddenChildren.pm | 190 + .../LatexIndent/HorizontalWhiteSpace.pm | 62 + .../scripts/latexindent/LatexIndent/IfElseFi.pm | 276 + .../scripts/latexindent/LatexIndent/Indent.pm | 371 ++ .../scripts/latexindent/LatexIndent/Item.pm | 149 + .../LatexIndent/KeyEqualsValuesBraces.pm | 122 + .../scripts/latexindent/LatexIndent/LogFile.pm | 166 + .../latexindent/LatexIndent/MandatoryArgument.pm | 130 + .../latexindent/LatexIndent/ModifyLineBreaks.pm | 174 + .../LatexIndent/NamedGroupingBracesBrackets.pm | 71 + .../latexindent/LatexIndent/OptionalArgument.pm | 115 + .../scripts/latexindent/LatexIndent/Preamble.pm | 64 + .../latexindent/LatexIndent/RoundBrackets.pm | 100 + .../scripts/latexindent/LatexIndent/Special.pm | 184 + .../scripts/latexindent/LatexIndent/Switches.pm | 37 + .../scripts/latexindent/LatexIndent/Tokens.pm | 68 + .../latexindent/LatexIndent/TrailingComments.pm | 112 + .../LatexIndent/UnNamedGroupingBracesBrackets.pm | 135 + .../scripts/latexindent/LatexIndent/Verbatim.pm | 296 + .../scripts/latexindent/defaultSettings.yaml | 456 +- .../texmf-dist/scripts/latexindent/latexindent.pl | 2132 +------ Master/tlpkg/libexec/ctan2tds | 8 +- 114 files changed, 9320 insertions(+), 20065 deletions(-) create mode 100644 Master/texmf-dist/doc/support/latexindent/appendices.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf delete mode 100644 Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/indent.yaml create mode 100644 Master/texmf-dist/doc/support/latexindent/latexindent.pdf create mode 100644 Master/texmf-dist/doc/support/latexindent/latexindent.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/logo.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/references.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-conclusions-know-limitations.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-default-user-local.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-demonstration.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-how-to-use.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-indent-config-and-settings.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-introduction.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/sec-the-m-switch.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsec-commands-and-their-options.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsec-conflicting-poly-switches.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsec-noAdditionalIndent-indentRules.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsec-partnering-poly-switches.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-commands-with-arguments.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-environments-and-their-arguments.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-environments-with-items.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-headings.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-ifelsefi.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-no-add-remaining-code-blocks.tex create mode 100644 Master/texmf-dist/doc/support/latexindent/subsubsec-special.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/bigTest.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/braceTest.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/braceTestsmall.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/conditional.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/environments.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/figureValign.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/filecontents.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/filecontents2.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/ifelsefi.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/ifelsefiONE.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/items1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/items2.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/items3.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/items4.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/matrix.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/multipleBraces.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/outputfile.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/preamble.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/pstricks1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/pstricks2.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/pstricks3.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/stylefile.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/table1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/table2.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/table3.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/table4.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/table5.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/testHeadings-simple.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/testHeadings.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/testHeadings1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/testItems.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/testcls.cls delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/theorem.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/tikz1.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/tikz2.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/tikz3.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/tikz4.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/tikz5.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/torusPGF.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/torusPSTricks.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/trailingComments.tex delete mode 100644 Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/BackUpFileProcedure.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Braces.pm create mode 100755 Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/DoubleBackSlash.pm create mode 100755 Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/FileExtension.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/HiddenChildren.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/HorizontalWhiteSpace.pm create mode 100755 Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm create mode 100755 Master/texmf-dist/scripts/latexindent/LatexIndent/KeyEqualsValuesBraces.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/MandatoryArgument.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm create mode 100755 Master/texmf-dist/scripts/latexindent/LatexIndent/NamedGroupingBracesBrackets.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/OptionalArgument.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/RoundBrackets.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Switches.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/TrailingComments.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/UnNamedGroupingBracesBrackets.pm create mode 100644 Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm diff --git a/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl b/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl index cdd979a8ccf..06adc58a1b8 100755 --- a/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl +++ b/Build/source/texk/texlive/linked_scripts/latexindent/latexindent.pl @@ -11,57 +11,34 @@ # # See http://www.gnu.org/licenses/. # -# For details of how to use this file, please see readme.txt +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl -# load packages/modules: assume strict and warnings are part of every perl distribution use strict; use warnings; +use FindBin; # help find defaultSettings.yaml +use Getopt::Long; # to get the switches/options/flags -# list of modules -my @listOfModules = ('FindBin','YAML::Tiny','File::Copy','File::Basename','Getopt::Long','File::HomeDir'); - -# check the other modules are available -foreach my $moduleName (@listOfModules) { - # references: - # http://stackoverflow.com/questions/251694/how-can-i-check-if-i-have-a-perl-module-before-using-it - # http://stackoverflow.com/questions/1917261/how-can-i-dynamically-include-perl-modules-without-using-eval - eval { - (my $file = $moduleName) =~ s|::|/|g; - require $file . '.pm'; - $moduleName->import(); - 1; - } or die "$moduleName Perl Module not currently installed; please install the module, and then try running latexindent.pl again; exiting"; -} - -# now that we have confirmed the modules are available, load them -use FindBin; # help find defaultSettings.yaml -use YAML::Tiny; # interpret defaultSettings.yaml and other potential settings files -use File::Copy; # to copy the original file to backup (if overwrite option set) -use File::Basename; # to get the filename and directory path -use Getopt::Long; # to get the switches/options/flags -use File::HomeDir; # to get users home directory, regardless of OS +# use lib to make sure that @INC contains the latexindent directory +use lib $FindBin::RealBin; +use LatexIndent::Document; # get the options -my $overwrite; -my $outputToFile; -my $silentMode; -my $tracingMode; -my $tracingModeVeryDetailed; -my $readLocalSettings=0; -my $onlyDefault; -my $showhelp; -my $cruftDirectory; +my %switches = (readLocalSettings=>0); GetOptions ( - "overwrite|w"=>\$overwrite, -"outputfile|o"=>\$outputToFile, -"silent|s"=>\$silentMode, -"trace|t"=>\$tracingMode, -"ttrace|tt"=>\$tracingModeVeryDetailed, -"local|l:s"=>\$readLocalSettings, -"onlydefault|d"=>\$onlyDefault, -"help|h"=>\$showhelp, -"cruft|c=s"=>\$cruftDirectory, + "silent|s"=>\$switches{silentMode}, + "trace|t"=>\$switches{trace}, + "ttrace|tt"=>\$switches{ttrace}, + "local|l:s"=>\$switches{readLocalSettings}, + "onlydefault|d"=>\$switches{onlyDefault}, + "overwrite|w"=>\$switches{overwrite}, + "outputfile|o=s"=>\$switches{outputToFile}, + "modifylinebreaks|m"=>\$switches{modifyLineBreaks}, + "logfile|g=s"=>\$switches{logFileName}, + "help|h"=>\$switches{showhelp}, + "cruft|c=s"=>\$switches{cruftDirectory}, ); # check local settings doesn't interfer with reading the file; @@ -74,20 +51,9 @@ GetOptions ( # # In such circumstances, we correct the mistake by assuming that # the only argument is the file to be indented, and place it in @ARGV -if($readLocalSettings and scalar(@ARGV) < 1) { - push(@ARGV,$readLocalSettings); - $readLocalSettings = ''; -} - -# this can also happen if the script is called as -# -# latexindent.pl -o -l myfile.tex outputfile.tex -# -# in which case, the GetOptions routine mistakes myfile.tex -# as the optional parameter to the l flag. -if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) { - unshift(@ARGV,$readLocalSettings); - $readLocalSettings = ''; +if($switches{readLocalSettings} and scalar(@ARGV) < 1) { + push(@ARGV,$switches{readLocalSettings}); + $switches{readLocalSettings} = ''; } # default value of readLocalSettings @@ -95,2054 +61,10 @@ if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) { # latexindent -l myfile.tex # # means that we wish to use localSettings.yaml -if(defined($readLocalSettings) and ($readLocalSettings eq '')){ - $readLocalSettings = 'localSettings.yaml'; -} - -# detailed tracing mode also implies regular tracing mode -$tracingMode = $tracingModeVeryDetailed ? 1 : $tracingMode; - -# version number -my $versionNumber = "2.2"; - -# Check the number of input arguments- if it is 0 then simply -# display the list of options (like a manual) -if(scalar(@ARGV) < 1 or $showhelp) { - print < - used to specify the location of backup files and indent.log -ENDQUOTE - ; - exit(2); -} - -# set up default for cruftDirectory using the one from the input file, -# unless it has been specified using -c="/some/directory" -$cruftDirectory=dirname $ARGV[0] unless(defined($cruftDirectory)); - -die "Could not find directory $cruftDirectory\nExiting, no indentation done." if(!(-d $cruftDirectory)); - -# we'll be outputting to the logfile and to standard output -my $logfile; -my $out = *STDOUT; - -# open the log file -open($logfile,">","$cruftDirectory/indent.log") or die "Can't open indent.log"; - -# output time to log file -my $time = localtime(); -print $logfile $time; - -# output version to log file -print $logfile <2) { - for my $fh ($out,$logfile) {print $fh <new; - -# Open defaultSettings.yaml -$defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" ); -print $logfile "\tReading defaultSettings.yaml from $FindBin::RealBin/defaultSettings.yaml\n\n" if($defaultSettings); - -# if latexindent.exe is invoked from TeXLive, then defaultSettings.yaml won't be in -# the same directory as it; we need to navigate to it -if(!$defaultSettings) { - $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml"); - print $logfile "\tReading defaultSettings.yaml (2nd attempt, TeXLive, Windows) from $FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml\n\n" if($defaultSettings); -} - -# if both of the above attempts have failed, we need to exit -if(!$defaultSettings) { - for my $fh ($out,$logfile) { - print $fh <[0]}; - -# empty array to store the paths -my @absPaths; - -# scalar to read user settings -my $userSettings; - -# get information about user settings- first check if indentconfig.yaml exists -my $indentconfig = File::HomeDir->my_home . "/indentconfig.yaml"; -# if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml -$indentconfig = File::HomeDir->my_home . "/.indentconfig.yaml" if(! -e $indentconfig); - -if ( -e $indentconfig and !$onlyDefault ) { - print $logfile "\tReading path information from $indentconfig\n"; - # if both indentconfig.yaml and .indentconfig.yaml exist - if ( -e File::HomeDir->my_home . "/indentconfig.yaml" and -e File::HomeDir->my_home . "/.indentconfig.yaml") { - print $logfile File::HomeDir->my_home,"/.indentconfig.yaml has been found, but $indentconfig takes priority\n"; - } elsif ( -e File::HomeDir->my_home . "/indentconfig.yaml" ) { - print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/.indentconfig.yaml can be used\n"; - - } elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) { - print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/indentconfig.yaml can be used\n"; - } - - # read the absolute paths from indentconfig.yaml - $userSettings = YAML::Tiny->read( "$indentconfig" ); - - # integrity check - if($userSettings) { - print $logfile "\t",Dump \%{$userSettings->[0]}; - print $logfile "\n"; - @absPaths = @{$userSettings->[0]->{paths}}; - } else { - print $logfile <my_home,"\n"; - print $logfile "\tTo specify user settings you would put indentconfig.yaml here: \n\t",File::HomeDir->my_home,"/indentconfig.yaml\n\n"; - print $logfile "\tAlternatively, you can use the hidden file .indentconfig.yaml as: \n\t",File::HomeDir->my_home,"/.indentconfig.yaml\n\n"; - } -} - -# get information about LOCAL settings, assuming that $readLocalSettings exists -my $directoryName = dirname $ARGV[0]; - -# add local settings to the paths, if appropriate -if ( (-e "$directoryName/$readLocalSettings") and $readLocalSettings and !(-z "$directoryName/$readLocalSettings")) { - print $logfile "\tAdding $directoryName/$readLocalSettings to paths\n\n"; - push(@absPaths,"$directoryName/$readLocalSettings"); -} elsif ( !(-e "$directoryName/$readLocalSettings") and $readLocalSettings) { - print $logfile "\tWARNING yaml file not found: \n\t$directoryName/$readLocalSettings not found\n"; - print $logfile "\t\tcarrying on without it.\n"; -} - -# read in the settings from each file -foreach my $settings (@absPaths) { - # check that the settings file exists and that it isn't empty - if (-e $settings and !(-z $settings)) { - print $logfile "\tReading USER settings from $settings\n"; - $userSettings = YAML::Tiny->read( "$settings" ); - - # if we can read userSettings - if($userSettings) { - # update the MASTER setttings to include updates from the userSettings - while(my($userKey, $userValue) = each %{$userSettings->[0]}) { - # the update approach is slightly different for hashes vs scalars/arrays - if (ref($userValue) eq "HASH") { - while(my ($userKeyFromHash,$userValueFromHash) = each %{$userSettings->[0]{$userKey}}) { - $masterSettings{$userKey}{$userKeyFromHash} = $userValueFromHash; - } - } else { - $masterSettings{$userKey} = $userValue; - } - } - # output settings to $logfile - if($masterSettings{logFilePreferences}{showEveryYamlRead}){ - print $logfile Dump \%{$userSettings->[0]}; - print $logfile "\n"; - } else { - print $logfile "\t\tNot showing settings in the log file, see showEveryYamlRead.\n"; - } - } else { - # otherwise print a warning that we can not read userSettings.yaml - print $logfile "WARNING\n\t$settings \n\t contains invalid yaml format- not reading from it\n"; - } - } else { - # otherwise keep going, but put a warning in the log file - print $logfile "\nWARNING\n\t",File::HomeDir->my_home,"/indentconfig.yaml\n"; - if (-z $settings) { - print $logfile "\tspecifies $settings \n\tbut this file is EMPTY- not reading from it\n\n" - } else { - print $logfile "\tspecifies $settings \n\tbut this file does not exist- unable to read settings from this file\n\n" - } - } -} - -# some people may wish to see showAlmagamatedSettings -# which details the overall state of the settings modified -# from the default in various user files -if($masterSettings{logFilePreferences}{showAlmagamatedSettings}){ - print $logfile "Almagamated/overall settings to be used:\n"; - print $logfile Dump \%masterSettings ; -} - -# scalar variables -my $defaultIndent = $masterSettings{defaultIndent}; -my $alwaysLookforSplitBraces = $masterSettings{alwaysLookforSplitBraces}; -my $alwaysLookforSplitBrackets = $masterSettings{alwaysLookforSplitBrackets}; -my $backupExtension = $masterSettings{backupExtension}; -my $indentPreamble = $masterSettings{indentPreamble}; -my $onlyOneBackUp = $masterSettings{onlyOneBackUp}; -my $maxNumberOfBackUps = $masterSettings{maxNumberOfBackUps}; -my $removeTrailingWhitespace = $masterSettings{removeTrailingWhitespace}; -my $cycleThroughBackUps = $masterSettings{cycleThroughBackUps}; - -# hash variables -my %lookForAlignDelims= %{$masterSettings{lookForAlignDelims}}; -my %indentRules= %{$masterSettings{indentRules}}; -my %verbatimEnvironments= %{$masterSettings{verbatimEnvironments}}; -my %noIndentBlock= %{$masterSettings{noIndentBlock}}; -my %checkunmatched= %{$masterSettings{checkunmatched}}; -my %checkunmatchedELSE= %{$masterSettings{checkunmatchedELSE}}; -my %checkunmatchedbracket= %{$masterSettings{checkunmatchedbracket}}; -my %noAdditionalIndent= %{$masterSettings{noAdditionalIndent}}; -my %indentAfterHeadings= %{$masterSettings{indentAfterHeadings}}; -my %indentAfterItems= %{$masterSettings{indentAfterItems}}; -my %itemNames= %{$masterSettings{itemNames}}; -my %constructIfElseFi= %{$masterSettings{constructIfElseFi}}; -my %fileExtensionPreference= %{$masterSettings{fileExtensionPreference}}; -my %fileContentsEnvironments= %{$masterSettings{fileContentsEnvironments}}; - -# original name of file -my $fileName = $ARGV[0]; - -# sort the file extensions by preference -my @fileExtensions = sort { $fileExtensionPreference{$a} <=> $fileExtensionPreference{$b} } keys(%fileExtensionPreference); - -# get the base file name, allowing for different extensions (possibly no extension) -my ($dir, $name, $ext) = fileparse($fileName, @fileExtensions); - -# quick check to make sure given file type is supported -if( -e $ARGV[0] and !$ext ){ -for my $fh ($out,$logfile) {print $fh <1) { - print $logfile "\t WARNING: onlyOneBackUp=$onlyOneBackUp and maxNumberOfBackUps: $maxNumberOfBackUps\n"; - print $logfile "\t\t setting onlyOneBackUp=0 which will allow you to reach $maxNumberOfBackUps back ups\n"; - $onlyOneBackUp = 0; - } - - # if the user has specified that $maxNumberOfBackUps = 1 then - # they only want one backup - if($maxNumberOfBackUps==1) { - $onlyOneBackUp=1 ; - print $logfile "\t FYI: you set maxNumberOfBackUps=1, so I'm setting onlyOneBackUp: 1 \n"; - } elsif($maxNumberOfBackUps<=0 and !$onlyOneBackUp) { - $onlyOneBackUp=0 ; - $maxNumberOfBackUps=-1; - } - - # if onlyOneBackUp is set, then the backup file will - # be overwritten each time - if($onlyOneBackUp) { - $backupFile .= $backupExtension; - print $logfile "\tcopying $fileName to $backupFile\n"; - print $logfile "\t$backupFile was overwritten\n\n" if (-e $backupFile); - } else { - # start with a backup file .bak0 (or whatever $backupExtension is present) - my $backupCounter = 0; - $backupFile .= $backupExtension.$backupCounter; - - # if it exists, then keep going: .bak0, .bak1, ... - while (-e $backupFile or $maxNumberOfBackUps>1) { - if($backupCounter==$maxNumberOfBackUps) { - print $logfile "\t maxNumberOfBackUps reached ($maxNumberOfBackUps)\n"; - - # some users may wish to cycle through back up files, e.g: - # copy myfile.bak1 to myfile.bak0 - # copy myfile.bak2 to myfile.bak1 - # copy myfile.bak3 to myfile.bak2 - # - # current back up is stored in myfile.bak4 - if($cycleThroughBackUps) { - print $logfile "\t cycleThroughBackUps detected (see cycleThroughBackUps) \n"; - for(my $i=1;$i<=$maxNumberOfBackUps;$i++) { - # remove number from backUpFile - my $oldBackupFile = $backupFile; - $oldBackupFile =~ s/$backupExtension.*/$backupExtension/; - my $newBackupFile = $oldBackupFile; - - # add numbers back on - $oldBackupFile .= $i; - $newBackupFile .= $i-1; - - # check that the oldBackupFile exists - if(-e $oldBackupFile){ - print $logfile "\t\t copying $oldBackupFile to $newBackupFile \n"; - copy($oldBackupFile,$newBackupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n"; - } - } - } - - # rest maxNumberOfBackUps - $maxNumberOfBackUps=1 ; - last; # break out of the loop - } elsif(!(-e $backupFile)) { - $maxNumberOfBackUps=1 ; - last; # break out of the loop - } - print $logfile "\t $backupFile already exists, incrementing by 1...\n"; - $backupCounter++; - $backupFile =~ s/$backupExtension.*/$backupExtension$backupCounter/; - } - print $logfile "\n\t copying $fileName to $backupFile\n\n"; - } - - # output these lines to the log file - print $logfile "\tBackup file: ",$backupFile,"\n"; - print $logfile "\tOverwriting file: ",$fileName,"\n\n"; - copy($fileName,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n"; -} - -if(!($outputToFile or $overwrite)) { - print $logfile "Just out put to the terminal :)\n\n" if !$silentMode ; -} - - -# scalar variables -my $line; # $line: takes the $line of the file -my $inpreamble=!$indentPreamble; - # $inpreamble: switch to determine if in - # preamble or not -my $inverbatim=0; # $inverbatim: switch to determine if in - # a verbatim environment or not -my $delimiters=0; # $delimiters: switch that governs if - # we need to check for & or not -my $trailingcomments; # $trailingcomments stores the comments at the end of - # a line -my $lineCounter=0; # $lineCounter keeps track of the line number -my $inIndentBlock=0; # $inindentblock: switch to determine if in - # a inindentblock or not -my $inFileContents=0; # $inFileContents: switch to determine if we're in a filecontents environment - -# array variables -my @lines; # @lines: stores the newly indented lines -my @mainfile; # @mainfile: stores input file; used to - # grep for \documentclass - -# array of hashes, containing details of commands & environments -my @masterIndentationArrayOfHashes; - -# check to see if the current file has \documentclass, if so, then -# it's the main file, if not, then it doesn't have preamble -open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; - @mainfile=; -close(MAINFILE); - -# if the MAINFILE doesn't have a \documentclass statement, then -# it shouldn't have preamble -if(scalar(@{[grep(m/^\s*\\documentclass/, @mainfile)]})==0) { - $inpreamble=0; - - print $logfile "Trace:\tNo documentclass detected, assuming no preamble\n" if($tracingMode); -} else { - print $logfile "Trace:\t documentclass detected, assuming preamble\n" if($tracingMode); -} - -# the previous OPEN command puts us at the END of the file -open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; - -# loop through the lines in the INPUT file -while() { - # increment the line counter - $lineCounter++; - - # very detailed output to logfile - if($tracingModeVeryDetailed){ - if( @masterIndentationArrayOfHashes){ - print $logfile "\nLine $lineCounter\t (detailed trace) indentation hash: \n" if($tracingMode); - for my $href ( @masterIndentationArrayOfHashes) { - print $logfile Dump \%{$href}; - } - } - } - - # tracing mode - print $logfile $masterSettings{logFilePreferences}{traceModeBetweenLines} if($tracingMode and !($inpreamble or $inverbatim or $inIndentBlock)); - - # check to see if we're still in the preamble - # or in a verbatim environment or in IndentBlock - if(!($inpreamble or $inverbatim or $inIndentBlock)) { - # if not, remove all leading spaces and tabs - # from the current line, assuming it isn't empty - s/^\t*// if($_ !~ /^((\s*)|(\t*))*$/); - s/^\s*// if($_ !~ /^((\s*)|(\t*))*$/); - - # tracing mode - print $logfile "Line $lineCounter\t removing leading spaces\n" if($tracingMode); - } else { - # otherwise check to see if we've reached the main - # part of the document - if(m/^\s*\\begin\{document\}/ and !$inFileContents and !$inverbatim) { - $inpreamble = 0; - - # tracing mode - print $logfile "Line $lineCounter\t \\begin{document} found, switching indentation searches on. \n" if($tracingMode); - } else { - # tracing mode - if($inpreamble) { - print $logfile "Line $lineCounter\t still in PREAMBLE, leaving exisiting leading space (see indentPreamble)\n" if($tracingMode); - } elsif($inverbatim) { - print $logfile "Line $lineCounter\t in VERBATIM-LIKE environment, leaving exisiting leading space\n" if($tracingMode); - } elsif($inIndentBlock) { - print $logfile "Line $lineCounter\t in NO INDENT BLOCK, leaving exisiting leading space\n" if($tracingMode); - } - } - } - - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - - # check to see if we're ending a filecontents environment - if( $_ =~ m/^\s*\\end\{(.*?)\}/ and $fileContentsEnvironments{$1} and $inFileContents){ - print $logfile "Line $lineCounter\t Found END of filecontents environment (see fileContentsEnvironments)\n" if($tracingMode); - $inFileContents = 0; - } - - # set the delimiters switch - $delimiters = @masterIndentationArrayOfHashes?$masterIndentationArrayOfHashes[-1]{alignmentDelimiters}:0; - - if($inverbatim){ - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in VERBATIM-LIKE environment, looking for $masterIndentationArrayOfHashes[-1]{end} \n" if($tracingMode); - } elsif($inIndentBlock) { - print $logfile "Line $lineCounter\t in NO INDENT BLOCK, doing nothing\n" if($tracingMode); - } elsif($delimiters) { - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in ALIGNMENT BLOCK environment, looking for $masterIndentationArrayOfHashes[-1]{end}\n" if($tracingMode); - } elsif($inpreamble and !$inFileContents) { - print $logfile "Line $lineCounter\t In preamble, looking for \\begin{document}\n" if($tracingMode); - } elsif($inpreamble and $inFileContents) { - print $logfile "Line $lineCounter\t In preamble, in filecontents environment\n" if($tracingMode); - } else { - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: looking for reasons to DECREASE indentation of CURRENT line \n" if($tracingMode); - } - - # check to see if we have \end{something} or \] - &at_end_of_env_or_eq() unless ($inpreamble or $inIndentBlock); - - # check to see if we have %* \end{something} for alignment blocks - # outside of environments - &end_command_with_alignment(); - - # check to see if we're at the end of a noindent - # block %\end{noindent} - &at_end_noindent(); - - # only check for unmatched braces if we're not in - # a verbatim-like environment or in the preamble or in a - # noIndentBlock or in a delimiter block - if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)) { - # The check for closing } and ] relies on counting, so - # we have to remove trailing comments so that any {, }, [, ] - # that are found after % are not counted - # - # note that these lines are NOT in @lines, so we - # have to store the $trailingcomments to put - # back on after the counting - # - # note the use of (?",$fileName); - print OUTPUTFILE @lines; - close(OUTPUTFILE); -} - -# if -o is active then output to $ARGV[1] -if($outputToFile) { - open(OUTPUTFILE,">",$ARGV[1]); - print OUTPUTFILE @lines; - close(OUTPUTFILE); - print $logfile "Output from indentation written to $ARGV[1].\n"; -} - -# final line of the logfil -print $logfile "\n",$masterSettings{logFilePreferences}{endLogFileWith}; - -# close the log file -close($logfile); - +my $document = LatexIndent::Document->new(name=>"masterdocument",fileName=>$ARGV[0],switches=>\%switches); +$document->latexindent; exit(0); - -sub indent_if_else_fi{ - # PURPOSE: set indentation of line that contains \else, \fi command - # - # - - # @masterIndentationArrayOfHashes could be empty -- if so, exit - return unless @masterIndentationArrayOfHashes; - return unless $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}; - - # look for \fi - if( $_ =~ m/^\s*\\fi/) { - # tracing mode - print $logfile "Line $lineCounter\t \\fi command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode); - &decrease_indent($masterIndentationArrayOfHashes[-1]{name}); - } - # look for \else or \or - elsif( $_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) { - # tracing mode - print $logfile "Line $lineCounter\t \\else command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode); - print $logfile "Line $lineCounter\t decreasing indent, still looking for \\fi to match \\",¤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}=""; - } -} - -sub indent_after_if_else_fi{ - # PURPOSE: set indentation *after* \if construct such as - # - # \ifnum\x=2 - # - # - # \else - # - # - # \fi - # - # How to read /^\s*\\(if.*?)(\s|\\|\#) - # - # ^\s* begins with multiple spaces (possibly none) - # \\(if.*?)(\s|\\|\#) matches \if... up to either a - # space, a \, or a # - # Note: this won't match \if.*\fi - if( $_ =~ m/^\s*\\(if.*?)(\s|\\|\#)/ and $_ !~ m/^\s*\\(if.*?\\fi)/ and $constructIfElseFi{$1}) { - # tracing mode - print $logfile "Line $lineCounter\t ifelsefi construct found: $1 \n" if($tracingMode); - &increase_indent({name=>$1,type=>"ifelseif"}); - } elsif(@masterIndentationArrayOfHashes) { - if( ($_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) and $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}) { - # tracing mode - print $logfile "Line $lineCounter\t setting indent *after* \\else or \\or command found for $masterIndentationArrayOfHashes[-1]{name} \n" if($tracingMode); - - # recover the indentation to be implemented *after* the \else or \or - $masterIndentationArrayOfHashes[-1]{indent}=$indentRules{$masterIndentationArrayOfHashes[-1]{name}}||$defaultIndent unless ($noAdditionalIndent{$masterIndentationArrayOfHashes[-1]{name}}); - } - } -} - -sub indent_item{ - # PURPOSE: when considering environments that can contain items, such - # as enumerate, itemize, etc, this subroutine sets the indentation for the item *itself* - - return unless(scalar(@masterIndentationArrayOfHashes)>1); - return unless $indentAfterItems{$masterIndentationArrayOfHashes[-2]{name}}; - - if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ and $itemNames{$1}){ - # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - if($itemNames{$masterIndentationArrayOfHashes[-1]{name}}) { - print $logfile "Line $lineCounter\t $1 found - neutralizing indentation from previous ",$masterIndentationArrayOfHashes[-1]{name},"\n" if($tracingMode); - &decrease_indent($1); - } - } - -} - -sub indent_after_item{ - # PURPOSE: Set the indentation *after* the item - # This matches a line that begins with - # - # \item - # \item[ - # \myitem - # \myitem[ - # - # or anything else specified in itemNames - # - return unless @masterIndentationArrayOfHashes; - return unless $indentAfterItems{$masterIndentationArrayOfHashes[-1]{name}}; - - if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ - and $itemNames{$1}) { - # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - &increase_indent({name=>$1,type=>"item"}); - } -} - -sub begin_command_with_alignment{ - # PURPOSE: This matches - # %* \begin{tabular} - # with any number of spaces (possibly none) between - # the * and \begin{noindent}. - # - # the comment symbol IS indended! - # - # This is to align blocks that contain delimeters that - # are NOT contained in an alignment block in the usual way, e.g - # \matrix{ - # %* \begin{tabular} - # 1 & 2 \\ - # 3 & 4 \\ - # %* \end{tabular} - # } - - if( $_ =~ m/^\s*%\*\s*\\begin\{(.*?)\}/ and $lookForAlignDelims{$1}) { - # increase the indentation - &increase_indent({name=>$1, - alignmentDelimiters=>1, - type=>"environment", - begin=>"\\begin{$1}", - end=>"\\end{$1}"}); - # tracing mode - print $logfile "Line $lineCounter\t Delimiter environment started: $1 (see lookForAlignDelims)\n" if($tracingMode); - } -} - -sub end_command_with_alignment{ - # PURPOSE: This matches - # %* \end{tabular} - # with any number of spaces (possibly none) between - # the * and \end{tabular} (or any other name used from - # lookFroAlignDelims) - # - # Note: the comment symbol IS indended! - # - # This is to align blocks that contain delimeters that - # are NOT contained in an alignment block in the usual way, e.g - # \matrix{ - # %* \begin{tabular} - # 1 & 2 \\ - # 3 & 4 \\ - # %* \end{tabular} - # } - return unless @masterIndentationArrayOfHashes; - return unless $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}; - - if( $_ =~ m/^\s*%\*\s*\\end\{(.*?)\}/ and $lookForAlignDelims{$1}) { - # same subroutine used at the end of regular tabular, align, etc - # environments - if($delimiters) { - &print_aligned_block(); - &decrease_indent($1); - } else { - # tracing mode - print $logfile "Line $lineCounter\t FYI: did you mean to start a delimiter block on a previous line? \n" if($tracingMode); - print $logfile "Line $lineCounter\t perhaps using %* \\begin{$1}\n" if($tracingMode); - } - } -} - -sub indent_heading{ - # PURPOSE: This matches - # \part - # \chapter - # \section - # \subsection - # \subsubsection - # \paragraph - # \subparagraph - # - # and anything else listed in indentAfterHeadings - # - # This subroutine specifies the indentation for the - # heading itself, i.e the line that has \chapter, \section etc - if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}){ - # tracing mode - print $logfile "Line $lineCounter\t Heading found: $1 \n" if($tracingMode); - - # get the heading settings, it's a hash within a hash - my %currentHeading = %{$indentAfterHeadings{$1}}; - - # $previousHeadingLevel: scalar that stores which heading - # we are under: \part, \chapter, etc - my $previousHeadingLevel=0; - - # form an array of the headings available - my @headingStore=(); - foreach my $env (@masterIndentationArrayOfHashes){ - if($env->{type} eq 'heading'){ - push(@headingStore,$env->{name}); - # update heading level - $previousHeadingLevel= $env->{headinglevel}; - } - } - - # if current heading level < old heading level, - if($currentHeading{level}<$previousHeadingLevel) { - # decrease indentation, but only if - # specified in indentHeadings. Note that this check - # needs to be done here- decrease_indent won't - # check a nested hash - - if(scalar(@headingStore)) { - while($currentHeading{level}<$previousHeadingLevel and scalar(@headingStore)) { - my $higherHeadingName = pop(@headingStore); - my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; - - # tracing mode - print $logfile "Line $lineCounter\t stepping UP heading level from $higherHeadingName \n" if($tracingMode); - - &decrease_indent($higherHeadingName) if($higherLevelHeading{indent}); - $previousHeadingLevel=$higherLevelHeading{level}; - } - # put the heading name back in to storage - push(@headingStore,$1); - } - } elsif($currentHeading{level}==$previousHeadingLevel) { - if(scalar(@headingStore)) { - my $higherHeadingName = pop(@headingStore); - my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; - &decrease_indent($higherHeadingName) if($higherLevelHeading{indent}); - } - } - } -} - -sub indent_after_heading{ - # PURPOSE: This matches - # \part - # \chapter - # \section - # \subsection - # \subsubsection - # \paragraph - # \subparagraph - # - # and anything else listed in indentAfterHeadings - # - # This subroutine is specifies the indentation for - # the text AFTER the heading, i.e the body of conent - # in each \chapter, \section, etc - if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}) { - # get the heading settings- it's a hash within a hash - my %currentHeading = %{$indentAfterHeadings{$1}}; - - &increase_indent({name=>$1,type=>"heading",headinglevel=>$currentHeading{level}}) if($currentHeading{indent}); - } -} - -sub at_end_noindent{ - # PURPOSE: This matches - # % \end{noindent} - # with any number of spaces (possibly none) between - # the comment and \end{noindent}. - # - # the comment symbol IS indended! - # - # This is for blocks of code that the user wants - # to leave untouched- similar to verbatim blocks - - if( $_ =~ m/^%\s*\\end\{(.*?)\}/ and $noIndentBlock{$1}) { - $inIndentBlock=0; - # tracing mode - print $logfile "Line $lineCounter\t % \\end{no indent block} found, switching inIndentBlock OFF \n" if($tracingMode); - } -} - -sub at_beg_noindent{ - # PURPOSE: This matches - # % \begin{noindent} - # with any number of spaces (possibly none) between - # the comment and \begin{noindent}. - # - # the comment symbol IS indended! - # - # This is for blocks of code that the user wants - # to leave untouched- similar to verbatim blocks - - if( $_ =~ m/^%\s*\\begin\{(.*?)\}/ and $noIndentBlock{$1}) { - $inIndentBlock = 1; - # tracing mode - print $logfile "Line $lineCounter\t % \\begin{no indent block} found, switching inIndentBlock ON \n" if($tracingMode); - } -} - -sub start_command_or_key_unmatched_brackets{ - # PURPOSE: This matches - # \pgfplotstablecreatecol[... - # - # or any other command/key that has brackets [ ] - # split across lines specified in the - # hash tables, %checkunmatchedbracket - # - # How to read: ^\s*(\\)?(.*?)(\[\s*) - # - # ^ line begins with - # \s* any (or no)spaces - # (\\)? matches a \ backslash but not necessarily - # (.*?) non-greedy character match and store the result - # ((?$commandname,matchedBRACKETS=>$matchedBRACKETS,type=>'splitBrackets'}); - } - } -} - -sub end_command_or_key_unmatched_brackets{ - # PURPOSE: Check for the closing BRACKET of a command that - # splits its BRACKETS across lines, such as - # - # \pgfplotstablecreatecol[ ... - # - # It works by checking if we have any entries - # in the array @masterIndentationArrayOfHashes, and making - # sure that we're not starting another command/key - # that has split BRACKETS (nesting). - # - # It also checks that the line is not commented. - # - # We count the number of [ and ADD to the counter - # ] and SUBTRACT to the counter - return unless @masterIndentationArrayOfHashes; - return unless ($masterIndentationArrayOfHashes[-1]{type} eq 'splitBrackets'); - print $logfile "Line $lineCounter\t Searching for closing BRACKET ] $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - if(!($_ =~ m/^\s*(\\)?(.*?)(\s*\[)/ - and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets)) - and $_ !~ m/^\s*%/) { - - # get the details of the most recent command name - my $commandname = $masterIndentationArrayOfHashes[-1]{name}; - my $matchedBRACKETS = $masterIndentationArrayOfHashes[-1]{matchedBRACKETS}; - - # match [ but don't match \[ - $matchedBRACKETS++ while ($_ =~ m/(? 0 ) { - # tracing mode - print $logfile "Line $lineCounter\t Found opening BRACE { $commandname\n" if($tracingMode); - - &increase_indent({name=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>0, - type=>"splitbraces"}); - } elsif($matchedbraces<0) { - # if $matchedbraces < 0 then we must be matching - # braces from a previous split-braces command - - # keep matching { OR }, and don't match \{ or \} - while ($_ =~ m/(((?$2, - type=>"environment", - begin=>"\\begin{$2}", - end=>"\\end{$2}"}); - - # check for verbatim-like environments - if($verbatimEnvironments{$2}){ - $inverbatim = 1; - # tracing mode - print $logfile "Line $lineCounter\t \\begin{verbatim-like} found, $2, switching ON verbatim \n" if($tracingMode); - - # remove the key and value from %lookForAlignDelims hash - # to avoid any further confusion - if($lookForAlignDelims{$2}) { - print $logfile "WARNING\n\t Line $lineCounter\t $2 is in *both* lookForAlignDelims and verbatimEnvironments\n"; - print $logfile "\t\t\t ignoring lookForAlignDelims and prioritizing verbatimEnvironments\n"; - print $logfile "\t\t\t Note that you only get this message once per environment\n"; - delete $lookForAlignDelims{$2}; - } - } - } -} - -sub at_end_of_env_or_eq{ - # PURPOSE: Check if we're at the END of an environment - # or at the END of a displayed equation \] - # - # This subroutine checks for matches of the form - # - # \end{environmentname} - # or - # \] - # - # Note: environmentname can begin with a backslash - # which might happen in a sty or cls file. - # - # It also checks to see if the current environment - # had alignment delimiters; if so, we need to turn - # OFF the $delimiter switch - - return unless @masterIndentationArrayOfHashes; - print $logfile "Line $lineCounter\t looking for \\end{$masterIndentationArrayOfHashes[-1]{name}} \n" if($tracingMode); - - if( ($_ =~ m/^\s*\\end\{\\?(.*?)\}/ or $_=~ m/^(\\\])/) and $_ !~ m/\s*^%/) { - # check if we're at the end of a verbatim-like environment - if($verbatimEnvironments{$1}) { - $inverbatim = 0; - # tracing mode - - print $logfile "Line $lineCounter\t \\end{verbatim-like} found: $1, switching off verbatim \n" if($tracingMode); - print $logfile "Line $lineCounter\t removing leading spaces \n" if($tracingMode); - #s/^\ *//; - s/^\t+// if($_ ne ""); - s/^\s+// if($_ ne ""); - } - - # check if we're in an environment that is looking - # to indent after each \item - if(scalar(@masterIndentationArrayOfHashes) and $itemNames{$masterIndentationArrayOfHashes[-1]{name}}) { - &decrease_indent($masterIndentationArrayOfHashes[-1]{name}); - } - - # if we're at the end of an environment that receives no additional indent, log it, and move on - if($noAdditionalIndent{$1}){ - print $logfile "Line $lineCounter\t \\end{$1} finished a no-additional-indent environment (see noAdditionalIndent)\n" if($tracingMode); - } - - # some commands contain \end{environmentname}, which - # can cause a problem if \begin{environmentname} was not - # started previously; if @masterIndentationArrayOfHashes is empty, - # then we don't need to check for \end{environmentname} - if(@masterIndentationArrayOfHashes) { - # check to see if \end{environment} fits with most recent \begin{...} - my %previousEnvironment = %{$masterIndentationArrayOfHashes[-1]}; - - # check to see if we need to turn off alignment - # delimiters and output the current block - if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters} and ($previousEnvironment{name} eq $1)) { - &print_aligned_block(); - } - - # tracing mode - print $logfile "Line $lineCounter\t \\end{environment} found: $1 \n" if($tracingMode and !$verbatimEnvironments{$1}); - - # check to see if \end{environment} fits with most recent \begin{...} - if($previousEnvironment{name} eq $1) { - # decrease the indentation (if appropriate) - print $logfile "Line $lineCounter\t removed $1 from Indentation array\n" if($tracingMode); - &decrease_indent($1); - } else { - # otherwise put the environment name back on the stack - print $logfile "Line $lineCounter\t WARNING: \\end{$1} found on its own line, not matched to \\begin{$previousEnvironment{name}}\n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); - } - - # need a special check for \[ and \] - if($1 eq "\\\]") { - &decrease_indent($1); - } - } - - # if we're at the end of the document, we remove all current - # indentation- this is especially prominent in examples that - # have headings, and the user has chosen to indentAfterHeadings - if($1 eq "document" and !$inFileContents and !$inpreamble and !$delimiters and !$inverbatim and !$inIndentBlock and @masterIndentationArrayOfHashes) { - @masterIndentationArrayOfHashes=(); - - # tracing mode - if($tracingMode) { - print $logfile "Line $lineCounter\t \\end{$1} found, emptying indentation array \n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); - } - } - } -} - -sub print_aligned_block{ - # PURPOSE: this subroutine does a few things related - # to printing blocks of code that contain - # delimiters, such as align, tabular, etc - # - # It does the following - # - turns off delimiters switch - # - processes the block - # - deletes the block - $delimiters=0; - - # tracing mode - print $logfile "Line $lineCounter\t Delimiter body FINISHED: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - # print the current FORMATTED block - my @block = &format_block(@{$masterIndentationArrayOfHashes[-1]{block}}); - foreach $line (@block) { - # add the indentation and add the - # each line of the formatted block - # to the output - # unless this would only create trailing whitespace and the - # corresponding option is set - unless ($line =~ m/^$/ and $removeTrailingWhitespace) { - $line =¤t_indentation().$line; - } - push(@lines,$line); - } -} - -sub format_block{ - # PURPOSE: Format a delimited environment such as the - # tabular or align environment that contains & - # - # INPUT: @block array containing unformatted block - # from, for example, align, or tabular - # OUTPUT: @formattedblock array containing FORMATTED block - - # @block is the input - my @block=@_; - - # tracing mode - print $logfile "\t\tFormatting alignment block: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - # step the line counter back to the beginning of the block- - # it will be increased back to the end of the block in the - # loop later on: foreach $row (@tmpblock) - $lineCounter -= scalar(@block); - - # local array variables - my @formattedblock; - my @tmprow=(); - my @tmpblock=(); - my @maxmstringsize=(); - my @ampersandCount=(); - - # local scalar variables - my $alignrowcounter=-1; - my $aligncolcounter=-1; - my $tmpstring; - my $row; - my $column; - my $maxmcolstrlength; - my $i; - my $j; - my $fmtstring; - my $linebreak; - my $maxNumberAmpersands = 0; - my $currentNumberAmpersands; - my $trailingcomments; - - # local hash table - my %stringsize=(); - - # loop through the block and count & per line- store the biggest - # NOTE: this needs to be done in its own block so that - # we can know what the maximum number of & in the block is - foreach $row (@block) { - # delete trailing comments - $trailingcomments=''; - if($row =~ m/((? $maxNumberAmpersands ); - - # put trailing comments back on - if($trailingcomments){ - $row =~ s/%TC/$trailingcomments/; - } - } - - # tracing mode - print $logfile "\t\tmaximum number of & in any row: $maxNumberAmpersands\n" if($tracingMode); - - # loop through the lines in the @block - foreach $row (@block){ - # get the ampersand count - $currentNumberAmpersands = shift(@ampersandCount); - - # increment row counter - $alignrowcounter++; - - # clear the $linebreak variable - $linebreak=''; - - # check for line break \\ - # and don't mess with a line that doesn't have the maximum - # number of & - if($row =~ m/\\\\/ and $currentNumberAmpersands==$maxNumberAmpersands ) { - # remove \\ and all characters that follow - # and put it back in later, once the measurement - # has been done - $row =~ s/(\\\\.*)//; - $linebreak = $1; - } - - if($currentNumberAmpersands==$maxNumberAmpersands) { - - # remove trailing comments - $trailingcomments=''; - if($row =~ m/((?$maxmcolstrlength) { - $maxmcolstrlength = $stringsize{$i.$j}; - } - } - } - push(@maxmstringsize,$maxmcolstrlength); - } - - # README: printf( formatting, expression) - # - # formatting has the form %-50s & %-20s & %-19s - # (the numbers have been made up for example) - # the - symbols mean that each column should be left-aligned - # the numbers represent how wide each column is - # the s represents string - # the & needs to be inserted - - # join up the maximum string lengths using "s %-" - $fmtstring = join("s & %-",@maxmstringsize); - - # add an s to the end, and a newline - $fmtstring .= "s "; - - # add %- to the beginning - $fmtstring = "%-".$fmtstring; - - # process the @tmpblock of aligned material - foreach $row (@tmpblock) { - $linebreak=''; - # check for line break \\ - if($row =~ m/\\\\/) { - # remove \\ and all characters that follow - # and put it back in later - $row =~ s/(\\\\.*$)//; - $linebreak = $1; - } - - if($row =~ m/NOFORMATTING/) { - $row =~ s/NOFORMATTING//; - $tmpstring=$row; - - # tracing mode - print $logfile "\t\tLine $lineCounter\t maximum number of & NOT found- not aligning delimiters \n" if($tracingMode); - } else { - # remove trailing comments - $trailingcomments=''; - if($row =~ m/((?1?"spaces":"space"," before \\\\ (see $masterIndentationArrayOfHashes[-1]{name} spacesBeforeDoubleBackSlash)\n" if($tracingMode); - $tmpstring =~ s/\\\\/$spaceString\\\\/; - } - } - - # put trailing comments back on - if($trailingcomments) { - $tmpstring =~ s/%TC/$trailingcomments/; - } - - # tracing mode - print $logfile "\t\tLine $lineCounter\t Found maximum number of & so aligning delimiters\n" if($tracingMode); - } - - # remove trailing whitespace - if ($removeTrailingWhitespace) { - print $logfile "\t\tLine $lineCounter\t removing trailing whitespace from delimiter aligned line\n" if ($tracingMode); - $tmpstring =~ s/\s+$/\n/; - } - - push(@formattedblock,$tmpstring); - - # increase the line counter - $lineCounter++; - } - - # return the formatted block - @formattedblock; -} - -sub increase_indent{ - # PURPOSE: Adjust the indentation - # of the current environment, command, etc; - # check that it's not an environment - # that doesn't want indentation. - - my %infoHash = %{pop(@_)}; - my $command = $infoHash{name}; - - # check for conflicting hash keys - &check_conflicting_keys($command); - - # quick check for verbatim Environment - if($inverbatim){ - print $logfile "Line $lineCounter\t currently inverbatim environment, not increasing indentation\n" if($tracingMode); - return; - } - - if($indentRules{$command}) { - # tracing mode - print $logfile "Line $lineCounter\t increasing indent using rule for $command (see indentRules)\n" if($tracingMode); - } else { - # default indentation - if(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command})) { - # tracing mode - print $logfile "Line $lineCounter\t increasing indent using defaultIndent\n" if($tracingMode); - } elsif($noAdditionalIndent{$command}) { - # tracing mode - print $logfile "Line $lineCounter\t no additional indent added for $command (see noAdditionalIndent)\n" if($tracingMode); - } - } - - # add to the master array of hashes - push(@masterIndentationArrayOfHashes,\%infoHash); - - # handle the keys slightly different when dealing with environments or commands - if($infoHash{type} eq 'environment'){ - # environments - if(!$noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent; - } - # check to see if we need to look for alignment delimiters - if($lookForAlignDelims{$command}){ - # there are two ways to complete the lookForAlignDelims field, either as a scalar - # or as a hash, so that we can check for alignDoubleBackSlash. - # - # tabular: - # delims: 1 - # alignDoubleBackSlash: 1 - # - # or, simply, - # - # tabular: 1 - # - # We need to perform a check to see which has been done. - if(ref($lookForAlignDelims{$command}) eq 'HASH'){ - # tabular: - # delims: 1 - # alignDoubleBackSlash: 1 - $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=defined $lookForAlignDelims{$command}{delims}?$lookForAlignDelims{$command}{delims}:1; - $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=defined $lookForAlignDelims{$command}{alignDoubleBackSlash}?$lookForAlignDelims{$command}{alignDoubleBackSlash}:1; - $masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash}=$lookForAlignDelims{$command}{spacesBeforeDoubleBackSlash}||0; - } else { - # tabular: 1 - $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=1; - $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=1; - } - if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters}==1){ - # tracing mode - print $logfile "Line $lineCounter\t Delimiter environment started: $command (see lookForAlignDelims)\n" if($tracingMode); - } - } - } else { - # commands, headings, etc - if(!$noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent; - } - } - - # details of noAdditionalIndent to the main hash - if($noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{noAdditionalIndent} = 'yes'; - } -} - -sub decrease_indent{ - # PURPOSE: Adjust the indentation - # of the current environment; - # check that it's not an environment - # that doesn't want indentation. - - # if there is no evidence of indentation, then return - return unless(scalar(@masterIndentationArrayOfHashes)); - - # otherwise get details of the most recent command, environment, item, if, heading, etc - my $command = pop(@_); - - if(!$inverbatim) { - print $logfile "Line $lineCounter\t removing ", $masterIndentationArrayOfHashes[-1]{name}, " from masterIndentationArrayOfHashes\n" if($tracingMode); - pop(@masterIndentationArrayOfHashes); - # tracing mode - if($tracingMode) { - if(@masterIndentationArrayOfHashes) { - print $logfile "Line $lineCounter\t decreasing masterIndentationArrayOfHashes to: ",¤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 index fd9756080a7..8a36fba70ad 100755 Binary files a/Master/bin/win32/latexindent.exe and b/Master/bin/win32/latexindent.exe differ diff --git a/Master/texmf-dist/doc/support/latexindent/README b/Master/texmf-dist/doc/support/latexindent/README index 0fc5cf558ed..84048efae10 100644 --- a/Master/texmf-dist/doc/support/latexindent/README +++ b/Master/texmf-dist/doc/support/latexindent/README @@ -20,7 +20,7 @@ *+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ -FOR COMPLETE DETAILS, PLEASE SEE documentation/manual.pdf +FOR COMPLETE DETAILS, PLEASE SEE documentation/latexindent.pdf Note: latexindent.exe was created using @@ -34,6 +34,7 @@ USAGE You'll need latexindent.pl + LatexIndent/*.pm defaultSettings.yaml in the same directory. Windows users might prefer to grab latexindent.exe @@ -49,5 +50,6 @@ I recommend both using the following: - a visual check, at the very least, make sure that each file has the same number of lines - a check using latexdiff inputfile.tex outputfile.tex + - git status myfile.tex %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/Master/texmf-dist/doc/support/latexindent/appendices.tex b/Master/texmf-dist/doc/support/latexindent/appendices.tex new file mode 100644 index 00000000000..cc77004e45b --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/appendices.tex @@ -0,0 +1,192 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\appendix + \section{Required \texttt{Perl} modules}\label{sec:requiredmodules} + If you intend to use \texttt{latexindent.pl} and \emph{not} one of the supplied standalone executable files, then you will need a few standard Perl modules -- if you can run the + minimum code in \cref{lst:helloworld} (\texttt{perl helloworld.pl}) then you will be able to run \texttt{latexindent.pl}, otherwise you may + need to install the missing modules. + + \begin{cmhlistings}[language=Perl]{\texttt{helloworld.pl}}{lst:helloworld} + #!/usr/bin/perl + + use strict; + use warnings; + use FindBin; + use YAML::Tiny; + use File::Copy; + use File::Basename; + use File::HomeDir; + use Getopt::Long; + use Data::Dumper; + + print "hello world"; + exit; +\end{cmhlistings} + My default installation on Ubuntu 12.04 did \emph{not} come + with all of these modules as standard, but Strawberry Perl for Windows \cite{strawberryperl} + did. + + Installing the modules given in \cref{lst:helloworld} will vary depending on your + operating system and \texttt{Perl} distribution. For example, Ubuntu users + might visit the software center, or else run + \begin{commandshell} +sudo perl -MCPAN -e 'install "File::HomeDir"' + \end{commandshell} + + 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{commandshell} +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{commandshell} + + Strawberry Perl users on Windows might use + \texttt{CPAN client}. All of the modules are readily available on CPAN \cite{cpan}. + + \texttt{indent.log} will contain details of the location + of the Perl modules on your system. \texttt{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 + wish to see where they are cached, use the \texttt{trace} option, e.g + \begin{dosprompt} +latexindent.exe -t myfile.tex + \end{dosprompt} + + \section{Updating the \texttt{path} variable}\label{sec:updating-path} + \texttt{latexindent.pl} has a few scripts (available at \cite{latexindent-home}) that can update the \texttt{path} variables\footnote{Thanks to \cite{jasjuang} for this feature!}. If you're + on a Linux or Mac machine, then you'll want \texttt{CMakeLists.txt} from \cite{latexindent-home}. + \subsection{Add to path for Linux} + To add \texttt{latexindent.pl} to the path for Linux, follow these steps: + \begin{enumerate} + \item download \texttt{latexindent.pl} and its associated modules, \texttt{defaultSettings.yaml}, + to your chosen directory from \cite{latexindent-home} ; + \item within your directory, create a directory called \texttt{path-helper-files} and + download \texttt{CMakeLists.txt} and \lstinline!cmake_uninstall.cmake.in! + from \cite{latexindent-home}/path-helper-files to this directory; + \item run + \begin{commandshell} +ls /usr/local/bin + \end{commandshell} + to see what is \emph{currently} in there; + \item run the following commands + \begin{commandshell} +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{commandshell} + \item run + \begin{commandshell} +ls /usr/local/bin + \end{commandshell} + again to check that \texttt{latexindent.pl}, its modules and \texttt{defaultSettings.yaml} have been added. + \end{enumerate} + To \emph{remove} the files, run + \begin{commandshell} +sudo make uninstall}. + \end{commandshell} + \subsection{Add to path for Windows} + To add \texttt{latexindent.exe} to the path for Windows, follow these steps: + \begin{enumerate} + \item download \texttt{latexindent.exe}, \texttt{defaultSettings.yaml}, \texttt{add-to-path.bat} + from \cite{latexindent-home} to your chosen directory; + \item open a command prompt and run the following command to see what is \emph{currently} in your \lstinline!%path%! variable; + \begin{dosprompt} +echo %path% + \end{dosprompt} + \item right click on \texttt{add-to-path.bat} and \emph{Run as administrator}; + \item log out, and log back in; + \item open a command prompt and run + \begin{dosprompt} +echo %path% + \end{dosprompt} + 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 \texttt{remove-from-path.bat} as administrator. + + \section{Differences from Version 2.2 to 3.0}\label{app:differences} + There are a few (small) changes to the interface when comparing Version 2.2 to Version 3.0. + Explicitly, in previous versions you might have run, for example, + \begin{commandshell} +latexindent.pl -o myfile.tex outputfile.tex + \end{commandshell} + whereas in Version 3.0 you would run any of the following, for example, + \begin{commandshell} +latexindent.pl -o=outputfile.tex myfile.tex +latexindent.pl -o outputfile.tex myfile.tex +latexindent.pl myfile.tex -o outputfile.tex +latexindent.pl myfile.tex -o=outputfile.tex +latexindent.pl myfile.tex -outputfile=outputfile.tex +latexindent.pl myfile.tex -outputfile outputfile.tex + \end{commandshell} + noting that the \emph{output} file is given \emph{next to} the \texttt{-o} switch. + + The fields given in \cref{lst:obsoleteYaml} are \emph{obsolete} from Version 3.0 + onwards. + \begin{yaml}[style=yaml-LST,numbers=none]{Obsolete YAML fields from Version 3.0}[colframe=white!25!red,colbacktitle=white!75!red,colback=white!90!red,]{lst:obsoleteYaml} +alwaysLookforSplitBrackets +alwaysLookforSplitBrackets +checkunmatched +checkunmatchedELSE +checkunmatchedbracket +constructIfElseFi +\end{yaml} + + There is a slight difference when specifying indentation after headings; specifically, + we now write \texttt{indentAfterThisHeading} instead of \texttt{indent}. See \cref{lst:indentAfterThisHeadingOld,lst:indentAfterThisHeadingNew} + + \begin{minipage}{.45\textwidth} + \begin{yaml}[style=yaml-LST,numbers=none]{\texttt{indentAfterThisHeading} in Version 2.2}{lst:indentAfterThisHeadingOld} +indentAfterHeadings: + part: + indent: 0 + level: 1 +\end{yaml} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \begin{yaml}[style=yaml-LST,numbers=none]{\texttt{indentAfterThisHeading} in Version 3.0}{lst:indentAfterThisHeadingNew} +indentAfterHeadings: + part: + indentAfterThisHeading: 0 + level: 1 +\end{yaml} + \end{minipage}% + + To specify \texttt{noAdditionalIndent} for display-math environments in Version 2.2, you would write YAML + as in \cref{lst:noAdditionalIndentOld}; as of Version 3.0, you would write YAML as in \cref{lst:indentAfterThisHeadingNew1} + or, if you're using \texttt{-m} switch, \cref{lst:indentAfterThisHeadingNew2}. + + \begin{minipage}{.45\textwidth} + \begin{yaml}[style=yaml-LST,numbers=none]{\texttt{noAdditionalIndent} in Version 2.2}{lst:noAdditionalIndentOld} +noAdditionalIndent: + \[: 0 + \]: 0 +\end{yaml} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \begin{yaml}[style=yaml-LST,numbers=none]{\texttt{noAdditionalIndent} for \texttt{displayMath} in Version 3.0}{lst:indentAfterThisHeadingNew1} +specialBeginEnd: + displayMath: + begin: '\\\[' + end: '\\\]' + lookForThis: 0 +\end{yaml} + + \begin{yaml}[style=yaml-LST,numbers=none]{\texttt{noAdditionalIndent} for \texttt{displayMath} in Version 3.0}{lst:indentAfterThisHeadingNew2} +noAdditionalIndent: + displayMath: 1 +\end{yaml} + \end{minipage}% + + \mbox{}\hfill \begin{minipage}{.25\textwidth} + \hrule + + \hfill\itshape End + + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf deleted file mode 100644 index 4ac36f075da..00000000000 Binary files a/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.pdf and /dev/null differ diff --git a/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex b/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex deleted file mode 100644 index c39b89e627e..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/documentation/latexindent.tex +++ /dev/null @@ -1,1512 +0,0 @@ -% arara: pdflatex -% arara: bibtex -% arara: pdflatex -% arara: pdflatex -% !arara: pdflatex -% !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 -% the Free Software Foundation, either version 3 of the License, or -% (at your option) any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% See . -\usepackage[left=4.5cm,right=2.5cm,showframe=false, -top=2cm,bottom=1.5cm]{geometry} % page setup -\usepackage{parskip} % paragraph skips -\usepackage{booktabs} % beautiful tables -\usepackage{listings} % nice verbatim environments -\usepackage{titlesec} % customize headings -\usepackage{changepage} % adjust width of page -\usepackage{fancyhdr} % headers & footers -\usepackage[sc,format=hang,font=small]{caption} % captions -\usepackage[backend=bibtex]{biblatex} % bibliography -\usepackage{tcolorbox} % framed environments -\usepackage[charter]{mathdesign} % changes font -\usepackage[expansion=false,kerning=true]{microtype} % better kerning -\usepackage{enumitem} % custom lists -% 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{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{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}}; }} - -\makeatletter -\tcbset{ - addtolol/.style={list entry={\kvtcb@title},add to list={lol}{lstlisting}}, -} - -\newtcblisting[use counter=lstlisting]{cmhlistings}[3][]{% - width=\linewidth, - breakable, - colback=blue!5!white, - colframe=white!85!black, - top=0cm, - bottom=0cm, - left=6mm, - listing only, - listing options={#1}, - center title, - title={\color{black}{\scshape Listing \thetcbcounter}: ~#2},label={#3}, - addtolol, -} - -\lstset{% - basicstyle=\small\ttfamily,language={[LaTeX]TeX}, - % numbers=left, - numberstyle=\ttfamily%\small, - breaklines=true, - % frame=single,framexleftmargin=8mm, xleftmargin=8mm, - % prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookrightarrow}}, - % backgroundcolor=\color{green!5},frameround=fttt, - % rulecolor=\color{blue!70!black}, - keywordstyle=\color{blue}, % keywords - commentstyle=\color{purple}, % comments - tabsize=3, - %xleftmargin=1.5em, -}% -\lstdefinestyle{yaml}{% - numbers=left, - numberstyle=\color{black},} -\lstdefinestyle{demo}{ - numbers=none, - linewidth=1.25\textwidth, - columns=fullflexible, -} - -% 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, -% numbers=left, -% xleftmargin=1.5em, -% breaklines=true, -% numberstyle=\ttfamily\small, -% columns=flexible, -% mathescape=false, -% #1, -%}} -%{} - -\newcommand{\fixthis}[1] -{% - \marginpar{\huge \color{red} \framebox{FIX}}% - \typeout{FIXTHIS: p\thepage : #1^^J}% -} -% custom section -\titleformat{\section} -{\normalfont\Large\bfseries} -{\llap{\thesection\hskip.5cm}} -{0pt} -{} -% custom subsection -\titleformat{\subsection} -{\normalfont\bfseries} -{\llap{\thesubsection\hskip.5cm}} -{0pt} -{} -% custom subsubsection -\titleformat{\subsubsection} -{\normalfont\bfseries} -{\llap{\thesubsubsection\hskip.5cm}} -{0pt} -{} - - -\titlespacing\section{0pt}{12pt plus 4pt minus 2pt}{-5pt plus 2pt minus 2pt} -\titlespacing\subsection{0pt}{12pt plus 4pt minus 2pt}{-6pt plus 2pt minus 2pt} -\titlespacing\subsubsection{0pt}{12pt plus 4pt minus 2pt}{-6pt plus 2pt minus 2pt} - - -% cleveref settings -\crefname{table}{Table}{Tables} -\Crefname{table}{Table}{Tables} -\crefname{figure}{Figure}{Figures} -\Crefname{figure}{Figure}{Figures} -\crefname{section}{Section}{Sections} -\Crefname{section}{Section}{Sections} -\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.2} -% \end{noindent} -\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! (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, - are \emph{usually} handled correctly by the script. Options for \lstinline!verbatim!-like - environments and indentation after headings (such as \lstinline!\chapter!, \lstinline!\section!, etc) - are also available. -\end{abstract} - -\tableofcontents -\lstlistoflistings - -\section{Before we begin} -\subsection{Thanks} -I first created \lstinline!latexindent.pl! to help me format chapter files -in a big project. After I blogged about it on the -\TeX{} stack exchange \cite{cmhblog} I received some positive feedback and -follow-up feature requests. A big thank you to Harish Kumar who has really -helped to drive the script forward and has put it through a number of challenging -tests--I look forward to more challenges in the future Harish! - -The \lstinline!yaml!-based interface of \lstinline!latexindent.pl! was inspired -by the wonderful \lstinline!arara! tool; any similarities are deliberate, and -I hope that it is perceived as the compliment that it is. Thank you to Paulo Cereda and the -team for releasing this awesome tool; I initially worried that I was going to -have to make a GUI for \lstinline!latexindent.pl!, but the release of \lstinline!arara! -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. -It will always make at least one backup (you can choose how many it makes, see \cpageref{page:onlyonebackup}) -but you should still be careful when using it. The script has been tested on many -files, but there are some known limitations (see \cref{sec:knownlimitations}). -You, the user, are responsible for ensuring that you maintain backups of your files -before running \lstinline!latexindent.pl! on them. I think it is important at this -stage to restate an important part of the license here: -\begin{quote}\itshape - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -\end{quote} -There is certainly no malicious intent in releasing this script, and I do hope -that it works as you expect it to--if it does not, please first of all -make sure that you have the correct settings, and then feel free to let me know with a -complete minimum working example as I would like to improve the code as much as possible. - -\begin{warning} - Before you try the script on anything important (like your thesis), test it - out on the sample files that come with it in the \lstinline!success! directory. -\end{warning} - - -\section{Demonstration: before and after} -Let's give a demonstration of some before and after code--after all, you probably -won't want to try the script if you don't much like the results. You might also -like to watch the video demonstration I made on youtube \cite{cmh:videodemo} - -As you look at \crefrange{lst:filecontentsbefore}{lst:pstricksafter}, remember -that \lstinline!latexindent.pl! is just following its rules--there is nothing -particular about these code snippets. All of the rules can be modified -so that each user can personalize their indentation scheme. - -In each of the samples given in \crefrange{lst:filecontentsbefore}{lst:pstricksafter} -the `before' case is a `worst case scenario' with no effort to make indentation. The `after' -result would be the same, regardless of the leading white space at the beginning of -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{sidebyside} - \noindent - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!filecontents! before}{lst:filecontentsbefore} -\begin{filecontents}{mybib.bib} -@online{strawberryperl, -title="Strawberry Perl", -url="http://strawberryperl.com/"} -@online{cmhblog, -title="A Perl script ... -url="... -\end{filecontents} - \end{cmhlistings} - \end{minipage}% - \noindent - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!filecontents! after}{lst:filecontentsafter} -\begin{filecontents}{mybib.bib} - @online{strawberryperl, - title="Strawberry Perl", - url="http://strawberryperl.com/"} - @online{cmhblog, - title="A Perl script for ... - url="... -\end{filecontents} - \end{cmhlistings} - \end{minipage} - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!tikzset! before}{lst:tikzsetbefore} -\tikzset{ -shrink inner sep/.code={ -\pgfkeysgetvalue... -\pgfkeysgetvalue... -} -} - \end{cmhlistings} - \end{minipage}% - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!tikzset! after}{lst:tikzsetafter} -\tikzset{ - shrink inner sep/.code={ - \pgfkeysgetvalue... - \pgfkeysgetvalue... - } -} - \end{cmhlistings} - \end{minipage} - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!pstricks! before}{lst:pstricksbefore} -\def\Picture#1{% -\def\stripH{#1}% -\begin{pspicture}[showgrid... -\psforeach{\row}{% -{{3,2.8,2.7,3,3.1}},% <=== Only this -{2.8,1,1.2,2,3},% -... -}{% -\expandafter... -} -\end{pspicture}} - \end{cmhlistings} - \end{minipage}% - \begin{minipage}{.6\textwidth} - \begin{cmhlistings}[style=demo]{\lstinline!pstricks! after}{lst:pstricksafter} -\def\Picture#1{% - \def\stripH{#1}% - \begin{pspicture}[showgrid... - \psforeach{\row}{% - {{3,2.8,2.7,3,3.1}},% <=== - {2.8,1,1.2,2,3},% - ... - }{% - \expandafter... - } - \end{pspicture}} - \end{cmhlistings} - \end{minipage} - \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 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. - -\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, 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=.25cm] - \item[] \lstinline!latexindent.pl! - - 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. - \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, --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=}]\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} - -\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 -to the directory of -your other \lstinline!arara! rules; otherwise you can add the directory in which \lstinline!latexindent.pl! -resides to your \lstinline!araraconfig.yaml! file. - -Once you have told \lstinline!arara! where to find your \lstinline!indent! rule, -you can use it any of the ways described in \cref{lst:arara} (or combinations thereof). -In fact, \lstinline!arara! allows yet greater flexibility--you can use \lstinline!yes/no!, \lstinline!true/false!, or \lstinline!on/off! to toggle the various options. - -\begin{cmhlistings}[style=demo,escapeinside={(*@}{@*)}]{\lstinline!arara! sample usage}{lst:arara} -%(*@@*) arara: indent -%(*@@*) arara: indent: {overwrite: yes} -%(*@@*) arara: indent: {output: myfile.tex} -%(*@@*) arara: indent: {silent: yes} -%(*@@*) arara: indent: {trace: yes} -%(*@@*) arara: indent: {localSettings: yes} -%(*@@*) arara: indent: {onlyDefault: on} -%(*@@*) arara: indent: { cruft: /home/cmhughes/Desktop } -\documentclass{article} -... -\end{cmhlistings} - -Hopefully the use of these rules is fairly self-explanatory, but for completeness -\cref{tab:orbsandswitches} shows the relationship between \lstinline!arara! directive arguments and the -switches given in \cref{sec:commandline}. - -\begin{table}[!ht] - \centering - \caption{\lstinline!arara! directive arguments and corresponding switches} - \label{tab:orbsandswitches} - \begin{tabular}{lc} - \toprule - \lstinline!arara! directive argument & switch \\ - \midrule - \lstinline!overwrite! & \lstinline!-w! \\ - \lstinline!output! & \lstinline!-o! \\ - \lstinline!silent! & \lstinline!-s! \\ - \lstinline!trace! & \lstinline!-t! \\ - \lstinline!localSettings! & \lstinline!-l! \\ - \lstinline!onlyDefault! & \lstinline!-d! \\ - \lstinline!cruft! & \lstinline!-c! \\ - \bottomrule - \end{tabular} -\end{table} - -The \lstinline!cruft! directive does not work well when used with -directories that contain spaces. - -\section{default, user, and local settings}\label{sec:defuseloc} -\lstinline!latexindent.pl! loads its settings from \lstinline!defaultSettings.yaml! -(rhymes with camel). The idea is to separate the behaviour of the script -from the internal working--this is very similar to the way that we separate content -from form when writing our documents in \LaTeX. - -\subsection{\lstinline!defaultSettings.yaml!} -If you look in \lstinline!defaultSettings.yaml! you'll find the switches -that govern the behaviour of \lstinline!latexindent.pl!. If you're not sure where -\lstinline!defaultSettings.yaml! resides on your computer, don't worry as \lstinline!indent.log! -will tell you where to find it. -\lstinline!defaultSettings.yaml! is commented, -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 \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. -\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}). - - 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! - - 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!. - - \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}} - \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. - - \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} - - \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!. - \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!. - - \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!. - - \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 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: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! (basic)}{lst:aligndelims:basic} -lookForAlignDelims: - tabular: 1 - tabularx: 1 - longtable: 1 - array: 1 - matrix: 1 - bmatrix: 1 - pmatrix: 1 - align: 1 - align*: 1 - alignat: 1 - alignat*: 1 - aligned: 1 - cases: 1 - dcases: 1 - pmatrix: 1 - listabla: 1 - \end{cmhlistings} - - 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:basic,lst:tabularafter:basic}. - - \begin{minipage}{.5\textwidth} - \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}% - \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,columns=fixed]{\lstinline!tabular! after (basic)}{lst:tabularafter:basic} -\begin{tabular}{cccc} - 1 & 2 & 3 & 4 \\ - 5 & & 6 & \\ -\end{tabular} - \end{cmhlistings} - \end{minipage} - - If you find that \lstinline!latexindent.pl! does not perform satisfactorily on such - 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}). - - 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 \\ - 5 & & 6 & \\ -%* \end{tabular} -} - \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}. - - - \begin{cmhlistings}[style=yaml]{\lstinline!verbatimEnvironments!}{lst:verbatimEnvironments} -verbatimEnvironments: - verbatim: 1 - lstlisting: 1 - \end{cmhlistings} - Note that if you put an environment in \lstinline!verbatimEnvironments! - and in other fields such as \lstinline!lookForAlignDelims! or \lstinline!noAdditionalIndent! - 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}. - - \begin{cmhlistings}[style=yaml]{\lstinline!noIndentBlock!}{lst:noIndentBlock} -noIndentBlock: - noindent: 1 - cmhtest: 1 - \end{cmhlistings} - - Of course, you don't want to have to specify these as null environments - in your code, so you use them with a comment symbol, \lstinline!%!, followed - by as many spaces (possibly none) as you like; see \cref{lst:noIndentBlockdemo} for - example. - \begin{cmhlistings}[style=demo,escapeinside={(*@}{@*)}]{\lstinline!noIndentBlock! demonstration}{lst:noIndentBlockdemo} -%(*@@*) \begin{noindent} - this code - won't - be touched - by - latexindent.pl! -%(*@@*)\end{noindent} - \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!. - - \begin{cmhlistings}[style=yaml]{\lstinline!noAdditionalIndent!}{lst:noAdditionalIndent} -noAdditionalIndent: - document: 1 - myexample: 1 - mydefinition: 1 - problem: 1 - exercises: 1 - mysolution: 1 - foreach: 0 - widepage: 1 - comment: 1 - \[: 1 - \]: 1 - frame: 0 - \end{cmhlistings} - Note in particular from \cref{lst:noAdditionalIndent} that if you wish content within - \lstinline!\[! and \lstinline!\]! to receive no additional indentation then - 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} - - \begin{cmhlistings}[style=yaml]{\lstinline!indentRules!}{lst:indentRules} -indentRules: - myenvironment: "\t\t" - anotherenvironment: "\t\t\t\t" - \[: "\t" - \end{cmhlistings} %%%%%\] just here to stop vim from colouring the rest of my code - Note that in contrast to \lstinline!noAdditionalIndent! you do \emph{not} - need to specify both \lstinline!\[! and \lstinline!\]! in this field. - - If you put an environment in both \lstinline!noAdditionalIndent! and in - \lstinline!indentRules! then \lstinline!latexindent.pl! will resolve the conflict - by ignoring \lstinline!indentRules! and prioritizing \lstinline!noAdditionalIndent!. - You will get a warning message in \lstinline!indent.log!; note that you will only - get one warning message per command or environment. Further discussion - 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 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 - level: 1 - chapter: - indent: 0 - level: 2 - section: - indent: 0 - level: 3 - ... - \end{cmhlistings} - The default settings do \emph{not} place indentation after a heading--you - can easily switch them on by changing \lstinline!indent: 0! to \lstinline!indent: 1!. - The \lstinline!level! field tells \lstinline!latexindent.pl! the hierarchy of the heading - structure in your document. You might, for example, like to have both \lstinline!section! - and \lstinline!subsection! set with \lstinline!level: 3! because you do not want the indentation to go too deep. - - You can add any of your own custom heading commands to this field, specifying the \lstinline!level! - as appropriate. You can also specify your own indentation in \lstinline!indentRules!-- - you will find the default \lstinline!indentRules! contains \lstinline!chapter: " "! which - 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} -indentAfterItems: - itemize: 1 - enumerate: 1 - \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} -\begin{itemize} -\item some text here -some more text here -some more text here -\item another item -\end{itemize} - \end{cmhlistings} - \end{minipage}% - \begin{minipage}{.5\textwidth} - \begin{cmhlistings}[style=demo,xleftmargin=-3mm,columns=fixed]{\lstinline!items! after}{lst:itemsafter} -\begin{itemize} - \item some text here - some more text here - some more text here - \item another item -\end{itemize} - \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} -\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} -\ifnum\radius>5 - \ifnum\radius<16 - \draw[decorate,... - \fi -\fi - \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. - Note that in each case, you should \emph{not} use the backslash.} - \end{warning} - - % 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!. - - 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} -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!. - - 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} -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!. - - 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} -checkunmatchedbracket: - psSolid: 1 - pgfplotstablecreatecol: 1 - pgfplotstablesave: 1 - pgfplotstabletypeset: 1 - mycommand: 1 - \end{cmhlistings} -\end{itemize} - -\subsubsection{Hierarchy of fields}\label{sec:fieldhierachy} -After reading the previous section, it should sound reasonable that -\lstinline!noAdditionalIndent!, \lstinline!indentRules!, and -\lstinline!verbatim! all serve mutually exclusive tasks. Naturally, you may -well wonder what happens if you choose to ask \lstinline!latexindent.pl! to -prioritize one above the other. - -For example, let's say that (after reading \cref{sec:indentconfig}) you put the fields in \cref{lst:conflict} into -one of your settings files. -\begin{cmhlistings}[style=yaml]{Conflicting ideas}{lst:conflict} -indentRules: - myenvironment: "\t\t" -noAdditionalIndent: - myenvironment: 1 -\end{cmhlistings} - -Clearly these fields conflict: first of all -you are telling \lstinline!latexindent.pl! that \lstinline!myenvironment! should -receive two tabs of indentation, and then you are telling it -not to put any indentation in the environment. \lstinline!latexindent.pl! -will always make the decision to prioritize \lstinline!noAdditionalIndent! above -\lstinline!indentRules! regardless of the order that you load them in -your settings file. The first -time it encounters \lstinline!myenvironment! it will put a warning in \lstinline!indent.log! -and delete the offending key from \lstinline!indentRules! so that any future -conflicts will not have to be addressed. - -Let's consider another conflicting example in \cref{lst:bigconflict} -\begin{cmhlistings}[style=yaml]{More conflicting ideas}{lst:bigconflict} -lookForAlignDelims: - myenvironment: 1 -verbatimEnvironments: - myenvironment: 1 -\end{cmhlistings} -This is quite a significant conflict--we are first of all telling \lstinline!latexindent.pl! -to look for alignment delimiters in \lstinline!myenvironment! and then -telling it that actually we would like \lstinline!myenvironment! to be considered -as a \lstinline!verbatim!-like environment. Regardless of the order that we -state \cref{lst:bigconflict} the \lstinline!verbatim! instruction will always win. -As in \cref{lst:conflict} you will only receive a warning in \lstinline!indent.log! the -first time \lstinline!latexindent.pl! encounters \lstinline!myenvironment! as the -offending key is deleted from \lstinline!lookForAlignDelims!. - -To summarize, \lstinline!latexindent.pl! will prioritize the various fields in the -following order: -\begin{enumerate} - \item \lstinline!verbatimEnvironments! - \item \lstinline!noAdditionalIndent! - \item \lstinline!indentRules! -\end{enumerate} -\subsection{\lstinline!indentconfig.yaml! and \lstinline!.indentconfig.yaml! (for user settings)}\label{sec:indentconfig} -Editing \lstinline!defaultSettings.yaml! is not ideal as it may be overwritten when -updating your distribution--a better way to customize the settings to your liking -is to set up your own settings file, -\lstinline!mysettings.yaml! (or any name you like, provided it ends with \lstinline!.yaml!). -The only thing you have to do is tell \lstinline!latexindent.pl! where to find it. - -\lstinline!latexindent.pl! will always check your home directory for \lstinline!indentconfig.yaml! -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 \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 - where to put \lstinline!indentconfig.yaml!, don't - worry \lstinline!latexindent.pl! will tell you in the log file exactly where to -put it assuming it doesn't exist already.} -\Cref{lst:indentconfig} shows a sample \lstinline!indentconfig.yaml! file. - -\begin{cmhlistings}[style=yaml]{\lstinline!indentconfig.yaml! (sample)}{lst:indentconfig} -# Paths to user settings for latexindent.pl -# -# Note that the settings will be read in the order you -# specify here- each successive settings file will overwrite -# the variables that you specify - -paths: -- /home/cmhughes/Documents/yamlfiles/mysettings.yaml -- /home/cmhughes/folder/othersettings.yaml -- /some/other/folder/anynameyouwant.yaml -- C:\Users\chughes\Documents\mysettings.yaml -- C:\Users\chughes\Desktop\test spaces\more spaces.yaml -\end{cmhlistings} - -Note that the \lstinline!.yaml! files you specify in \lstinline!indentconfig.yaml! -will be loaded in the order that you write them in. Each file doesn't have -to have every switch from \lstinline!defaultSettings.yaml!; in fact, I recommend -that you only keep the switches that you want to \emph{change} in these -settings files. - -To get started with your own settings file, you might like to save a copy of -\lstinline!defaultSettings.yaml! in another directory and call it, for -example, \lstinline!mysettings.yaml!. Once you have added the path to \lstinline!indentconfig.yaml! -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, -and adds the changes we described on \cpageref{page:examsettings}. - -\begin{cmhlistings}[style=yaml]{\lstinline!mysettings.yaml! (example)}{lst:mysettings} -# Default value of indentation -defaultIndent: "\t\t\t\t" - -# environments that have tab delimiters, add more -# as needed -lookForAlignDelims: - tabbing: 1 - -# If you use the exam documentclass, you might -# like the following settings -# environments that have \item commands -indentAfterItems: - parts: 1 - -# commands to be treated like \item -itemNames: - part: 1 -\end{cmhlistings} - -You can make sure that your settings are loaded by checking \lstinline!indent.log! -for details--if you have specified a path that \lstinline!latexindent.pl! doesn't -recognize then you'll get a warning, otherwise you'll get confirmation that -\lstinline!latexindent.pl! has read your settings file \footnote{Windows users - may find that they have to end \lstinline!.yaml! files with a blank line}. - -\begin{warning} - When editing \lstinline!.yaml! files it is \emph{extremely} important - to remember how sensitive they are to spaces. I highly recommend copying - and pasting from \lstinline!defaultSettings.yaml! when you create your - first \lstinline!whatevernameyoulike.yaml! file. - - If \lstinline!latexindent.pl! can not read your \lstinline!.yaml! file it - will tell you so in \lstinline!indent.log!. -\end{warning} - -\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. - -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} -# Default value of indentation -defaultIndent: " " - -# environments that have tab delimiters, add more -# as needed -lookForAlignDelims: - tabbing: 0 - -# verbatim environments- environments specified -# in this hash table will not be changed at all! -verbatimEnvironments: - cmhenvironment: 0 -\end{cmhlistings} - -You can make sure that your local settings are loaded by checking \lstinline!indent.log! -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! 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}. - -\begin{figure} - \centering - \begin{tikzpicture}[ - needed/.style={very thick, draw=blue,fill=blue!20, - text centered, minimum height=2.5em,rounded corners=1ex}, - optional/.style={draw=black, very thick,scale=0.8, - text centered, minimum height=2.5em,rounded corners=1ex}, - optionalfill/.style={fill=black!10}, - connections/.style={draw=black!30,dotted,line width=3pt,text=red}, - ] - % Draw diagram elements - \node (latexindent) [needed,circle] {\lstinline!latexindent.pl!}; - \node (default) [needed,above right=.5cm of latexindent] {\lstinline!defaultSettings.yaml!}; - \node (indentconfig) [optional,right=of latexindent] {\lstinline!indentconfig.yaml!}; - \node (any) [optional,optionalfill,above right=of indentconfig] {\lstinline!any.yaml!}; - \node (name) [optional,optionalfill,right=of indentconfig] {\lstinline!name.yaml!}; - \node (you) [optional,optionalfill,below right=of indentconfig] {\lstinline!you.yaml!}; - \node (want) [optional,optionalfill,below=of indentconfig] {\lstinline!want.yaml!}; - \node (local) [optional,below=of latexindent] {\lstinline!localSettings.yaml!}; - % Draw arrows between elements - \draw[connections,solid] (latexindent) to[in=-90]node[pos=0.5,anchor=north]{1} (default.south) ; - \draw[connections,optional] (latexindent) -- node[pos=0.5,anchor=north]{2} (indentconfig) ; - \draw[connections,optional] (indentconfig) to[in=-90] (any.south) ; - \draw[connections,optional] (indentconfig) -- (name) ; - \draw[connections,optional] (indentconfig) to[out=-45,in=90] (you) ; - \draw[connections,optional] (indentconfig) -- (want) ; - \draw[connections,optional] (latexindent) -- node[pos=0.5,anchor=west]{3} (local) ; - \end{tikzpicture} - \caption{Schematic of the load order described in \cref{sec:loadorder}; solid lines represent - mandatory files, dotted lines represent optional files. \lstinline!indentconfig.yaml! can - contain as many files as you like--the files will be loaded in order; if you specify - settings for the same field in more than one file, the most recent takes priority. } - \label{fig:loadorder} -\end{figure} - -\subsection{An important example} -I was working on a document that had the text shown in \cref{lst:casestudy}. -\begin{cmhlistings}[style=demo,escapeinside={(*@}{@*)}]{When to set \lstinline!alwaysLookforSplitBrackets=0!}{lst:casestudy} -Hence determine how many zeros the function $h(x)=f(x)-g(x)$ -has on the interval $[0,9)$.(*@\label{line:interval1}@*) -\begin{shortsolution} - The function $h$ has $10$ zeros on the interval $[0,9)$.(*@\label{line:interval2}@*) -\end{shortsolution} -\end{cmhlistings} -I had allowed \lstinline!alwaysLookforSplitBrackets=1!, which is the default setting. -Unfortunately, this caused undesired results, as \lstinline!latexindent.pl! thought that the opening -\lstinline![! in the interval notation (\cref{line:interval1,line:interval2}) -was an opening brace that needed to be closed (with a corresponding \lstinline!]!). Clearly -this was inappropriate, but also expected since \lstinline!latexindent.pl! was simply -following its matching rules. - -In this particular instance, I set up \lstinline!localSettings.yaml! -to contain \lstinline!alwaysLookforSplitBrackets: 0! and then specified the commands -that could split brackets across lines (such as \lstinline!begin{axis}!) individually -in \lstinline!checkunmatchedbracket!. Another option would have been to wrap the -the line in an environment from \lstinline!noIndentBlock! which treats its contents -as a verbatim environment. - - -\section{Known limitations}\label{sec:knownlimitations} -There are a number of known limitations of the script, and almost certainly quite a -few that are \emph{unknown}! - -The main limitation is to do with the alignment routine of environments that contain -delimiters--in other words, environments that are entered in \lstinline!lookForAlignDelims!. -Indeed, this is the only part of the script that can \emph{potentially} remove -lines from \lstinline!myfile.tex!. Note that \lstinline!indent.log! will always -finish with a comparison of line counts before and after. - -The routine works well for `standard' blocks of code that have the same number of \lstinline!&! -per line, but it will not do anything for lines that do not--such examples -include \lstinline!tabular! environments that use \lstinline!\multicolumn! or -perhaps spread cell contents across multiple lines. For each alignment block (\lstinline!tabular!, -\lstinline!align!, etc) \lstinline!latexindent.pl! first of all makes a record -of the maximum number of \lstinline!&!; if each row does not have that -number of \lstinline!&! then it will not try to format that row. Details -will be given in \lstinline!indent.log! assuming that \lstinline!trace! mode -is active. - -If you have a \lstinline!verbatim!-like environment inside a \lstinline!tabular!-like -environment, the \lstinline!verbatim! environment \emph{will} be formatted, which -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!, \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, 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. - -\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} -If you intend to use \lstinline!latexindent.pl! and \emph{not} one of the supplied standalone executable files, then you will need a few standard Perl modules--if you can run the -minimum code in \cref{lst:helloworld} (\lstinline!perl helloworld.pl!) then you will be able to run \lstinline!latexindent.pl!, otherwise you may -need to install the missing modules. - -\begin{cmhlistings}[language=Perl]{\lstinline!helloworld.pl!}{lst:helloworld} -#!/usr/bin/perl - -use strict; -use warnings; -use FindBin; -use YAML::Tiny; -use File::Copy; -use File::Basename; -use Getopt::Long; -use File::HomeDir; - -print "hello world"; -exit; -\end{cmhlistings} -My default installation on Ubuntu 12.04 did \emph{not} come -with all of these modules as standard, but Strawberry Perl for Windows \cite{strawberryperl} -did. - -Installing the modules given in \cref{lst:helloworld} will vary depending on your -operating system and \lstinline!Perl! distribution. For example, Ubuntu users -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.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 -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} -The \lstinline!arara! rule (\lstinline!indent.yaml!) contains lines such as those -given in \cref{lst:arararule}. With this setup, the user \emph{always} has -to specify whether or not they want (in this example) to use the \lstinline!trace! -identifier. -\begin{cmhlistings}[style=yaml,numbers=none]{The \lstinline!arara! rule}{lst:arararule} -... -arguments: -- identifier: trace - flag: @{ isTrue( parameters.trace, "-t" ) } -... -\end{cmhlistings} - -If you would like to have the \lstinline!trace! option on by default every time you -call \lstinline!latexindent.pl! from \lstinline!arara! (without having to write \lstinline!% arara: indent: {trace: yes}!), then simply -amend \cref{lst:arararule} so that it looks like \cref{lst:arararulemod}. -\begin{cmhlistings}[style=yaml,numbers=none]{The \lstinline!arara! rule (modified)}{lst:arararulemod} -... -arguments: -- identifier: trace - flag: @{ isTrue( parameters.trace, "-t" ) } - default: "-t" -... -\end{cmhlistings} - -With this modification in place, you now simply to write \lstinline!% arara: indent! and -\lstinline!trace! mode will be activated by default. If you wish to turn off \lstinline!trace! -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} diff --git a/Master/texmf-dist/doc/support/latexindent/indent.yaml b/Master/texmf-dist/doc/support/latexindent/indent.yaml deleted file mode 100644 index 0db81a066f2..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/indent.yaml +++ /dev/null @@ -1,38 +0,0 @@ -!config -# indent rule for arara -# author: Paulo Cereda, Chris Hughes -# last updated: 11/9/2013 -# requires arara 3.0+ -# -# Sample usage: -# -# % arara: indent -# % arara: indent: {overwrite: yes} -# % arara: indent: {output: myfile.tex, silent: no} -# % arara: indent: {output: myfile.tex, silent: yes, overwrite: yes} -# % arara: indent: {trace: true} -# % arara: indent: {localSettings: true} -# % arara: indent: {onlyDefault: on} -# % arara: indent: { cruft: /home/cmhughes/Desktop } -# -# Directories with spaces will cause issues in the cruft call. -# -# Note: output will take priority above overwrite -identifier: indent -name: Indent -command: @{ isWindows( "cmd /c latexindent.exe", "latexindent.pl" ) } @{silent} @{trace} @{localSettings} @{cruft}@{ isNotEmpty( cruft, '="'.concat(parameters.cruft).concat('"') ) } @{overwrite} @{onlyDefault} @{output} "@{file}" @{ isNotEmpty( output, '"'.concat(parameters.output).concat('"') ) } -arguments: -- identifier: overwrite - flag: @{ isTrue( parameters.overwrite, "-w" ) } -- identifier: silent - flag: @{ isTrue( parameters.silent, "-s" ) } -- identifier: trace - flag: @{ isTrue( parameters.trace, "-t" ) } -- identifier: localSettings - flag: @{ isTrue( parameters.localSettings, "-l" ) } -- identifier: output - flag: @{ isNotEmpty( parameters.output, "-o" ) } -- identifier: onlyDefault - flag: @{ isTrue( parameters.onlyDefault, "-d" ) } -- identifier: cruft - flag: @{ isNotEmpty( parameters.cruft, "-c" ) } diff --git a/Master/texmf-dist/doc/support/latexindent/latexindent.pdf b/Master/texmf-dist/doc/support/latexindent/latexindent.pdf new file mode 100644 index 00000000000..7c912e4b0fa Binary files /dev/null and b/Master/texmf-dist/doc/support/latexindent/latexindent.pdf differ diff --git a/Master/texmf-dist/doc/support/latexindent/latexindent.tex b/Master/texmf-dist/doc/support/latexindent/latexindent.tex new file mode 100644 index 00000000000..b31a22b7141 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/latexindent.tex @@ -0,0 +1,467 @@ +% arara: pdflatex: {shell: yes} +% arara: bibtex +% arara: pdflatex: {shell: yes} +% arara: pdflatex: {shell: yes} +% arara: pdflatex: {shell: yes} +% !arara: indent: {overwrite: yes, trace: yes, localSettings: yes, silent: yes} +\documentclass[10pt]{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 +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% See . +\usepackage[left=4.5cm,right=2.5cm,showframe=false, + top=2cm,bottom=1.5cm]{geometry} % page setup +\usepackage{lmodern} +\usepackage{parskip} % paragraph skips +\usepackage{booktabs} % beautiful tables +\usepackage{listings} % nice verbatim environments +\usepackage{titlesec} % customize headings +\usepackage{titletoc} % customize headings +\usepackage{multicol} +\usepackage{changepage} % adjust width of page +\usepackage{fancyhdr} % headers & footers +\usepackage{wrapfig} +\usepackage{fontawesome} +\usepackage[sc,format=hang,font=small]{caption} % captions +\usepackage[backend=bibtex]{biblatex} % bibliography +\usepackage{tcolorbox} % framed environments +\usepackage{xparse} +\usepackage[charter]{mathdesign} % changes font +\usepackage[expansion=false,kerning=true]{microtype} % better kerning +\usepackage{enumitem} % custom lists +\usepackage{longtable} +\usepackage{array} +% setup gitinfo2, as in the manual, details just above begin{document} +\usepackage[mark,grumpy]{gitinfo2} +% tcolorbox libraries +\tcbuselibrary{breakable,skins,listings,minted,xparse} +%\usepackage{varioref} % clever referencing +%\tcbuselibrary{documentation,breakable,skins,minted} +% tikz libraries +\usetikzlibrary{positioning} +\usetikzlibrary{decorations.pathmorphing} +\usetikzlibrary{decorations,shapes} +\usepackage{varioref} % clever referencing +\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{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}}; } +} + +\definecolor{harvestgold}{cmyk}{0.00, 0.05, 0.51, 0.07} %EDE275 +\definecolor{cmhgold}{cmyk}{0,0.178,0.909,0.008} %FDD017 +\makeatletter +\tcbset{ + addtolol/.style={list entry={\kvtcb@title},add to list={lol}{lstlisting}}, + cmhlistings/.style={ + % width=\linewidth, + %breakable, + colback=blue!5!white, + colframe=white!25!black,colback=white, + top=0cm, + bottom=0cm, + left=0mm, + listing only, + center title, + listing engine=minted, + minted style=colorful, + minted options={obeytabs=true,showtabs=true,tabsize=4,showspaces=true}, + addtolol, + boxrule=0pt, + toprule=1pt,bottomrule=1pt, + titlerule=1pt, + colframe=white!40!black, + colback=white, + sharp corners, + colbacktitle=white!75!black + }, + yaml-TCB/.style={ + listing only, + listing engine=listings, + left=0cm, + boxrule=0pt, + %leftrule=3pt, + sharp corners, + center title, + %colbacktitle=white!75!black, + colbacktitle=white!75!blue, + colframe=white!25!blue, + colback=white!90!blue, + toprule=2pt, + titlerule=2pt, + %bottomrule=1pt, + }, + MLB-TCB/.style={ + yaml-TCB, + center title, + colframe=cmhgold, + colbacktitle=harvestgold, + colback=white!60!cmhgold, + width=0.9\linewidth, + before=\centering, + %bottomrule=1pt, + enhanced, + overlay={\node[anchor=north east,outer sep=2pt,draw=cmhgold,very thick,double,fill=harvestgold,font =\small] at ([yshift=-3mm]frame.north east) {\texttt{-m}}; } + } +} + +\newtcblisting[use counter=lstlisting]{cmhlistings}[3][]{% + cmhlistings, + center title, + title={\color{black}{\scshape Listing \thetcbcounter}: ~#2},label={#3}, + listing engine=listings, + listing options={#1}, +} + +\DeclareTCBInputListing[use counter=lstlisting]{\cmhlistingsfromfile}{O{} m O{} m m}{% + cmhlistings, + listing file={#2}, + listing options={#1}, + title={\color{black}{\scshape Listing \thetcbcounter}: ~#4},label={#5}, + #3, +} + +% command shell +\newtcblisting{commandshell}{colback=black,colupper=white,colframe=yellow!75!black, + listing only,listing options={style=tcblatex,language=sh, + morekeywords={latexindent,pl}, + keywordstyle=\color{blue!35!white}\bfseries, + }, + listing engine=listings, + left=0cm, + every listing line={\textcolor{red}{\small\ttfamily\fontseries{b}\selectfont cmh:$\sim$\$ }}} + +% dosprompt +\newtcblisting{dosprompt}{ + colback=black, + colupper=white, + colframe=yellow!75!black, + listing only, + listing options={ + language=command.com, + morekeywords={latexindent,pl}, + keywordstyle=\color{blue!35!white}\bfseries, + basicstyle=\small\color{white}\ttfamily + }, + listing engine=listings, + left=0cm, + every listing line={\textcolor{white}{\small\ttfamily\fontseries{b}\selectfont C:\textbackslash Users\textbackslash cmh$>$}}} + +\lstset{% + basicstyle=\small\ttfamily,language={[LaTeX]TeX}, + % numbers=left, + numberstyle=\ttfamily%\small, + breaklines=true, + % frame=single,framexleftmargin=8mm, xleftmargin=8mm, + % prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookrightarrow}}, + % backgroundcolor=\color{green!5},frameround=fttt, + % rulecolor=\color{blue!70!black}, + keywordstyle=\color{blue}, % keywords + commentstyle=\color{purple}, % comments + tabsize=3, + %xleftmargin=1.5em, +}% +\DeclareTCBListing[use counter=lstlisting]{yaml}{O{} m O{} m}{ + yaml-TCB, + listing options={ + style=tcblatex, + numbers=none, + numberstyle=\color{red}, + #1, + }, + title={\color{black}{\scshape Listing \thetcbcounter}: ~#2},label={#4}, + #3, +} + +\lstdefinestyle{yaml-LST}{ + style=tcblatex, + numbers=none, + %numbers=left, + numberstyle=\color{red}, +} + +\lstdefinestyle{demo}{ + numbers=none, + linewidth=1.25\textwidth, + columns=fullflexible, +} + +% 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) + }}; + \node[anchor=north west,outer sep=2pt,opacity=0.25] at ([xshift=-4.25cm]frame.north west) {\resizebox{3cm}{!}{\faGithub}}; + }, + % 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} + +\newtcbox{yamltitlebox}[1][]{colframe=black!50!white,boxrule=.5pt,sharp corners,#1} + +\newcommand{\flagbox}[1]{% + \par + \makebox[30pt][l]{% + \hspace{-2cm}% + \ttfamily\fontseries{b}\selectfont #1 + }% +} + +\NewDocumentCommand{\yamltitle}{O{} m s m}{% + \par + \makebox[30pt][l]{% + \hspace{-2cm}% + \yamltitlebox[#1]{% + {\ttfamily\fontseries{b}\selectfont{\color{blue!80!white}#2}}: % + \IfBooleanTF{#3} + {$\langle$\itshape #4$\rangle$} + {{\bfseries #4}} + }} + \par\nobreak% +} + +\newcommand{\fixthis}[1] +{% + \marginpar{\huge \color{red} \framebox{FIX}}% + \typeout{FIXTHIS: p\thepage : #1^^J}% +} +% custom section +\titleformat{\section} +{\normalfont\Large\bfseries} +{\llap{\thesection\hskip.5cm}} +{0pt} +{} +% custom subsection +\titleformat{\subsection} +{\normalfont\bfseries} +{\llap{\thesubsection\hskip.5cm}} +{0pt} +{} +% custom subsubsection +\titleformat{\subsubsection} +{\normalfont\bfseries} +{\llap{\thesubsubsection\hskip.5cm}} +{0pt} +{} + +\titlespacing\section{0pt}{12pt plus 4pt minus 2pt}{-5pt plus 2pt minus 2pt} +\titlespacing\subsection{0pt}{12pt plus 4pt minus 2pt}{-6pt plus 2pt minus 2pt} +\titlespacing\subsubsection{0pt}{12pt plus 4pt minus 2pt}{-6pt plus 2pt minus 2pt} + +% list of listings +\contentsuse{lstlisting}{lol} +\titlecontents{lstlisting}[2em] + {\addvspace{0.25pc}} + {\textbf{Code \thecontentslabel} } + {} + {\titlerule*[0.5em]{$\cdot$}\contentspage} + [] +\AtBeginDocument{\addtocontents{lol}{\protect\begin{widepage}\protect\begin{multicols}{2}}} +\AtEndDocument{\addtocontents{lol}{\protect\end{multicols}\protect\end{widepage}}} + +% cleveref settings +\crefname{table}{Table}{Tables} +\Crefname{table}{Table}{Tables} +\crefname{figure}{Figure}{Figures} +\Crefname{figure}{Figure}{Figures} +\crefname{section}{Section}{Sections} +\Crefname{section}{Section}{Sections} +\crefname{listing}{Listing}{Listings} +\Crefname{listing}{Listing}{Listings} + +% headers and footers +\fancyhf{} % delete current header and footer +\fancyhead[R]{\bfseries\thepage% + \tikz[remember picture,overlay] { + \node at (1,0){\includegraphics{logo-bw}}; } +} +\fancyhead[L]{\rightmark} +\fancyheadoffset[L]{3cm} +\pagestyle{fancy} + +% renew plain style +\fancypagestyle{plain}{% + \fancyhf{} % clear all header and footer fields + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt}} + +% widepage environment +\newenvironment{widepage}{\begin{adjustwidth}{-3cm}{0cm}}{\end{adjustwidth}} + +% symbols for the m switch +\newcommand{\BeginStartsOnOwnLine}{\color{red}\spadesuit} +\newcommand{\BodyStartsOnOwnLine}{\color{red}\heartsuit} +\newcommand{\EndStartsOnOwnLine}{\color{red}\diamondsuit} +\newcommand{\EndFinishesWithLineBreak}{\color{red}\clubsuit} +\newcommand{\ElseStartsOnOwnLine}{\color{red}\bigstar} +\newcommand{\ElseFinishesWithLineBreak}{\color{red}\square} +\newcommand{\EqualsStartsOnOwnLine}{\color{red}\bullet} + +% table rules +\setlength\heavyrulewidth{0.25ex} +% gitinfo2 settings +\renewcommand{\gitMark}{\gitBranch\,@\,\gitAbbrevHash{}\,\textbullet{}\,\gitAuthorDate\,\textbullet{}\faGithub} + +% setting up gitinfo2: +% copy the file post-xxx-sample.txt from http://mirror.ctan.org/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 + +% http://tex.stackexchange.com/questions/233843/textasteriskcentered-invisible-with-garamondmathdesign +% remove the definition of \textasteriskcentered for TS1 encoding +\UndeclareTextCommand{\textasteriskcentered}{TS1} +% reinstate a default encoding +\DeclareTextSymbolDefault{\textasteriskcentered}{OT1} +% suitably define the command +\DeclareTextCommand{\textasteriskcentered}{OT1}{\raisebox{-.7ex}[1ex][0pt]{*}} + +\begin{document} +\renewcommand*{\thefootnote}{\arabic{footnote}} +\title{% + \begin{tcolorbox}[ + width=5.2cm, + boxrule=0pt, + colframe=white!40!black, + colback=white, + rightrule=2pt, + sharp corners, + enhanced, + overlay={\node[anchor=north east,outer sep=2pt] at ([xshift=3cm,yshift=4mm]frame.north east) {\includegraphics[width=3cm]{logo}}; }] + \centering\ttfamily\bfseries latexindent.pl\\[1cm] Version 3.0 + \end{tcolorbox} +} +\author{Chris Hughes \thanks{and contributors! See \vref{sec:contributors}. For + all communication, please visit \cite{latexindent-home}.}} +\maketitle +\begin{adjustwidth}{1cm}{1cm} + \small + \texttt{latexindent.pl} is a \texttt{Perl} script that indents \texttt{.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 \texttt{tabular}), + and commands, including those that can split braces and brackets across lines, + are \emph{usually} handled correctly by the script. Options for \texttt{verbatim}-like + environments and commands, together with indentation after headings (such as \lstinline!chapter!, \lstinline!section!, etc) + are also available. The script also has the ability to modifiy line breaks, and add + comment symbols. All user options are customisable via the switches in the YAML interface. +\end{adjustwidth} +\tableofcontents +{\small + \lstlistoflistings +} + +\input{sec-introduction} +\input{sec-demonstration} +\input{sec-how-to-use} +\input{sec-indent-config-and-settings.tex} +\input{sec-default-user-local} +\input{subsec-noAdditionalIndent-indentRules} +\input{subsubsec-environments-and-their-arguments} +\input{subsubsec-environments-with-items} +\input{subsubsec-commands-with-arguments} +\input{subsubsec-ifelsefi} +\input{subsubsec-special} +\input{subsubsec-headings} +\input{subsubsec-no-add-remaining-code-blocks} +\stopcontents[noAdditionalIndent] +\input{subsec-commands-and-their-options} +\input{sec-the-m-switch} +\input{subsec-partnering-poly-switches} +\input{subsec-conflicting-poly-switches} +\input{sec-conclusions-know-limitations} +\input{references} +\input{appendices} +\end{document} + +\subsection{The phases of \texttt{latexindent.pl}} + With these rules in mind, let's study a few test cases: + + latexindent.pl environments-line-break-conflict.tex -s -t -m -o environments-line-break-conflict-mod1.tex -l=env-conflicts-mod1.yaml + latexindent.pl environments-line-break-conflict-nested.tex -s -t -m -o environments-line-break-conflict-nested-mod-2.tex -l=env-conflicts-mod2.yaml + latexindent.pl environments-line-break-conflict-nested.tex -s -t -m -o environments-line-break-conflict-nested-mod-3.tex -l=env-conflicts-mod3.yaml + environments-first-opt-args.tex, see all of the different examples in test-cases.sh + environments-second-opt-args.tex provides some interesting cases too + + The \lstinline!\fi! command knows to insert a space, so as to give, for example, \lstinline!\fi! text, and avoid things such as \lstinline!\fitext! + + from yaml + diff --git a/Master/texmf-dist/doc/support/latexindent/logo.tex b/Master/texmf-dist/doc/support/latexindent/logo.tex new file mode 100644 index 00000000000..3b0841fcae5 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/logo.tex @@ -0,0 +1,20 @@ +% arara: pdflatex +% +% to create the black and white logo: +% convert -density 1000 -colorspace GRAY logo.pdf logo-bw.pdf +\documentclass[border=1mm]{standalone} + +\usepackage{tikz} +\usetikzlibrary{matrix} +\definecolor{harvestgold}{cmyk}{0.00, 0.05, 0.51, 0.07} %EDE275 +\definecolor{cmhgold}{cmyk}{0,0.178,0.909,0.008} %FDD017 +\definecolor{bakeoffblue}{cmyk}{0.24, 0.00, 0.02, 0.18} %9fd2cd +\definecolor{bakeoffgreen}{cmyk}{0.30, 0.00, 0.20, 0.29} %80b692 +\definecolor{burntorange}{cmyk}{0.00, 0.41, 1.00, 0.04} +\begin{document} +\begin{tikzpicture}[logo/.style={draw=blue,circle,fill=white}] + \matrix{ + \node[logo,dash pattern=on .5pt off 1.0pt,thick,draw=purple!75!white]{}; & \node[logo,draw=burntorange]{}; \\ + \node[logo,fill,draw=bakeoffgreen,fill=bakeoffblue]{}; & \node[logo,double,draw=cmhgold,fill=harvestgold]{};\\}; +\end{tikzpicture} +\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/references.tex b/Master/texmf-dist/doc/support/latexindent/references.tex new file mode 100644 index 00000000000..548b3945784 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/references.tex @@ -0,0 +1,4 @@ +\nocite{*} +\section{References} + \printbibliography[heading=subbibnumbered,title={External links},notkeyword=contributor] + \printbibliography[env=specialbib,heading=subbibnumbered,title={Contributors\label{sec:contributors}},keyword=contributor] diff --git a/Master/texmf-dist/doc/support/latexindent/sec-conclusions-know-limitations.tex b/Master/texmf-dist/doc/support/latexindent/sec-conclusions-know-limitations.tex new file mode 100644 index 00000000000..4f9053b9717 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/sec-conclusions-know-limitations.tex @@ -0,0 +1,38 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\section{Conclusions and known limitations}\label{sec:knownlimitations} + There are a number of known limitations of the script, and almost certainly quite a + few that are \emph{unknown}! + + For example, \texttt{latexindent.pl} will not indent the following code correctly, + because of the unmatched \lstinline![!. I'm hopeful to be able to resolve this + issue in a future version. + + \begin{lstlisting}[,nolol=true,] +\parbox{ +\@ifnextchar[{\@assignmentwithcutoff}{\@assignmentnocutoff} +} +\end{lstlisting} + + The main other limitation is to do with the alignment routine of environments/commands that contain + delimiters which are specified in \texttt{lookForAlignDelims}. + + The routine works well for `standard' blocks of code that have the same number of \lstinline!&! + per line, but it will not do anything for lines that do not -- such examples + include \texttt{tabular} environments that use \lstinline!\multicolumn! or + perhaps spread cell contents across multiple lines. For each alignment block (\texttt{tabular}, + \texttt{align}, etc) \texttt{latexindent.pl} first of all makes a record + of the maximum number of \lstinline!&!; if each row does not have that + number of \lstinline!&! then it will not try to format that row. Details + will be given in \texttt{indent.log} assuming that \texttt{trace} mode + is active. + + You can run \texttt{latexindent} on \texttt{.sty}, \texttt{.cls} and any file types + 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 \texttt{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, 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/users/6621/cmhughes}. diff --git a/Master/texmf-dist/doc/support/latexindent/sec-default-user-local.tex b/Master/texmf-dist/doc/support/latexindent/sec-default-user-local.tex new file mode 100644 index 00000000000..5dc0e8a77b4 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/sec-default-user-local.tex @@ -0,0 +1,492 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\section{defaultSettings.yaml}\label{sec:defuseloc} + \texttt{latexindent.pl} loads its settings from \texttt{defaultSettings.yaml}. The idea is to separate the behaviour of the script + from the internal working -- this is very similar to the way that we separate content + from form when writing our documents in \LaTeX. + + If you look in \texttt{defaultSettings.yaml} you'll find the switches + that govern the behaviour of \texttt{latexindent.pl}. If you're not sure where + \texttt{defaultSettings.yaml} resides on your computer, don't worry as \texttt{indent.log} + will tell you where to find it. + \texttt{defaultSettings.yaml} is commented, + but here is a description of what each switch is designed to do. The default + value is given in each case; whenever you see \emph{integer} in \emph{this} + section, assume that it must be greater than or equal to \texttt{0} unless + otherwise stated. + +\yamltitle{fileExtensionPreference}*{fields} + \texttt{latexindent.pl} can be called to + act on a file without + specifying the file extension. For example we can call + \begin{commandshell} +latexindent.pl myfile +\end{commandshell} + \begin{wrapfigure}[8]{r}[0pt]{6cm} + \cmhlistingsfromfile[firstnumber=22,linerange={22-26},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{fileExtensionPreference}}{lst:fileExtensionPreference} + \end{wrapfigure} + + in which case the script will look for \texttt{myfile} with the extensions + specified in \texttt{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. + + Calling \texttt{latexindent.pl myfile} with the (default) settings specified in \cref{lst:fileExtensionPreference} + means that the script will first look for \texttt{myfile.tex}, then \texttt{myfile.sty}, \texttt{myfile.cls}, + and finally \texttt{myfile.bib} in order\footnote{Throughout this manual, listings with line numbers represent code + taken directly from \texttt{defaultSettings.yaml}.}. + +\yamltitle{backupExtension}*{extension name} + + If you call \texttt{latexindent.pl} with the \texttt{-w} switch (to overwrite + \texttt{myfile.tex}) then it will create a backup file before doing + any indentation; the default extension is \texttt{.bak}, so, for example, \texttt{myfile.bak0} + would be created when calling \texttt{latexindent.pl myfile.tex} for the first time. + + By default, every time you subsequently call \texttt{latexindent.pl} with + the \texttt{-w} to act upon \texttt{myfile.tex}, it will create successive back up files: \texttt{myfile.bak1}, \texttt{myfile.bak2}, + etc. + +\yamltitle{onlyOneBackUp}*{integer} + \label{page:onlyonebackup} + If you don't want a backup for every time that you call \texttt{latexindent.pl} (so + you don't want \texttt{myfile.bak1}, \texttt{myfile.bak2}, etc) and you simply + want \texttt{myfile.bak} (or whatever you chose \texttt{backupExtension} to be) + then change \texttt{onlyOneBackUp} to \texttt{1}; the default value of + \texttt{onlyOneBackUp} is \texttt{0}. + +\yamltitle{maxNumberOfBackUps}*{integer} + 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 \texttt{maxNumberOfBackUps} is $0$ which will \emph{not} + prevent backup files being made; in this case, the behaviour will be dictated + entirely by \texttt{onlyOneBackUp}. The default value of \texttt{maxNumberOfBackUps} + is \texttt{0}. + +\yamltitle{cycleThroughBackUps}*{integer} + Some users may wish to cycle through backup files, by deleting the + oldest backup file and keeping only the most recent; for example, + with \texttt{maxNumberOfBackUps: 4}, and \texttt{cycleThroughBackUps} + set to \texttt{1} then the \texttt{copy} procedure given below + would be obeyed. + + \begin{commandshell} +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{commandshell} + The default value of \texttt{cycleThroughBackUps} is \texttt{0}. + +\yamltitle{logFilePreferences}*{fields} + \begin{wrapfigure}[10]{r}[0pt]{9cm} + \cmhlistingsfromfile[firstnumber=63,linerange={63-67},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.85\linewidth,before=\centering,yaml-TCB]{\texttt{logFilePreferences}}{lst:logFilePreferences} + \end{wrapfigure} + \texttt{latexindent.pl} writes information to \texttt{indent.log}, some + of which can be customised by changing \texttt{logFilePreferences}; see \cref{lst:logFilePreferences}. + If you load your own user settings (see \vref{sec:indentconfig}) then \texttt{latexindent.pl} will + detail them in \texttt{indent.log}; you can choose not to have the details logged by switching + \texttt{showEveryYamlRead} to \texttt{0}. Once all of your settings have + been loaded, you can see the amalgamated settings in the log file by switching \texttt{showAmalgamatedSettings} + to \texttt{1}, if you wish. The log file will end with the characters + given in \texttt{endLogFileWith}, and will report the \texttt{GitHub} address + of \texttt{latexindent.pl} to the log file if \texttt{showGitHubInfoFooter} is set to \texttt{1}. + +\yamltitle{verbatimEnvironments}*{fields} + + \begin{wrapfigure}[14]{r}[0pt]{6cm} + \cmhlistingsfromfile[firstnumber=71,linerange={71-73},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{verbatimEnvironments}}{lst:verbatimEnvironments} + + \vspace{.2cm} + \cmhlistingsfromfile[firstnumber=76,linerange={76-78},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{verbatimCommands}}{lst:verbatimCommands} + \end{wrapfigure} + A field that contains a list of environments + that you would like left completely alone -- no indentation will be performed + on environments that you have specified in this field, see \cref{lst:verbatimEnvironments}. + + Note that if you put an environment in \\ \texttt{verbatimEnvironments} + and in other fields such as \texttt{lookForAlignDelims} or \texttt{noAdditionalIndent} + then \texttt{latexindent.pl} will \emph{always} prioritize \\ \texttt{verbatimEnvironments}. + +\yamltitle{verbatimCommands}*{fields} + A field that contains a list of commands that are verbatim commands, for example + \lstinline|\lstinline|; any commands populated in this field are protected from line breaking + routines (only relevant if the \texttt{-m} is active, see \vref{sec:modifylinebreaks}). + +\yamltitle{noIndentBlock}*{fields} + + \begin{wrapfigure}[8]{r}[0pt]{6cm} + \cmhlistingsfromfile[firstnumber=84,linerange={84-86},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{noIndentBlock}}{lst:noIndentBlock} + \end{wrapfigure} + If you have a block of code that you don't want \texttt{latexindent.pl} to touch (even if it is \emph{not} a verbatim-like + environment) then you can wrap it in an environment from \texttt{noIndentBlock}; + you can use any name you like for this, provided you populate it as demonstrate in + \cref{lst:noIndentBlock}. + + Of course, you don't want to have to specify these as null environments + in your code, so you use them with a comment symbol, \lstinline!%!, followed + by as many spaces (possibly none) as you like; see \cref{lst:noIndentBlockdemo} for + example. + + \begin{cmhlistings}[style=demo,escapeinside={(*@}{@*)}]{\texttt{noIndentBlock} demonstration}{lst:noIndentBlockdemo} +%(*@@*) \begin{noindent} + this code + won't + be touched + by + latexindent.pl! +%(*@@*)\end{noindent} + \end{cmhlistings} + +\yamltitle{removeTrailingWhitespace}*{fields}\label{yaml:removeTrailingWhitespace} + + \begin{wrapfigure}[12]{r}[0pt]{6cm} + \cmhlistingsfromfile[firstnumber=89,linerange={89-91},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{removeTrailingWhitespace}{lst:removeTrailingWhitespace} + + \vspace{.2cm} + \cmhlistingsfromfile[firstnumber=95,linerange={95-98},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{fileContentsEnvironments}}{lst:fileContentsEnvironments} + \end{wrapfigure} + Trailing white space can be removed both \emph{before} and \emph{after} processing + the document, as detailed in \cref{lst:removeTrailingWhitespace}; each of the fields + can take the values \texttt{0} or \texttt{1}. See \vref{lst:removeTWS-before,lst:env-mlb5-modAll,lst:env-mlb5-modAll-remove-WS} + for before and after results. Thanks to \cite{vosskuhle} for providing this feature. + +\yamltitle{fileContentsEnvironments}*{field} + + Before \texttt{latexindent.pl} determines the difference between preamble (if any) and the main document, + it first searches for any of the environments specified in \texttt{fileContentsEnvironments}, see + \cref{lst:fileContentsEnvironments}. + The behaviour of \texttt{latexindent.pl} on these environments is determined by their location (preamble or not), and + the value \texttt{indentPreamble}, discussed next. + +\yamltitle{indentPreamble}{0|1} + + The preamble of a document can sometimes contain some trickier code + for \texttt{latexindent.pl} to operate upon. By default, \texttt{latexindent.pl} + won't try to operate on the preamble (as \texttt{indentPreamble} is set to \texttt{0}, + by default), but if you'd like \texttt{latexindent.pl} to try then change \texttt{indentPreamble} to \texttt{1}. + +\yamltitle{lookForPreamble}*{fields} + + \begin{wrapfigure}[8]{r}[0pt]{5cm} + \cmhlistingsfromfile[firstnumber=103,linerange={103-107},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{lookForPreamble}{lst:lookForPreamble} + \end{wrapfigure} + Not all files contain preamble; for example, \texttt{sty}, \texttt{cls} and \texttt{bib} files typically do \emph{not}. Referencing + \cref{lst:lookForPreamble}, if you set, for example, \texttt{.tex} to \texttt{0}, then regardless of the setting of the value of \texttt{indentPreamble}, preamble + will not be assumed when operating upon \texttt{.tex} files. +\yamltitle{preambleCommandsBeforeEnvironments}{0|1} + Assuming that \texttt{latexindent.pl} is asked to operate upon the preamble of a document, + when this switch is set to \texttt{0} then environment code blocks will be sought first, + and then command code blocks. When this switch is set to \texttt{1}, commands + will be sought first. The example that first motivated this switch contained the code given in \cref{lst:motivatepreambleCommandsBeforeEnvironments}. + + \begin{cmhlistings}{Motivating \texttt{preambleCommandsBeforeEnvironments}}{lst:motivatepreambleCommandsBeforeEnvironments} +... +preheadhook={\begin{mdframed}[style=myframedstyle]}, +postfoothook=\end{mdframed}, +... +\end{cmhlistings} + +\yamltitle{defaultIndent}*{horizontal space} + This is the default indentation (\lstinline!\t! means a tab, and is the default value) used in the absence of other details + for the command or environment we are working with; see \texttt{indentRules} in \vref{sec:noadd-indent-rules} + for more details. + + If you're interested in experimenting with \texttt{latexindent.pl} then you + can \emph{remove} all indentation by setting \texttt{defaultIndent: ""}. + +\yamltitle{lookForAlignDelims}*{fields} + \begin{wrapfigure}[12]{r}[0pt]{5cm} + \begin{yaml}[numbers=none]{\texttt{lookForAlignDelims} (basic)}[width=.8\linewidth,before=\centering]{lst:aligndelims:basic} +lookForAlignDelims: + tabular: 1 + tabularx: 1 + longtable: 1 + array: 1 + matrix: 1 + ... + \end{yaml} + \end{wrapfigure} + This contains a list of environments and/or commands that + are operated upon in a special way by \texttt{latexindent.pl} (see \cref{lst:aligndelims:basic}). + In fact, the fields in \texttt{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. + + The environments specified in this field will be operated on in a special way by \texttt{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:basic,lst:tabularafter:basic}. + + If you find that \texttt{latexindent.pl} does not perform satisfactorily on such + environments then you can set the relevant key to \texttt{0}, for example \texttt{tabular: 0}; alternatively, if you just want to ignore \emph{specific} + instances of the environment, you could wrap them in something from \texttt{noIndentBlock} (see \cref{lst:noIndentBlock}). + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tabular1.tex}{\texttt{tabular1.tex}}{lst:tabularbefore:basic} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tabular1-default.tex}{\texttt{tabular1.tex} default output}{lst:tabularafter:basic} + \end{minipage}% + + If you wish to remove the alignment of the \lstinline!\\! within a delimiter-aligned block, then the + advanced form of \texttt{lookForAlignDelims} shown in \cref{lst:aligndelims:advanced} is for you. + + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/tabular.yaml}[yaml-TCB]{\texttt{tabular.yaml}}{lst:aligndelims:advanced} + + Note that you can use a mixture of the basic and advanced form: in \cref{lst:aligndelims:advanced} \texttt{tabular} and \texttt{tabularx} + are advanced and \texttt{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 \texttt{delims}: switch equivalent to simply specifying, for example, \texttt{tabular: 1} in + the basic version shown in \cref{lst:aligndelims:basic} (default: 1); + \item \texttt{alignDoubleBackSlash}: switch to determine if \lstinline!\\! should be aligned (default: 1); + \item \texttt{spacesBeforeDoubleBackSlash}: optionally, specifies the number of spaces to be inserted + before (non-aligned) \lstinline!\\!. In order to use this field, \texttt{alignDoubleBackSlash} needs + to be set to 0 (default: 0). + \end{itemize} + + Assuming that you have the settings in \cref{lst:aligndelims:advanced} saved in \texttt{tabular.yaml}, and the code + from \cref{lst:tabularbefore:basic} in \texttt{tabular1.tex} and you run + \begin{commandshell} +latexindent.pl -l tabular.yaml tabular1.tex +\end{commandshell} + then you should 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}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tabular1.tex}{\texttt{tabular1.tex}}{lst:tabularbefore:advanced} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tabular1-advanced.tex}{\texttt{tabular1.tex} using \cref{lst:aligndelims:advanced}}{lst:tabularafter:advanced} + \end{minipage}% + + Saving \cref{lst:aligndelims:advanced} into \texttt{tabular1.yaml} as in \cref{lst:tabular1YAML}, and running the command + \begin{commandshell} +latexindent.pl -l tabular1.yaml tabular1.tex +\end{commandshell} + gives \cref{lst:tabularafter:spacing}; note the spacing before the \lstinline!\\!. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tabular1-advanced-3spaces.tex}{\texttt{tabular1.tex} using \cref{lst:tabular1YAML}}{lst:tabularafter:spacing} + \end{minipage}% + \hfill + \begin{minipage}{.54\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/tabular1.yaml}[yaml-TCB]{\texttt{tabular1.yaml}}{lst:tabular1YAML} + \end{minipage}% + + As of Version 3.0, the alignment routine works on mandatory and optional arguments within commands, and also within `special' code blocks + (see \texttt{specialBeginEnd} on \cpageref{yaml:specialBeginEnd}); for example, assuming that you have a command called \lstinline!\matrix! + and that it is populated within \texttt{lookForAlignDelims} (which it is, by default), and that you + run the command + \begin{commandshell} +latexindent.pl matrix1.tex + \end{commandshell} + then the before-and-after results + shown in \cref{lst:matrixbefore,lst:matrixafter} are achievable by default. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/matrix1.tex}{\texttt{matrix1.tex}}{lst:matrixbefore} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/matrix1-default.tex}{\texttt{matrix1.tex} default output}{lst:matrixafter} + \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}! \ldots \lstinline!\end{tabular}!, then you can use the mark up + illustrated in \cref{lst:alignmentmarkup}; the default output is shown in \cref{lst:alignmentmarkup-default}. 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 \texttt{lookForAlignDelims}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/align-block.tex}{\texttt{align-block.tex}}{lst:alignmentmarkup} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/align-block-default.tex}{\texttt{align-block.tex} default output}{lst:alignmentmarkup-default} + \end{minipage}% + + With reference to \vref{tab:code-blocks} and the, yet undiscussed, fields of \texttt{noAdditionalIndent} and \texttt{indentRules} + (see \vref{sec:noadd-indent-rules}), these comment-marked blocks are considered \texttt{environments}. + +\yamltitle{indentAfterItems}*{fields} + \begin{wrapfigure}[5]{r}[0pt]{7cm} + \cmhlistingsfromfile[firstnumber=155,linerange={155-158},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{indentAfterItems}}{lst:indentafteritems} + \end{wrapfigure} + The environment names specified in \texttt{indentAfterItems} tell + \texttt{latexindent.pl} to look for \lstinline!\item! commands; if these switches are set to \texttt{1} + then indentation will be performed so as indent the code after each \texttt{item}. + A demonstration is given in \cref{lst:itemsbefore,lst:itemsafter} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/items1.tex}{\texttt{items1.tex}}{lst:itemsbefore} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/items1-default.tex}{\texttt{items1.tex} default output}{lst:itemsafter} + \end{minipage} + +\yamltitle{itemNames}*{fields} + \begin{wrapfigure}[5]{r}[0pt]{5cm} + \cmhlistingsfromfile[firstnumber=164,linerange={164-166},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{itemNames}}{lst:itemNames} + \end{wrapfigure} + If you have your own \texttt{item} commands (perhaps you + prefer to use \texttt{myitem}, for example) + then you can put populate them in \texttt{itemNames}. + For example, users of the \texttt{exam} document class might like to add + \texttt{parts} to \texttt{indentAfterItems} and \texttt{part} to \texttt{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}.) + +\yamltitle{specialBeginEnd}*{fields}\label{yaml:specialBeginEnd} + The fields specified in \texttt{specialBeginEnd} are, in their default state, focused on math mode begin and end statements, but + there is no requirement for this to be the case; \cref{lst:specialBeginEnd} shows the + default settings of \texttt{specialBeginEnd}. + + \cmhlistingsfromfile[firstnumber=170,linerange={170-182},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{specialBeginEnd}}{lst:specialBeginEnd} + + The field \texttt{displayMath} represents \lstinline!\[...\]!, \texttt{inlineMath} represents + \lstinline!$...$! and \texttt{displayMathTex} represents \lstinline!$$...$$!. You can, of course, + rename these in your own YAML files (see \vref{sec:localsettings}); indeed, you + might like to set up your own specil begin and end statements. + + A demonstration of the before-and-after results are shown in \cref{lst:specialbefore,lst:specialafter}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1.tex}{\texttt{special1.tex} before}{lst:specialbefore} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1-default.tex}{\texttt{special1.tex} default output}{lst:specialafter} + \end{minipage} + + For each field, \texttt{lookForThis} is set to \texttt{1} by default, which means that \texttt{latexindent.pl} + will look for this pattern; you can tell \texttt{latexindent.pl} not to look for the pattern, by setting + \texttt{lookForThis} to \texttt{0}. + +\yamltitle{indentAfterHeadings}*{fields} + \begin{wrapfigure}[17]{r}[0pt]{8cm} + \cmhlistingsfromfile[firstnumber=192,linerange={192-201},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{indentAfterHeadings}}{lst:indentAfterHeadings} + \end{wrapfigure} + 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*!, or indeed any user-specified command written in this field.\footnote{There is a slight + difference in interface for this field when comparing Version 2.2 to Version 3.0; see \vref{app:differences} for details.} + + The default settings do \emph{not} place indentation after a heading, but you + can easily switch them on by changing \\ \texttt{indentAfterThisHeading: 0} to \\ \texttt{indentAfterThisHeading: 1}. + The \texttt{level} field tells \texttt{latexindent.pl} the hierarchy of the heading + structure in your document. You might, for example, like to have both \texttt{section} + and \texttt{subsection} set with \texttt{level: 3} because you do not want the indentation to go too deep. + + You can add any of your own custom heading commands to this field, specifying the \texttt{level} + as appropriate. You can also specify your own indentation in \texttt{indentRules} (see \vref{sec:noadd-indent-rules}); + you will find the default \texttt{indentRules} contains \lstinline!chapter: " "! which + tells \texttt{latexindent.pl} simply to use a space character after \texttt{\chapter} headings + (once \texttt{indent} is set to \texttt{1} for \texttt{chapter}). + + For example, assuming that you have the code in \cref{lst:headings1yaml} saved into \texttt{headings1.yaml}, + and that you have the text from \cref{lst:headings1} saved into \texttt{headings1.tex}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings1.yaml}[yaml-TCB]{\texttt{headings1.yaml}}{lst:headings1yaml} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings1.tex}{\texttt{headings1.tex}}{lst:headings1} + \end{minipage} + + If you run the command + \begin{commandshell} +latexindent.pl headings1.tex -l=headings1.yaml +\end{commandshell} + then you should receive the output given in \cref{lst:headings1-mod1}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings1-mod1.tex}{\texttt{headings1.tex} using \cref{lst:headings1yaml}}{lst:headings1-mod1} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings1-mod2.tex}{\texttt{headings1.tex} second modification}{lst:headings1-mod2} + \end{minipage} + + Now say that you modify the \texttt{YAML} from \cref{lst:headings1yaml} so that the \texttt{paragraph} \texttt{level} is \texttt{1}; after + running + \begin{commandshell} +latexindent.pl headings1.tex -l=headings1.yaml +\end{commandshell} + you should receive the code given in \cref{lst:headings1-mod2}; notice that + the \texttt{paragraph} and \texttt{subsection} are at the same indentation level. + +\subsection{The code blocks known \texttt{latexindent.pl}}\label{subsubsec:code-blocks} + As of Version 3.0, \texttt{latexindent.pl} processes documents using code blocks; each + of these are shown in \cref{tab:code-blocks}. + + \begin{longtable}{m{.3\linewidth}@{\hspace{.25cm}}m{.4\linewidth}@{}m{.2\linewidth}} + \caption{Code blocks known to \texttt{latexindent.pl}}\label{tab:code-blocks}\\ + \toprule + Code block & characters allowed in name & example \\ + \midrule + environments & \lstinline!a-zA-Z@\*0-9_\\! & + \begin{lstlisting}[,nolol=true,] +\begin{myenv} +body of myenv +\end{myenv} + \end{lstlisting} + \\\cmidrule{2-3} + optionalArguments & \emph{inherits} name from parent (e.g environment name) & + \begin{lstlisting}[,nolol=true,] +[ +opt arg text +] + \end{lstlisting} + \\\cmidrule{2-3} + mandatoryArguments & \emph{inherits} name from parent (e.g environment name) & + \begin{lstlisting}[,nolol=true,] +{ +mand arg text +} + \end{lstlisting} + \\\cmidrule{2-3} + commands & \lstinline!+a-zA-Z@\*0-9_\:! & \lstinline!\mycommand!$\langle$\itshape{arguments}$\rangle$ \\\cmidrule{2-3} + keyEqualsValuesBracesBrackets & \lstinline!a-zA-Z@\*0-9_\/.\h\{\}:\#-! & \lstinline!my key/.style=!$\langle$\itshape{arguments}$\rangle$ \\\cmidrule{2-3} + namedGroupingBracesBrackets & \lstinline!a-zA-Z@\*> output.tex +\end{commandshell} + See \vref{app:differences} for details of how the interface has changed + from Version 2.2 to Version 3.0 for this flag. +\flagbox{-s, --silent} + \begin{commandshell} +latexindent.pl -s myfile.tex +latexindent.pl myfile.tex -s + \end{commandshell} + + Silent mode: no output will be given to the terminal. + +\flagbox{-t, --trace} + \begin{commandshell} +latexindent.pl -t myfile.tex +latexindent.pl myfile.tex -t + \end{commandshell} + + \label{page:traceswitch} + Tracing mode: verbose output will be given to \texttt{indent.log}. This + is useful if \texttt{latexindent.pl} has made a mistake and you're + trying to find out where and why. You might also be interested in learning + about \texttt{latexindent.pl}'s thought process -- if so, this + switch is for you, although it should be noted that, especially for large files, this does affect + performance of the script. + +\flagbox{-tt, --ttrace} + \begin{commandshell} +latexindent.pl -tt myfile.tex +latexindent.pl myfile.tex -tt + \end{commandshell} + + \emph{More detailed} tracing mode: this option gives more details to \texttt{indent.log} + than the standard \texttt{trace} option (note that, even more so than with \texttt{-t}, + especially for large files, performance of the script will be affected). + +\flagbox{-l, --local[=myyaml.yaml,other.yaml,...]} + \begin{commandshell} +latexindent.pl -l myfile.tex +latexindent.pl -l=myyaml.yaml myfile.tex +latexindent.pl -l myyaml.yaml myfile.tex +latexindent.pl -l first.yaml,second.yaml,third.yaml myfile.tex +latexindent.pl -l=first.yaml,second.yaml,third.yaml myfile.tex +latexindent.pl myfile.tex -l=first.yaml,second.yaml,third.yaml + \end{commandshell} + + \label{page:localswitch} + \texttt{latexindent.pl} will always load \texttt{defaultSettings.yaml} (rhymes with camel) + and if it is called with the \texttt{-l} switch and it finds \texttt{localSettings.yaml} + in the same directory as \texttt{myfile.tex} then these settings will be + added to the indentation scheme. Information will be given in \texttt{indent.log} on + the success or failure of loading \texttt{localSettings.yaml}. + + The \texttt{-l} flag can take an \emph{optional} parameter which details the name (or names separated by commas) of a YAML file(s) + that resides in the same directory as \texttt{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 \texttt{localSettings.yaml}. + In fact, you can specify \emph{relative} path names to the current directory, but \emph{not} + absolute paths -- for absolute paths, see \vref{sec:indentconfig}. + Explicit demonstrations of how to use the \texttt{-l} switch are given throughout this documentation. + +\flagbox{-d, --onlydefault} + \begin{commandshell} +latexindent.pl -d myfile.tex + \end{commandshell} + + Only \texttt{defaultSettings.yaml}: you might like to read \cref{sec:defuseloc} before + using this switch. By default, \texttt{latexindent.pl} will always search for + \texttt{indentconfig.yaml} or \texttt{.indentconfig.yaml} in your home directory. If you would prefer it not to do so + then (instead of deleting or renaming \texttt{indentconfig.yaml}/\texttt{.indentconfig.yaml}) you can simply + call the script with the \texttt{-d} switch; note that this will also tell + the script to ignore \texttt{localSettings.yaml} even if it has been called with the + \texttt{-l} switch. + +\flagbox{-c, --cruft=} + \begin{commandshell} +latexindent.pl -c=/path/to/directory/ myfile.tex + \end{commandshell} + + If you wish to have backup files and \texttt{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 + +\flagbox{-g, --logfile} + \begin{commandshell} +latexindent.pl -g=other.log myfile.tex +latexindent.pl -g other.log myfile.tex +latexindent.pl --logfile other.log myfile.tex +latexindent.pl myfile.tex -g other.log + \end{commandshell} + + By default, \texttt{latexindent.pl} reports information to \texttt{indent.log}, but if you wish to change the + name of this file, simply call the script with your chosen name after the \texttt{-g} switch as demonstrated above. + +\flagbox{-m, --modifylinebreaks} + \begin{commandshell} +latexindent.pl -m myfile.tex +latexindent.pl -modifylinebreaks myfile.tex + \end{commandshell} + + One of the most exciting developments in Version~3.0 is the ability to modify line breaks; for full details + see \vref{sec:modifylinebreaks} + + \texttt{latexindent.pl} can also be called on a file without the file extension, for + example + \begin{commandshell} +latexindent.pl myfile + \end{commandshell} + and in which case, you can specify + the order in which extensions are searched for; see \vref{lst:fileExtensionPreference} + for full details. + +\subsection{From \texttt{arara}}\label{sec:arara} + Using \texttt{latexindent.pl} from the command line is fine for some folks, but + others may find it easier to use from \texttt{arara}. \texttt{arara} ships with + a rule, \texttt{indent.yaml}, but in case you do not have this rule, you can find it at \cite{paulo}. + + You can use the rule in any of the ways described in \cref{lst:arara} (or combinations thereof). + In fact, \texttt{arara} allows yet greater flexibility -- you can use \texttt{yes/no}, \texttt{true/false}, or \texttt{on/off} to toggle the various options. + \begin{cmhlistings}[style=demo,escapeinside={(*@}{@*)}]{\texttt{arara} sample usage}{lst:arara} +%(*@@*) arara: indent +%(*@@*) arara: indent: {overwrite: yes} +%(*@@*) arara: indent: {output: myfile.tex} +%(*@@*) arara: indent: {silent: yes} +%(*@@*) arara: indent: {trace: yes} +%(*@@*) arara: indent: {localSettings: yes} +%(*@@*) arara: indent: {onlyDefault: on} +%(*@@*) arara: indent: { cruft: /home/cmhughes/Desktop } +\documentclass{article} +... +\end{cmhlistings} +%(*@@*) arara: indent: { modifylinebreaks: yes } + + Hopefully the use of these rules is fairly self-explanatory, but for completeness + \cref{tab:orbsandswitches} shows the relationship between \texttt{arara} directive arguments and the + switches given in \cref{sec:commandline}. + + \begin{table}[!ht] + \centering + \caption{\texttt{arara} directive arguments and corresponding switches} + \label{tab:orbsandswitches} + \begin{tabular}{lc} + \toprule + \texttt{arara} directive argument & switch \\ + \midrule + \texttt{overwrite} & \texttt{-w} \\ + \texttt{output} & \texttt{-o} \\ + \texttt{silent} & \texttt{-s} \\ + \texttt{trace} & \texttt{-t} \\ + \texttt{localSettings} & \texttt{-l} \\ + \texttt{onlyDefault} & \texttt{-d} \\ + \texttt{cruft} & \texttt{-c} \\ + \texttt{modifylinebreaks} & \texttt{-m} \\ + \bottomrule + \end{tabular} + \end{table} + + The \texttt{cruft} directive does not work well when used with + directories that contain spaces. + diff --git a/Master/texmf-dist/doc/support/latexindent/sec-indent-config-and-settings.tex b/Master/texmf-dist/doc/support/latexindent/sec-indent-config-and-settings.tex new file mode 100644 index 00000000000..a3cffa0921a --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/sec-indent-config-and-settings.tex @@ -0,0 +1,154 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\section{User, local settings, \texttt{indentconfig.yaml} and \texttt{.indentconfig.yaml}}\label{sec:indentconfig} + Editing \texttt{defaultSettings.yaml} is not ideal as it may be overwritten when + updating your distribution--a better way to customize the settings to your liking + is to set up your own settings file, + \texttt{mysettings.yaml} (or any name you like, provided it ends with \texttt{.yaml}). + The only thing you have to do is tell \texttt{latexindent.pl} where to find it. + + \texttt{latexindent.pl} will always check your home directory for \texttt{indentconfig.yaml} + and \texttt{.indentconfig.yaml} (unless + it is called with the \texttt{-d} switch), + which is a plain text file you can create that contains the \emph{absolute} + paths for any settings files that you wish \texttt{latexindent.pl} to load. There is no difference + between \texttt{indentconfig.yaml} and \texttt{.indentconfig.yaml}, other than the + fact that \texttt{.indentconfig.yaml} is a `hidden' file; thank you to \cite{jacobo-diaz-hidden-config} + for providing this feature. In what follows, we will use \texttt{indentconfig.yaml}, but it + is understood that this equally represents \texttt{.indentconfig.yaml} as well. If you + have both files in existence, \texttt{indentconfig.yaml} takes priority. + + For Mac and Linux users, their home directory is \texttt{~/username} while + Windows (Vista onwards) is \lstinline!C:\Users\username!\footnote{If you're not sure + where to put \texttt{indentconfig.yaml}, don't + worry \texttt{latexindent.pl} will tell you in the log file exactly where to + put it assuming it doesn't exist already.} + \Cref{lst:indentconfig} shows a sample \texttt{indentconfig.yaml} file. + + \begin{yaml}{\texttt{indentconfig.yaml} (sample)}{lst:indentconfig} + # Paths to user settings for latexindent.pl + # + # Note that the settings will be read in the order you + # specify here- each successive settings file will overwrite + # the variables that you specify + + paths: + - /home/cmhughes/Documents/yamlfiles/mysettings.yaml + - /home/cmhughes/folder/othersettings.yaml + - /some/other/folder/anynameyouwant.yaml + - C:\Users\chughes\Documents\mysettings.yaml + - C:\Users\chughes\Desktop\test spaces\more spaces.yaml +\end{yaml} + + Note that the \texttt{.yaml} files you specify in \texttt{indentconfig.yaml} + will be loaded in the order that you write them in. Each file doesn't have + to have every switch from \texttt{defaultSettings.yaml}; in fact, I recommend + that you only keep the switches that you want to \emph{change} in these + settings files. + + To get started with your own settings file, you might like to save a copy of + \texttt{defaultSettings.yaml} in another directory and call it, for + example, \texttt{mysettings.yaml}. Once you have added the path to \texttt{indentconfig.yaml} + you can change the switches and add more code-block names 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 \texttt{tabbing} + environment/command to the list of environments that contains alignment delimiters; you might also like to + refer to the many YAML files detailed throughout the rest of this documentation. + + \begin{yaml}{\texttt{mysettings.yaml} (example)}{lst:mysettings} +# Default value of indentation +defaultIndent: "\t\t\t\t" + +# environments that have tab delimiters, add more +# as needed +lookForAlignDelims: + tabbing: 1 +\end{yaml} + + You can make sure that your settings are loaded by checking \texttt{indent.log} + for details -- if you have specified a path that \texttt{latexindent.pl} doesn't + recognize then you'll get a warning, otherwise you'll get confirmation that + \texttt{latexindent.pl} has read your settings file \footnote{Windows users + may find that they have to end \texttt{.yaml} files with a blank line}. + + \begin{warning} + When editing \texttt{.yaml} files it is \emph{extremely} important + to remember how sensitive they are to spaces. I highly recommend copying + and pasting from \texttt{defaultSettings.yaml} when you create your + first \texttt{whatevernameyoulike.yaml} file. + + If \texttt{latexindent.pl} can not read your \texttt{.yaml} file it + will tell you so in \texttt{indent.log}. + \end{warning} + +\subsection{\texttt{localSettings.yaml}}\label{sec:localsettings} + The \texttt{-l} switch tells \texttt{latexindent.pl} to look for \texttt{localSettings.yaml} in the + \emph{same directory} as \texttt{myfile.tex}. If you'd prefer to name your \texttt{localSettings.yaml} file something + different, (say, \texttt{myyaml.yaml}) then + you can call \texttt{latexindent.pl} using, for example, + \begin{commandshell} +latexindent.pl -l=myyaml.yaml myfile.tex +\end{commandshell} + + Any settings file(s) specified using the \texttt{-l} switch will be read \emph{after} \texttt{defaultSettings.yaml} and, assuming they exist, + user settings from \texttt{indentconfig.yaml}. + + Your settings file can contain any switches that you'd + like to change; a sample is shown in \cref{lst:localSettings}, and you'll find plenty of further examples throughout this manual. + + \begin{yaml}{\texttt{localSettings.yaml} (example)}{lst:localSettings} +# verbatim environments- environments specified +# in this hash table will not be changed at all! +verbatimEnvironments: + cmhenvironment: 0 +\end{yaml} + + You can make sure that your settings file has been loaded by checking \texttt{indent.log} + for details; if it can not be read then you receive a warning, otherwise you'll get confirmation that + \texttt{latexindent.pl} has read your settings file. + +\subsection{Settings load order}\label{sec:loadorder} + \texttt{latexindent.pl} loads the settings files in the following order: + \begin{enumerate} + \item \texttt{defaultSettings.yaml} is always loaded, and can not be renamed; + \item \texttt{anyUserSettings.yaml} and any other arbitrarily-named files specified in \texttt{indentconfig.yaml}; + \item \texttt{localSettings.yaml} but only if found in the same directory as \texttt{myfile.tex} and called + with \texttt{-l} switch; this file can be renamed, provided that the call to \texttt{latexindent.pl} is adjusted + accordingly (see \cref{sec:localsettings}). You may specify relative paths to other + YAML files using the \texttt{-l} switch, separating multiple files using commas. + \end{enumerate} + A visual representation of this is given in \cref{fig:loadorder}. + + \begin{figure} + \centering + \begin{tikzpicture}[ + needed/.style={very thick, draw=blue,fill=blue!20, + text centered, minimum height=2.5em,rounded corners=1ex}, + optional/.style={draw=black, very thick,scale=0.8, + text centered, minimum height=2.5em,rounded corners=1ex}, + optionalfill/.style={fill=black!10}, + connections/.style={draw=black!30,dotted,line width=3pt,text=red}, + ] + % Draw diagram elements + \node (latexindent) [needed,circle] {\texttt{latexindent.pl}}; + \node (default) [needed,above right=.5cm of latexindent] {\texttt{defaultSettings.yaml}}; + \node (indentconfig) [optional,right=of latexindent] {\texttt{indentconfig.yaml}}; + \node (any) [optional,optionalfill,above right=of indentconfig] {\texttt{any.yaml}}; + \node (name) [optional,optionalfill,right=of indentconfig] {\texttt{name.yaml}}; + \node (you) [optional,optionalfill,below right=of indentconfig] {\texttt{you.yaml}}; + \node (want) [optional,optionalfill,below=of indentconfig] {\texttt{want.yaml}}; + \node (local) [optional,below=of latexindent] {\texttt{localSettings.yaml}}; + % Draw arrows between elements + \draw[connections,solid] (latexindent) to[in=-90]node[pos=0.5,anchor=north]{1} (default.south) ; + \draw[connections,optional] (latexindent) -- node[pos=0.5,anchor=north]{2} (indentconfig) ; + \draw[connections,optional] (indentconfig) to[in=-90] (any.south) ; + \draw[connections,optional] (indentconfig) -- (name) ; + \draw[connections,optional] (indentconfig) to[out=-45,in=90] (you) ; + \draw[connections,optional] (indentconfig) -- (want) ; + \draw[connections,optional] (latexindent) -- node[pos=0.5,anchor=west]{3} (local) ; + \end{tikzpicture} + \caption{Schematic of the load order described in \cref{sec:loadorder}; solid lines represent + mandatory files, dotted lines represent optional files. \texttt{indentconfig.yaml} can + contain as many files as you like. The files will be loaded in order; if you specify + settings for the same field in more than one file, the most recent takes priority. } + \label{fig:loadorder} + \end{figure} diff --git a/Master/texmf-dist/doc/support/latexindent/sec-introduction.tex b/Master/texmf-dist/doc/support/latexindent/sec-introduction.tex new file mode 100644 index 00000000000..ffe81105a01 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/sec-introduction.tex @@ -0,0 +1,47 @@ +\section{Introduction} +\subsection{Thanks} + I first created \texttt{latexindent.pl} to help me format chapter files + in a big project. After I blogged about it on the + \TeX{} stack exchange \cite{cmhblog} I received some positive feedback and + follow-up feature requests. A big thank you to Harish Kumar who + helped to develop and test the initial versions of the script. + + The \texttt{YAML}-based interface of \texttt{latexindent.pl} was inspired + by the wonderful \texttt{arara} tool; any similarities are deliberate, and + I hope that it is perceived as the compliment that it is. Thank you to Paulo Cereda and the + team for releasing this awesome tool; I initially worried that I was going to + have to make a GUI for \texttt{latexindent.pl}, but the release of \texttt{arara} + has meant there is no need. + + 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, and thank you to those who report bugs and request features + at \cite{latexindent-home}. + +\subsection{License} + \texttt{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 \texttt{latexindent.pl} has the option to overwrite your \texttt{.tex} files. + It will always make at least one backup (you can choose how many it makes, see \cpageref{page:onlyonebackup}) + but you should still be careful when using it. The script has been tested on many + files, but there are some known limitations (see \cref{sec:knownlimitations}). + You, the user, are responsible for ensuring that you maintain backups of your files + before running \texttt{latexindent.pl} on them. I think it is important at this + stage to restate an important part of the license here: + \begin{quote}\itshape + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + \end{quote} + There is certainly no malicious intent in releasing this script, and I do hope + that it works as you expect it to; if it does not, please first of all + make sure that you have the correct settings, and then feel free to let me know at \cite{latexindent-home} with a + complete minimum working example as I would like to improve the code as much as possible. + \begin{warning} + Before you try the script on anything important (like your thesis), test it + out on the sample files in the \texttt{test-case} directory \cite{latexindent-home}. + \end{warning} + + \emph{If you have used any version 2.* of \texttt{latexindent.pl}, there + are a few changes to the interface; see \vref{app:differences} and the comments + throughout this document for details}. diff --git a/Master/texmf-dist/doc/support/latexindent/sec-the-m-switch.tex b/Master/texmf-dist/doc/support/latexindent/sec-the-m-switch.tex new file mode 100644 index 00000000000..541a66572d2 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/sec-the-m-switch.tex @@ -0,0 +1,555 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +% the -m switch +% the -m switch +% the -m switch + +\fancyhead[R]{\bfseries\thepage% + \tikz[remember picture,overlay] { + \node at (1,0){\includegraphics{logo}}; + }} +\section{The \texttt{-m} (\texttt{modifylinebreaks}) switch}\label{sec:modifylinebreaks} + All features described in this section will only be relevant if the \texttt{-m} switch + is used. + +\yamltitle{modifylinebreaks}*{fields} + \begin{wrapfigure}[7]{r}[0pt]{8cm} + \cmhlistingsfromfile[firstnumber=356,linerange={356-358},style=yaml-LST,numbers=left,]{../defaultSettings.yaml}[MLB-TCB,width=.85\linewidth,before=\centering]{\texttt{modifyLineBreaks}}{lst:modifylinebreaks} + \end{wrapfigure} + \makebox[0pt][r]{% + \raisebox{-\totalheight}[0pt][0pt]{% + \tikz\node[opacity=1] at (0,0) {\includegraphics[width=4cm]{logo}};}}% + One of the most exciting features of Version 3.0 is the \texttt{-m} switch, which + permits \texttt{latexindent.pl} to modify line breaks, according to the + specifications in the \texttt{modifyLineBreaks} field. \emph{The settings + in this field will only be considered if the \texttt{-m} switch has been used}. + A snippet of the default settings of this field is shown in \cref{lst:modifylinebreaks}. + + Having read the previous paragraph, it should sound reasonable that, if you call \texttt{latexindent.pl} + using the \texttt{-m} switch, then you give it permission to modify line breaks in your file, + but let's be clear: + + \begin{warning} + If you call \texttt{latexindent.pl} with the \texttt{-m} switch, then you + are giving it permission to modify line breaks. By default, the only + thing that will happen is that multiple blank lines will be condensed into + one blank line; many other settings are possible, discussed next. + \end{warning} + +\yamltitle{preserveBlankLines}{0|1} + This field is directly related to \emph{poly-switches}, discussed below. + By default, it is set to \texttt{1}, which means that blank lines will + be protected from removal; however, regardless of this setting, multiple + blank lines can be condensed if \texttt{condenseMultipleBlankLinesInto} is + greater than \texttt{0}, discussed next. + +\yamltitle{condenseMultipleBlankLinesInto}*{integer $\geq 0$} + Assuming that this switch takes an integer value greater than \texttt{0}, \texttt{latexindent.pl} will condense multiple blank lines into + the number of blank lines illustrated by this switch. As an example, \cref{lst:mlb-bl} shows a sample file + with blank lines; upon running + \begin{commandshell} +latexindent.pl myfile.tex -m +\end{commandshell} + the output is shown in \cref{lst:mlb-bl-out}; note that the multiple blank lines have been + condensed into one blank line, and note also that we have used the \texttt{-m} switch! + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mlb1.tex}{\texttt{mlb1.tex}}{lst:mlb-bl} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mlb1-out.tex}{\texttt{mlb1.tex} out output}{lst:mlb-bl-out} + \end{minipage} + +\subsection{Poly-switches} + Every other field in the \texttt{modifyLineBreaks} field uses poly-switches, and can take + one of four integer values\footnote{You might like to associate one of the four circles in the logo with one of the four given values}: + \begin{itemize}[font=\bfseries] + \item[$-1$] \emph{remove mode}: line breaks before or after the \emph{} can be removed (assuming that \texttt{preserveBlankLines} is set to \texttt{0}); + \item[0] \emph{off mode}: line breaks will not be modified for the \emph{} under consideration; + \item[1] \emph{add mode}: a line break will be added before or after the \emph{} under consideration, assuming that + there is not already a line break before or after the \emph{}; + \item[2] \emph{comment then add mode}: a comment symbol will be added, followed by a line break before or after the \emph{} under consideration, assuming that + there is not already a comment and line break before or after the \emph{}. + \end{itemize} + All poly-switches are \emph{off} by default; \texttt{latexindent.pl} searches first of all for per-name settings, and then followed by global per-thing settings. + +\subsection{modifyLineBreaks for environments}\label{sec:modifylinebreaks-environments} + We start by viewing a snippet of \texttt{defaultSettings.yaml} in \cref{lst:environments-mlb}; note that it contains \emph{global} settings (immediately + after the \texttt{environments} field) and that \emph{per-name} settings are also allowed -- in the case of \cref{lst:environments-mlb}, settings + for \texttt{equation*} have been specified. Note that all poly-switches are \emph{off} by default. + + \cmhlistingsfromfile[firstnumber=359,linerange={359-368},style=yaml-LST,numbers=left,]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,MLB-TCB]{\texttt{environments}}{lst:environments-mlb} + +\subsubsection{Adding line breaks (poly-switches set to $1$ or $2$)} + Let's begin with the simple example given in \cref{lst:env-mlb1-tex}; note that we have annotated key parts of the file using $\BeginStartsOnOwnLine$, + $\BodyStartsOnOwnLine$, $\EndStartsOnOwnLine$ and $\EndFinishesWithLineBreak$, these will be related to fields specified in \cref{lst:environments-mlb}. + + \begin{cmhlistings}[escapeinside={(*@}{@*)}]{\texttt{env-mlb1.tex}}{lst:env-mlb1-tex} +before words(*@$\BeginStartsOnOwnLine$@*) \begin{myenv}(*@$\BodyStartsOnOwnLine$@*)body of myenv(*@$\EndStartsOnOwnLine$@*)\end{myenv}(*@$\EndFinishesWithLineBreak$@*) after words +\end{cmhlistings} + + Let's explore \texttt{BeginStartsOnOwnLine} and \texttt{BodyStartsOnOwnLine} in \cref{lst:env-mlb1,lst:env-mlb2}, and in particular, + let's allow each of them in turn to take a value of $1$. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb1.yaml}[MLB-TCB]{\texttt{env-mlb1.yaml}}{lst:env-mlb1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb2.yaml}[MLB-TCB]{\texttt{env-mlb2.yaml}}{lst:env-mlb2} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl -m env-mlb.tex -l env-mlb1.yaml +latexindent.pl -m env-mlb.tex -l env-mlb2.yaml +\end{commandshell} + the output is as in \cref{lst:env-mlb-mod1,lst:env-mlb-mod2} respectively. + + \begin{widepage} + \begin{minipage}{.57\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod1.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb1}}{lst:env-mlb-mod1} + \end{minipage} + \hfill + \begin{minipage}{.42\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod2.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb2}}{lst:env-mlb-mod2} + \end{minipage} + \end{widepage} + + There are a couple of points to note: + \begin{itemize} + \item in \cref{lst:env-mlb-mod1} a line break has been added at the point denoted by $\BeginStartsOnOwnLine$ in \cref{lst:env-mlb1-tex}; no + other line breaks have been changed; + \item in \cref{lst:env-mlb-mod2} a line break has been added at the point denoted by $\BodyStartsOnOwnLine$ in \cref{lst:env-mlb1-tex}; + furthermore, note that the \emph{body} of \texttt{myenv} has received the appropriate (default) indentation. + \end{itemize} + + Let's now change each of the \texttt{1} values in \cref{lst:env-mlb1,lst:env-mlb2} so that they are $2$ and + save them into \texttt{env-mlb3.yaml} and \texttt{env-mlb4.yaml} respectively (see \cref{lst:env-mlb3,lst:env-mlb4}). + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb3.yaml}[MLB-TCB]{\texttt{env-mlb3.yaml}}{lst:env-mlb3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb4.yaml}[MLB-TCB]{\texttt{env-mlb4.yaml}}{lst:env-mlb4} + \end{minipage} + + Upon running commands analogous to the above, we obtain \cref{lst:env-mlb-mod3,lst:env-mlb-mod4}. + + \begin{widepage} + \begin{minipage}{.57\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod3.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb3}}{lst:env-mlb-mod3} + \end{minipage} + \hfill + \begin{minipage}{.42\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod4.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb4}}{lst:env-mlb-mod4} + \end{minipage} + \end{widepage} + + Note that line breaks have been added as in \cref{lst:env-mlb-mod1,lst:env-mlb-mod2}, but this time a comment symbol + has been added before adding the line break; in both cases, trailing horizontal + space has been stripped before doing so. + + Let's explore \texttt{EndStartsOnOwnLine} and \texttt{EndFinishesWithLineBreak} in \cref{lst:env-mlb5,lst:env-mlb6}, + and in particular, let's allow each of them in turn to take a value of $1$. + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb5.yaml}[MLB-TCB]{\texttt{env-mlb5.yaml}}{lst:env-mlb5} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb6.yaml}[MLB-TCB]{\texttt{env-mlb6.yaml}}{lst:env-mlb6} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl -m env-mlb.tex -l env-mlb5.yaml +latexindent.pl -m env-mlb.tex -l env-mlb6.yaml +\end{commandshell} + the output is as in \cref{lst:env-mlb-mod5,lst:env-mlb-mod6}. + + \begin{widepage} + \begin{minipage}{.42\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod5.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb5}}{lst:env-mlb-mod5} + \end{minipage} + \hfill + \begin{minipage}{.57\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod6.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb6}}{lst:env-mlb-mod6} + \end{minipage} + \end{widepage} + + There are a couple of points to note: + \begin{itemize} + \item in \cref{lst:env-mlb-mod5} a line break has been added at the point denoted by $\EndStartsOnOwnLine$ in \vref{lst:env-mlb1-tex}; no + other line breaks have been changed and the \lstinline!\end{myenv}! statement has \emph{not} received indentation (as intended); + \item in \cref{lst:env-mlb-mod6} a line break has been added at the point denoted by $\EndFinishesWithLineBreak$ in \vref{lst:env-mlb1-tex}. + \end{itemize} + + Let's now change each of the \texttt{1} values in \cref{lst:env-mlb5,lst:env-mlb6} so that they are $2$ and + save them into \texttt{env-mlb7.yaml} and \texttt{env-mlb8.yaml} respectively (see \cref{lst:env-mlb7,lst:env-mlb8}). + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb7.yaml}[MLB-TCB]{\texttt{env-mlb7.yaml}}{lst:env-mlb7} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb8.yaml}[MLB-TCB]{\texttt{env-mlb8.yaml}}{lst:env-mlb8} + \end{minipage} + + Upon running commands analogous to the above, we obtain \cref{lst:env-mlb-mod7,lst:env-mlb-mod8}. + + \begin{widepage} + \begin{minipage}{.42\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod7.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb7}}{lst:env-mlb-mod7} + \end{minipage} + \hfill + \begin{minipage}{.57\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb-mod8.tex}{\texttt{env-mlb.tex} using \cref{lst:env-mlb8}}{lst:env-mlb-mod8} + \end{minipage} + \end{widepage} + + Note that line breaks have been added as in \cref{lst:env-mlb-mod5,lst:env-mlb-mod6}, but this time a comment symbol + has been added before adding the line break; in both cases, trailing horizontal + space has been stripped before doing so. + + If you ask \texttt{latexindent.pl} to add a line break (possibly with a comment) using a poly-switch value of $1$ (or $2$), + it will only do so if necessary. For example, if you process the file in \vref{lst:mlb2} using any of the YAML + files presented so far in this section, it will be left unchanged. + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb2.tex}{\texttt{env-mlb2.tex}}{lst:mlb2} + \end{minipage} + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb3.tex}{\texttt{env-mlb3.tex}}{lst:mlb3} + \end{minipage} + + In contrast, the output from processing the file in \cref{lst:mlb3} will vary depending + on the poly-switches used; in \cref{lst:env-mlb3-mod2} you'll see that the comment symbol after + the \lstinline!\begin{myenv}! has been moved to the next line, as \texttt{BodyStartsOnOwnLine} + is set to \texttt{1}. In \cref{lst:env-mlb3-mod4} you'll see that the comment has been accounted + for correctly because \texttt{BodyStartsOnOwnLine} has been set to \texttt{2}, + and the comment symbol has \emph{not} been moved to its own line. You're encouraged to experiment + with \cref{lst:mlb3} and by setting the other poly-switches considered so far to \texttt{2} in turn. + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb3-mod2.tex}{\texttt{env-mlb3.tex} using \vref{lst:env-mlb2}}{lst:env-mlb3-mod2} + \end{minipage} + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb3-mod4.tex}{\texttt{env-mlb3.tex} using \vref{lst:env-mlb4}}{lst:env-mlb3-mod4} + \end{minipage} + + The details of the discussion in this section have concerned \emph{global} poly-switches in the \texttt{environments} field; + each switch can also be specified on a \emph{per-name} basis, which would take priority over the global values; with + reference to \vref{lst:environments-mlb}, an example is shown for the \texttt{equation*} environment. + +\subsubsection{Removing line breaks (poly-switches set to $-1$)} + Setting poly-switches to $-1$ tells \texttt{latexindent.pl} to remove line breaks of the \emph{}, if necessary. We will consider the + example code given in \cref{lst:mlb4}, noting in particular the positions of + the line break highlighters, $\BeginStartsOnOwnLine$, $\BodyStartsOnOwnLine$, $\EndStartsOnOwnLine$ + and $\EndFinishesWithLineBreak$, together with the associated YAML files in \crefrange{lst:env-mlb9}{lst:env-mlb12}. + + \begin{minipage}{.45\linewidth} + \begin{cmhlistings}[escapeinside={(*@}{@*)}]{\texttt{env-mlb4.tex}}{lst:mlb4} +before words(*@$\BeginStartsOnOwnLine$@*) +\begin{myenv}(*@$\BodyStartsOnOwnLine$@*) +body of myenv(*@$\EndStartsOnOwnLine$@*) +\end{myenv}(*@$\EndFinishesWithLineBreak$@*) +after words +\end{cmhlistings} + \end{minipage}% + \hfill + \begin{minipage}{.51\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb9.yaml}[MLB-TCB]{\texttt{env-mlb9.yaml}}{lst:env-mlb9} + + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb10.yaml}[MLB-TCB]{\texttt{env-mlb10.yaml}}{lst:env-mlb10} + + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb11.yaml}[MLB-TCB]{\texttt{env-mlb11.yaml}}{lst:env-mlb11} + + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/env-mlb12.yaml}[MLB-TCB]{\texttt{env-mlb12.yaml}}{lst:env-mlb12} + \end{minipage} + + After running the commands + \begin{commandshell} +latexindent.pl -m env-mlb4.tex -l env-mlb9.yaml +latexindent.pl -m env-mlb4.tex -l env-mlb10.yaml +latexindent.pl -m env-mlb4.tex -l env-mlb11.yaml +latexindent.pl -m env-mlb4.tex -l env-mlb12.yaml +\end{commandshell} + + we obtain the respective output in \crefrange{lst:env-mlb4-mod9}{lst:env-mlb4-mod12}. + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb4-mod9.tex}{\texttt{env-mlb4.tex} using \cref{lst:env-mlb9}}{lst:env-mlb4-mod9} + \end{minipage} + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb4-mod10.tex}{\texttt{env-mlb4.tex} using \cref{lst:env-mlb10}}{lst:env-mlb4-mod10} + \end{minipage} + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb4-mod11.tex}{\texttt{env-mlb4.tex} using \cref{lst:env-mlb11}}{lst:env-mlb4-mod11} + \end{minipage} + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb4-mod12.tex}{\texttt{env-mlb4.tex} using \cref{lst:env-mlb12}}{lst:env-mlb4-mod12} + \end{minipage} + + Notice that in + \begin{itemize} + \item \cref{lst:env-mlb4-mod9} the line break denoted by $\BeginStartsOnOwnLine$ in \cref{lst:mlb4} has been removed; + \item \cref{lst:env-mlb4-mod10} the line break denoted by $\BodyStartsOnOwnLine$ in \cref{lst:mlb4} has been removed; + \item \cref{lst:env-mlb4-mod11} the line break denoted by $\EndStartsOnOwnLine$ in \cref{lst:mlb4} has been removed; + \item \cref{lst:env-mlb4-mod12} the line break denoted by $\EndFinishesWithLineBreak$ in \cref{lst:mlb4} has been removed. + \end{itemize} + We examined each of these cases separately for clarity of explanation, but you can combine all of the YAML + settings in \crefrange{lst:env-mlb9}{lst:env-mlb12} into one file; alternatively, you could tell \texttt{latexindent.pl} + to load them all by using the following command, for example + \begin{widepage} + \begin{commandshell} +latexindent.pl -m env-mlb4.tex -l env-mlb9.yaml,env-mlb10.yaml,env-mlb11.yaml,env-mlb12.yaml +\end{commandshell} + \end{widepage} + which gives the output in \vref{lst:env-mlb1-tex}. + + \paragraph{About trailing horizontal space} + Recall that on \cpageref{yaml:removeTrailingWhitespace} we discussed the YAML field \texttt{removeTrailingWhitespace}, + and that it has two (binary) switches to determine if horizontal space should be removed \texttt{beforeProcessing} and \texttt{afterProcessing}. + The \texttt{beforeProcessing} is particularly relevant when considering the \texttt{-m} switch; let's consider the + file shown in \cref{lst:mlb5}, which highlights trailing spaces. + + \begin{minipage}{.45\linewidth} + \begin{cmhlistings}[showspaces=true,escapeinside={(*@}{@*)}]{\texttt{env-mlb5.tex}}{lst:mlb5} +before words (*@$\BeginStartsOnOwnLine$@*) +\begin{myenv} (*@$\BodyStartsOnOwnLine$@*) +body of myenv (*@$\EndStartsOnOwnLine$@*) +\end{myenv} (*@$\EndFinishesWithLineBreak$@*) +after words +\end{cmhlistings} + \end{minipage} + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/removeTWS-before.yaml}[yaml-TCB]{\texttt{removeTWS-before.yaml}}{lst:removeTWS-before} + \end{minipage} + + The output from the following commands + \begin{widepage} + \begin{commandshell} +latexindent.pl -m env-mlb5.tex -l env-mlb9.yaml,env-mlb10.yaml,env-mlb11.yaml,env-mlb12.yaml +latexindent.pl -m env-mlb5.tex -l env-mlb9.yaml,env-mlb10.yaml,env-mlb11.yaml,env-mlb12.yaml,removeTWS-before.yaml +\end{commandshell} + \end{widepage} + is shown, respectively, in \cref{lst:env-mlb5-modAll,lst:env-mlb5-modAll-remove-WS}; note that + the trailing horizontal white space has been preserved (by default) in \cref{lst:env-mlb5-modAll}, while + in \cref{lst:env-mlb5-modAll-remove-WS}, it has been removed using the switch specified in \cref{lst:removeTWS-before}. + + \begin{widepage} + \cmhlistingsfromfile{demonstrations/env-mlb5-modAll.tex}{\texttt{env-mlb5.tex} using \crefrange{lst:env-mlb4-mod9}{lst:env-mlb4-mod12}}{lst:env-mlb5-modAll} + + \cmhlistingsfromfile{demonstrations/env-mlb5-modAll-remove-WS.tex}{\texttt{env-mlb5.tex} using \crefrange{lst:env-mlb4-mod9}{lst:env-mlb4-mod12} \emph{and} \cref{lst:removeTWS-before}}{lst:env-mlb5-modAll-remove-WS} + \end{widepage} + + + \paragraph{Blank lines} + Now let's consider the file in \cref{lst:mlb6}, which contains blank lines. + + \begin{minipage}{.45\linewidth} + \begin{cmhlistings}[escapeinside={(*@}{@*)}]{\texttt{env-mlb6.tex}}{lst:mlb6} +before words(*@$\BeginStartsOnOwnLine$@*) + + +\begin{myenv}(*@$\BodyStartsOnOwnLine$@*) + + +body of myenv(*@$\EndStartsOnOwnLine$@*) + + +\end{myenv}(*@$\EndFinishesWithLineBreak$@*) + +after words +\end{cmhlistings} + \end{minipage}% + \hfill + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/UnpreserveBlankLines.yaml}[MLB-TCB]{\texttt{UnpreserveBlankLines.yaml}}{lst:UnpreserveBlankLines} + \end{minipage} + + Upon running the following commands + \begin{widepage} + \begin{commandshell} +latexindent.pl -m env-mlb6.tex -l env-mlb9.yaml,env-mlb10.yaml,env-mlb11.yaml,env-mlb12.yaml +latexindent.pl -m env-mlb6.tex -l env-mlb9.yaml,env-mlb10.yaml,env-mlb11.yaml,env-mlb12.yaml,UnpreserveBlankLines.yaml +\end{commandshell} + \end{widepage} + we receive the respective outputs in \cref{lst:env-mlb6-modAll,lst:env-mlb6-modAll-un-Preserve-Blank-Lines}. In + \cref{lst:env-mlb6-modAll} we see that the multiple blank lines have each been condensed into one blank line, + but that blank lines have \emph{not} been removed by the poly-switches -- this is because, by default, \texttt{preserveBlankLines} + is set to \texttt{1}. By contrast, in \cref{lst:env-mlb6-modAll-un-Preserve-Blank-Lines}, we have allowed + the poly-switches to remove blank lines because, in \cref{lst:UnpreserveBlankLines}, we have set \texttt{preserveBlankLines} to \texttt{0}. + + \begin{widepage} + \begin{minipage}{.30\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb6-modAll.tex}{\texttt{env-mlb6.tex} using \crefrange{lst:env-mlb4-mod9}{lst:env-mlb4-mod12}}{lst:env-mlb6-modAll} + \end{minipage} + \hfill + \begin{minipage}{.65\linewidth} + \cmhlistingsfromfile{demonstrations/env-mlb6-modAll-un-Preserve-Blank-Lines.tex}{\texttt{env-mlb6.tex} using \crefrange{lst:env-mlb4-mod9}{lst:env-mlb4-mod12} \emph{and} \cref{lst:UnpreserveBlankLines}}{lst:env-mlb6-modAll-un-Preserve-Blank-Lines} + \end{minipage} + \end{widepage} + +\subsection{Poly-switches for other code blocks} + Rather than repeat the examples shown for the environment code blocks (in \vref{sec:modifylinebreaks-environments}), we choose to detail the poly-switches for + all other code blocks in \cref{tab:poly-switch-mapping}; note that each and every one of these poly-switches is \emph{off by default}, i.e, set to \texttt{0}. Note also that, + by design, line breaks involving \texttt{verbatim}, \texttt{filecontents} and `comment-marked' code blocks (\vref{lst:alignmentmarkup}) can \emph{not} be + modified using \texttt{latexindent.pl}. + + \begin{longtable}{m{.2\textwidth}@{\hspace{.75cm}}m{.35\textwidth}@{}m{.4\textwidth}} + \caption{Poly-switch mappings for all code-block types}\label{tab:poly-switch-mapping}\\ + \toprule + Code block & Sample & Poly-switch mapping \\ + \midrule + environment & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +before words(*@$\BeginStartsOnOwnLine$@*) +\begin{myenv}(*@$\BodyStartsOnOwnLine$@*) +body of myenv(*@$\EndStartsOnOwnLine$@*) +\end{myenv}(*@$\EndFinishesWithLineBreak$@*) +after words + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & BeginStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & BodyStartsOnOwnLine \\ + $\EndStartsOnOwnLine$ & EndStartsOnOwnLine \\ + $\EndFinishesWithLineBreak$ & EndFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + ifelsefi & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +before words(*@$\BeginStartsOnOwnLine$@*) +\if...(*@$\BodyStartsOnOwnLine$@*) +body of if statement(*@$\ElseStartsOnOwnLine$@*) +\else(*@$\ElseFinishesWithLineBreak$@*) +body of else statement(*@$\EndStartsOnOwnLine$@*) +\fi(*@$\EndFinishesWithLineBreak$@*) +after words + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & IfStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & BodyStartsOnOwnLine \\ + $\ElseStartsOnOwnLine$ & ElseStartsOnOwnLine \\ + $\ElseFinishesWithLineBreak$ & ElseFinishesWithLineBreak \\ + $\EndStartsOnOwnLine$ & FiStartsOnOwnLine \\ + $\EndFinishesWithLineBreak$ & FiFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + optionalArguments & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +...(*@$\BeginStartsOnOwnLine$@*) +[(*@$\BodyStartsOnOwnLine$@*) +body of opt arg(*@$\EndStartsOnOwnLine$@*) +](*@$\EndFinishesWithLineBreak$@*) +... + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & LSqBStartsOnOwnLine\footnote{LSqB stands for Left Square Bracket} \\ + $\BodyStartsOnOwnLine$ & OptArgBodyStartsOnOwnLine \\ + $\EndStartsOnOwnLine$ & RSqBStartsOnOwnLine \\ + $\EndFinishesWithLineBreak$ & RSqBFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + mandatoryArguments & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +...(*@$\BeginStartsOnOwnLine$@*) +{(*@$\BodyStartsOnOwnLine$@*) +body of mand arg(*@$\EndStartsOnOwnLine$@*) +}(*@$\EndFinishesWithLineBreak$@*) +... + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & LCuBStartsOnOwnLine\footnote{LCuB stands for Left Curly Brace} \\ + $\BodyStartsOnOwnLine$ & MandArgBodyStartsOnOwnLine \\ + $\EndStartsOnOwnLine$ & RCuBStartsOnOwnLine \\ + $\EndFinishesWithLineBreak$ & RCuBFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + commands & + \begin{lstlisting}[escapeinside={(*@}{@*)},morekeywords={mycommand},nolol=true,] +before words(*@$\BeginStartsOnOwnLine$@*) +\mycommand(*@$\BodyStartsOnOwnLine$@*) +(*@$\langle$\itshape{arguments}$\rangle$@*) + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & CommandStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & CommandNameFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + namedGroupingBraces Brackets & + \begin{lstlisting}[escapeinside={(*@}{@*)},morekeywords={myname},nolol=true,] +before words(*@$\BeginStartsOnOwnLine$@*) +myname(*@$\BodyStartsOnOwnLine$@*) +(*@$\langle$\itshape{braces/brackets}$\rangle$@*) + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & NameStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & NameFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + keyEqualsValuesBraces\newline Brackets & + \begin{lstlisting}[escapeinside={(*@}{@*)},morekeywords={key},nolol=true,] +before words(*@$\BeginStartsOnOwnLine$@*) +key(*@$\EqualsStartsOnOwnLine$@*)=(*@$\BodyStartsOnOwnLine$@*) +(*@$\langle$\itshape{braces/brackets}$\rangle$@*) + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & KeyStartsOnOwnLine \\ + $\EqualsStartsOnOwnLine$ & EqualsStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & EqualsFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + items & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +before words(*@$\BeginStartsOnOwnLine$@*) +\item(*@$\BodyStartsOnOwnLine$@*) +... + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & ItemStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & ItemFinishesWithLineBreak \\ + \end{tabular} + \\ + \cmidrule{2-3} + specialBeginEnd & + \begin{lstlisting}[escapeinside={(*@}{@*)},nolol=true] +before words(*@$\BeginStartsOnOwnLine$@*) +\[(*@$\BodyStartsOnOwnLine$@*) +body of special(*@$\EndStartsOnOwnLine$@*) +\](*@$\EndFinishesWithLineBreak$@*) +after words + \end{lstlisting} + & + \begin{tabular}[t]{c@{~}l@{}} + $\BeginStartsOnOwnLine$ & SpecialBeginStartsOnOwnLine \\ + $\BodyStartsOnOwnLine$ & SpecialBodyStartsOnOwnLine \\ + $\EndStartsOnOwnLine$ & SpecialEndStartsOnOwnLine \\ + $\EndFinishesWithLineBreak$ & SpecialEndFinishesWithLineBreak \\ + \end{tabular} + \\ + \bottomrule + \end{longtable} diff --git a/Master/texmf-dist/doc/support/latexindent/subsec-commands-and-their-options.tex b/Master/texmf-dist/doc/support/latexindent/subsec-commands-and-their-options.tex new file mode 100644 index 00000000000..8ef571bc574 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsec-commands-and-their-options.tex @@ -0,0 +1,139 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsection{Commands and the strings between their arguments}\label{subsec:commands-string-between} + The \texttt{command} code blocks will always look for optional (square bracketed) and + mandatory (curly braced) arguments which can contain comments, line breaks and + `beamer' commands \lstinline!<.*?>! between them. There are switches that can allow them to contain + other strings, which we discuss next. + +\yamltitle{commandCodeBlocks}*{fields} + + The \texttt{commandCodeBlocks} field contains a few switches detailed in \cref{lst:commandCodeBlocks}. + + \cmhlistingsfromfile[firstnumber=278,linerange={278-286},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{commandCodeBlocks}}{lst:commandCodeBlocks} + +\yamltitle{roundParenthesesAllowed}{0|1} + + The need for this field was mostly motivated by commands found in code used to generate images in \texttt{PSTricks} and \texttt{tikz}; for example, + let's consider the code given in \cref{lst:pstricks1}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/pstricks1.tex}{\texttt{pstricks1.tex}}{lst:pstricks1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/pstricks1-default.tex}{\texttt{pstricks1} default output}{lst:pstricks1-default} + \end{minipage} + + Notice that the \lstinline!\defFunction! command has an optional argument, followed by a + mandatory argument, followed by a round-parenthesis argument, $(u,v)$. + + By default, because \texttt{roundParenthesesAllowed} is set to $1$ in \cref{lst:commandCodeBlocks}, then \texttt{latexindent.pl} + will allow round parenthesis between optional and mandatory arguments. In the case of the code in \cref{lst:pstricks1}, + \texttt{latexindent.pl} finds \emph{all} the arguments of \lstinline!defFunction!, both before and after \lstinline!(u,v)!. + + The default output from running \texttt{latexindent.pl} on \cref{lst:pstricks1} actually leaves it unchanged (see \cref{lst:pstricks1-default}); + note in particular, this is because of \texttt{noAdditionalIndentGlobal} as discussed on \cpageref{page:command:noAddGlobal}. + + Upon using the YAML settings in \cref{lst:noRoundParentheses}, and running the command + \begin{commandshell} +latexindent.pl pstricks1.tex -l noRoundParentheses.yaml + \end{commandshell} + we obtain the output given in \cref{lst:pstricks1-nrp}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/pstricks1-nrp.tex}{\texttt{pstricks1.tex} using \cref{lst:noRoundParentheses}}{lst:pstricks1-nrp} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/noRoundParentheses.yaml}[yaml-TCB]{\texttt{noRoundParentheses.yaml}}{lst:noRoundParentheses} + \end{minipage} + + Notice the difference between \cref{lst:pstricks1-default} and \cref{lst:pstricks1-nrp}; in particular, in \cref{lst:pstricks1-nrp}, because + round parentheses are \emph{not} allowed, \texttt{latexindent.pl} finds that the \lstinline!\defFunction! command finishes at the first opening + round parenthesis. As such, the remaining braced, mandatory, arguments are found to be \texttt{UnNamedGroupingBracesBrackets} (see \vref{tab:code-blocks}) + which, by default, assume indentation for their body, and hence the tabbed indentation in \cref{lst:pstricks1-nrp}. + + Let's explore this using the YAML given in \cref{lst:defFunction} and run the command + \begin{commandshell} +latexindent.pl pstricks1.tex -l defFunction.yaml + \end{commandshell} + then the output is as in \cref{lst:pstricks1-indent-rules}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/pstricks1-indent-rules.tex}{\texttt{pstricks1.tex} using \cref{lst:defFunction}}{lst:pstricks1-indent-rules} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/defFunction.yaml}[yaml-TCB]{\texttt{defFunction.yaml}}{lst:defFunction} + \end{minipage} + + Notice in \cref{lst:pstricks1-indent-rules} that the \emph{body} of the \lstinline!defFunction! command i.e, the subsequent lines + containing arguments after the command name, have received the single space of indentation specified by \cref{lst:defFunction}. + +\yamltitle{stringsAllowedBetweenArguments}*{fields} + \texttt{tikz} users may well specify code such as that given in \cref{lst:tikz-node1}; processing this code using + \texttt{latexindent.pl} gives the default output in \cref{lst:tikz-node1-default}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tikz-node1.tex}{\texttt{tikz-node1.tex}}{lst:tikz-node1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[columns=fixed]{demonstrations/tikz-node1-default.tex}{\texttt{tikz-node1} default output}{lst:tikz-node1-default} + \end{minipage} + + With reference to \vref{lst:commandCodeBlocks}, we see that the strings + \begin{quote} + to, node, ++ + \end{quote} + are all allowed to appear between arguments, as they are each set to $1$; importantly, you are encouraged to add further names + to this field as necessary. This means that when \texttt{latexindent.pl} + processes \cref{lst:tikz-node1}, it consumes: + \begin{itemize} + \item the optional argument \lstinline![thin]! + \item the round-bracketed argument \lstinline!(c)! because \texttt{roundParenthesesAllowed} is $1$ by default + \item the string \lstinline!to! (specified in \texttt{stringsAllowedBetweenArguments}) + \item the optional argument \lstinline![in=110,out=-90]! + \item the string \lstinline!++! (specified in \texttt{stringsAllowedBetweenArguments}) + \item the round-bracketed argument \lstinline!(0,-0.5cm)! because \texttt{roundParenthesesAllowed} is $1$ by default + \item the string \lstinline!node! (specified in \texttt{stringsAllowedBetweenArguments}) + \item the optional argument \lstinline![below,align=left,scale=0.5]! + \end{itemize} + + We can explore this further, for example using \cref{lst:draw} and running the command + \begin{commandshell} +latexindent.pl tikz-node1.tex -l draw.yaml +\end{commandshell} + we receive the output given in \cref{lst:tikz-node1-draw}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/tikz-node1-draw.tex}{\texttt{tikz-node1.tex} using \cref{lst:draw}}{lst:tikz-node1-draw} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/draw.yaml}[yaml-TCB]{\texttt{draw.yaml}}{lst:draw} + \end{minipage} + + Notice that each line after the \lstinline!\draw! command (its `body') in \cref{lst:tikz-node1-draw} has been given the + appropriate two-spaces worth of indentation specified in \cref{lst:draw}. + + Let's compare this with the output from using the YAML settings in \cref{lst:no-to}, and running the command + \begin{commandshell} +latexindent.pl tikz-node1.tex -l no-to.yaml +\end{commandshell} + given in \cref{lst:tikz-node1-no-to}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/tikz-node1-no-to.tex}{\texttt{tikz-node1.tex} using \cref{lst:no-to}}{lst:tikz-node1-no-to} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/no-to.yaml}[yaml-TCB]{\texttt{no-to.yaml}}{lst:no-to} + \end{minipage} + + In this case, \texttt{latexindent.pl} sees that: + \begin{itemize} + \item the \lstinline!\draw! command finishes after the \lstinline!(c)! as (\texttt{stringsAllowedBetweenArguments} has \texttt{to} set to $0$) + \item it finds a \texttt{namedGroupingBracesBrackets} called \texttt{to} (see \vref{tab:code-blocks}) \emph{with} argument \lstinline![in=110,out=-90]! + \item it finds another \texttt{namedGroupingBracesBrackets} but this time called \texttt{node} with argument \lstinline![below,align=left,scale=0.5]! + \end{itemize} diff --git a/Master/texmf-dist/doc/support/latexindent/subsec-conflicting-poly-switches.tex b/Master/texmf-dist/doc/support/latexindent/subsec-conflicting-poly-switches.tex new file mode 100644 index 00000000000..61216c96c7c --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsec-conflicting-poly-switches.tex @@ -0,0 +1,137 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsection{Conflicting poly-switches: sequential code blocks} + It is very easy to have conflicting poly-switches; if we use the example from \vref{lst:mycommand1}, + and consider the YAML settings given in \cref{lst:mycom-mlb4}. The output from running + \begin{commandshell} +latexindent.pl -m -l=mycom-mlb4.yaml mycommand1.tex +\end{commandshell} + is given in \cref{lst:mycom-mlb4}. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb4.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb4}}{lst:mycommand1-mlb4} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb4.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb4.yaml}}{lst:mycom-mlb4} + \end{minipage} + + Studying \cref{lst:mycom-mlb4}, we see that the two poly-switches are at opposition with one another: + \begin{itemize} + \item on the one hand, \texttt{LCuBStartsOnOwnLine} should \emph{not} start on its own line (as poly-switch is set to $-1$); + \item on the other hand, \texttt{RCuBFinishesWithLineBreak} \emph{should} finish with a line break. + \end{itemize} + So, which should win the conflict? As demonstrated in \cref{lst:mycommand1-mlb4}, it is clear that \texttt{LCuBStartsOnOwnLine} won + this conflict, and the reason is that \emph{the second argument was processed after the first} -- in general, the most recently-processed + code block and associated poly-switch takes priority. + + We can explore this further by considering the YAML settings in \cref{lst:mycom-mlb5}; upon running the command + \begin{commandshell} +latexindent.pl -m -l=mycom-mlb5.yaml mycommand1.tex +\end{commandshell} + we obtain the output given in \cref{lst:mycommand1-mlb5}. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb5.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb5}}{lst:mycommand1-mlb5} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb5.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb5.yaml}}{lst:mycom-mlb5} + \end{minipage} + + As previously, the most-recently-processed code block takes priority -- as before, the second (i.e, \emph{last}) argument. Exploring this + further, we consider the YAML settings in \cref{lst:mycom-mlb6}, which give associated output in \cref{lst:mycommand1-mlb6}. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb6.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb6}}{lst:mycommand1-mlb6} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb6.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb6.yaml}}{lst:mycom-mlb6} + \end{minipage} + + Note that a \lstinline!%! \emph{has} been added to the trailing first \lstinline!}!; this is because: + \begin{itemize} + \item while processing the \emph{first} argument, the trailing line break has been removed (\texttt{RCuBFinishesWithLineBreak} set to $-1$); + \item while processing the \emph{second} argument, \texttt{latexindent.pl} finds that it does \emph{not} begin on its own line, and so + because \texttt{LCuBStartsOnOwnLine} is set to $2$, it adds a comment, followed by a line break. + \end{itemize} + +\subsection{Conflicting poly-switches: nested code blocks} + Now let's consider an example when nested code blocks have conflicting poly-switches; we'll use the code in \cref{lst:nested-env}, + noting that it contains nested environments. + + \cmhlistingsfromfile{demonstrations/nested-env.tex}{\texttt{nested-env.tex}}{lst:nested-env} + + Let's use the YAML settings given in \cref{lst:nested-env-mlb1-yaml}, which upon running the command + \begin{commandshell} +latexindent.pl -m -l=nested-env-mlb1.yaml nested-env.tex + \end{commandshell} + gives the output in \cref{lst:nested-env-mlb1}. + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/nested-env-mlb1.tex}{\texttt{nested-env.tex} using \cref{lst:nested-env-mlb1}}{lst:nested-env-mlb1} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/nested-env-mlb1.yaml}[MLB-TCB,width=\linewidth]{\texttt{nested-env-mlb1.yaml}}{lst:nested-env-mlb1-yaml} + \end{minipage} + + In \cref{lst:nested-env-mlb1}, let's first of all note that both environments have received the appropriate (default) indentation; secondly, + note that the poly-switch \texttt{EndStartsOnOwnLine} appears to have won the conflict, as \lstinline!\end{one}! has had its leading line break removed. + + To understand it, let's talk about the three basic phases of \texttt{latexindent.pl}: + \begin{enumerate} + \item Phase 1: packing, in which code blocks are replaced with unique ids, working from \emph{the inside to the outside}, and then sequentially -- for example, in + \cref{lst:nested-env}, the \texttt{two} environment is found \emph{before} the \texttt{one} environment; if the -m switch is active, then during this phase: + \begin{itemize} + \item line breaks at the beginning of the \texttt{body} can be added (if \texttt{BodyStartsOnOwnLine} is $1$ or $2$) or removed (if \texttt{BodyStartsOnOwnLine} is $-1$); + \item line breaks at the end of the body can be added (if \texttt{EndStartsOnOwnLine} is $1$ or $2$) or removed (if \texttt{EndStartsOnOwnLine} is $-1$); + \item line breaks after the end statement can be added (if \texttt{EndFinishesWithLineBreak} is $1$ or $2$). + \end{itemize} + \item Phase 2: indentation, in which white space is added to the begin, body, and end statements; + \item Phase 3: unpacking, in which unique ids are replaced by their \emph{indented} code blocks; if the -m switch is active, then during this phase, + \begin{itemize} + \item line breaks before \texttt{begin} statements can be added or removed (depending upon \texttt{BeginStartsOnOwnLine}); + \item line breaks after \emph{end} statements can be removed but \emph{NOT} added (see \texttt{EndFinishesWithLineBreak}). + \end{itemize} + \end{enumerate} + + With reference to \cref{lst:nested-env-mlb1}, this means that during Phase 1: + \begin{itemize} + \item the \texttt{two} environment is found first, and + the line break ahead of the \lstinline!\end{two}! statement is removed because \texttt{EndStartsOnOwnLine} is set to $-1$. Importantly, + because, \emph{at this stage}, \lstinline!\end{two}! \emph{does} finish with a line break, \texttt{EndFinishesWithLineBreak} causes + no action. + \item next, the \texttt{one} environment is found; the line break ahead of \lstinline!\end{one}! is removed because \texttt{EndStartsOnOwnLine} + is set to $-1$. + \end{itemize} + The indentation is done in Phase 2, and then in Phase 3, \emph{there is no option to add a line break after the \lstinline!end! statements}. + We can justify this by remembering that during Phase 3, the \texttt{one} environment will be found and processed first, followed + by the \texttt{two} environment. If the \texttt{two} environment were to add a line break after the \lstinline!\end{two}! statement, then + \texttt{latexindent.pl} would have no way of knowing how much indentation to add to the subsequent text (in this case, \lstinline!\end{one}!). + + We can explore this further using the poly-switches in \cref{lst:nested-env-mlb2}; upon running the command + \begin{commandshell} +latexindent.pl -m -l=nested-env-mlb2.yaml nested-env.tex + \end{commandshell} + we obtain the output given in \cref{lst:nested-env-mlb2-output}. + + \begin{minipage}{.45\linewidth} + \cmhlistingsfromfile{demonstrations/nested-env-mlb2.tex}{\texttt{nested-env.tex} using \cref{lst:nested-env-mlb2}}{lst:nested-env-mlb2-output} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/nested-env-mlb2.yaml}[MLB-TCB,width=\linewidth]{\texttt{nested-env-mlb2.yaml}}{lst:nested-env-mlb2} + \end{minipage} + + During Phase 1: + \begin{itemize} + \item the \texttt{two} environment is found first, and + the line break ahead of the \lstinline!\end{two}! statement is not changed because \texttt{EndStartsOnOwnLine} is set to $1$. + Importantly, because, \emph{at this stage}, \lstinline!\end{two}! \emph{does} finish with a line break, \texttt{EndFinishesWithLineBreak} causes + no action. + \item next, the \texttt{one} environment is found; the line break ahead of \lstinline!\end{one}! is already present, and no action is needed. + \end{itemize} + The indentation is done in Phase 2, and then in Phase 3, the \texttt{one} environment is found and processed first, followed by + the \texttt{two} environment. \emph{At this stage}, the \texttt{two} environment finds \texttt{EndFinishesWithLineBreak} is $-1$, so it removes + the trailing line break; remember, at this point, \texttt{latexindent.pl} has completely finished with the \texttt{one} environment. diff --git a/Master/texmf-dist/doc/support/latexindent/subsec-noAdditionalIndent-indentRules.tex b/Master/texmf-dist/doc/support/latexindent/subsec-noAdditionalIndent-indentRules.tex new file mode 100644 index 00000000000..e0a20542877 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsec-noAdditionalIndent-indentRules.tex @@ -0,0 +1,24 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsection{\texttt{noAdditionalIndent} and \texttt{indentRules}}\label{sec:noadd-indent-rules} + \texttt{latexindent.pl} operates on files by looking for code blocks, as detailed in \vref{subsubsec:code-blocks}; + for each type of code block in \vref{tab:code-blocks} (which we will call a \emph{$\langle$thing$\rangle$} in what follows) + it searches YAML fields for information in the following order: + \begin{enumerate} + \item \texttt{noAdditionalIndent} for the \emph{name} of the current \emph{$\langle$thing$\rangle$}; + \item \texttt{indentRules} for the \emph{name} of the current \emph{$\langle$thing$\rangle$}; + \item \texttt{noAdditionalIndentGlobal} for the \emph{type} of the current \emph{$\langle$thing$\rangle$}; + \item \texttt{indentRulesGlobal} for the \emph{type} of the current \emph{$\langle$thing$\rangle$}. + \end{enumerate} + + Using the above list, the first piece of information to be found will be used; failing that, + the value of \texttt{defaultIndent} is used. + If information is found in multiple fields, the first one according to the list above will be used; for example, + if information is present in both \texttt{indentRules} and in \texttt{noAdditionalIndentGlobal}, then the information from \texttt{indentRules} + takes priority. + + We now present details for the different type of code blocks known to \texttt{latexindent.pl}, as detailed in \vref{tab:code-blocks}; for + reference, there follows a list of the code blocks covered. + + \startcontents[noAdditionalIndent] + \printcontents[noAdditionalIndent]{}{0}{} diff --git a/Master/texmf-dist/doc/support/latexindent/subsec-partnering-poly-switches.tex b/Master/texmf-dist/doc/support/latexindent/subsec-partnering-poly-switches.tex new file mode 100644 index 00000000000..d906fe84e9e --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsec-partnering-poly-switches.tex @@ -0,0 +1,47 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsection{Partnering \texttt{BodyStartsOnOwnLine} with argument-based poly-switches} + Some poly-switches need to be partnered together; in particular, when line breaks involving the \emph{first} argument + of a code block need to be accounted for using both \texttt{BodyStartsOnOwnLine} (or its equivalent, see \vref{tab:poly-switch-mapping}) + and \texttt{LCuBStartsOnOwnLine} for mandatory arguments, and \texttt{LSqBStartsOnOwnLine} for optional arguments. + + Let's begin with the code in \cref{lst:mycommand1} and the YAML settings in \cref{lst:mycom-mlb1}; with reference + to \vref{tab:poly-switch-mapping}, the key \texttt{CommandNameFinishesWithLineBreak} is an alias for \texttt{BodyStartsOnOwnLine}. + + \cmhlistingsfromfile{demonstrations/mycommand1.tex}{\texttt{mycommand1.tex}}{lst:mycommand1} + + Upon running the command + \begin{commandshell} +latexindent.pl -m -l=mycom-mlb1.yaml mycommand1.tex +\end{commandshell} + we obtain \cref{lst:mycommand1-mlb1}; note that the \emph{second} mandatory argument beginning brace \lstinline!{! has had + its leading line break removed, but that the \emph{first} brace has not. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb1.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb1}}{lst:mycommand1-mlb1} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb1.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb1.yaml}}{lst:mycom-mlb1} + \end{minipage} + + Now let's change the YAML file so that it is as in \cref{lst:mycom-mlb2}; upon running the analogous command to that given above, + we obtain \cref{lst:mycommand1-mlb2}; both beginning braces \lstinline!{! have had their leading line breaks removed. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb2.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb2}}{lst:mycommand1-mlb2} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb2.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb2.yaml}}{lst:mycom-mlb2} + \end{minipage} + + Now let's change the YAML file so that it is as in \cref{lst:mycom-mlb3}; upon running the analogous command to that given above, + we obtain \cref{lst:mycommand1-mlb3}. + + \begin{minipage}{.4\linewidth} + \cmhlistingsfromfile{demonstrations/mycommand1-mlb3.tex}{\texttt{mycommand1.tex} using \cref{lst:mycom-mlb3}}{lst:mycommand1-mlb3} + \end{minipage} + \hfill + \begin{minipage}{.55\linewidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycom-mlb3.yaml}[MLB-TCB,width=\linewidth]{\texttt{mycom-mlb3.yaml}}{lst:mycom-mlb3} + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-commands-with-arguments.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-commands-with-arguments.tex new file mode 100644 index 00000000000..592e7fe4243 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-commands-with-arguments.tex @@ -0,0 +1,100 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{Commands with arguments}\label{subsubsec:commands-arguments} + Let's begin with the simple example in \cref{lst:mycommand}; when \texttt{latexindent.pl} operates + on this file, the default output is shown in \cref{lst:mycommand-default}. \footnote{The command code blocks + have quite a few subtleties, described in \vref{subsec:commands-string-between}.} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand.tex}{\texttt{mycommand.tex}}{lst:mycommand} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-default.tex}{\texttt{mycommand.tex} default output}{lst:mycommand-default} + \end{minipage} + + As in the environment-based case (see \vref{lst:myenv-noAdd1,lst:myenv-noAdd2}) we may specify \texttt{noAdditionalIndent} + either in `scalar' form, or in `field' form, as shown in \cref{lst:mycommand-noAdd1,lst:mycommand-noAdd2} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd1.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd1.yaml}}{lst:mycommand-noAdd1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd2.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd2.yaml}}{lst:mycommand-noAdd2} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl mycommand.tex -l mycommand-noAdd1.yaml +latexindent.pl mycommand.tex -l mycommand-noAdd2.yaml +\end{commandshell} + we receive the respective output given in \cref{lst:mycommand-output-noAdd1,lst:mycommand-output-noAdd2} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd1.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd1}}{lst:mycommand-output-noAdd1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd2.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd2}}{lst:mycommand-output-noAdd2} + \end{minipage} + + Note that in \cref{lst:mycommand-output-noAdd1} that the `body', optional argument \emph{and} mandatory argument have \emph{all} received + no additional indentation, while in \cref{lst:mycommand-output-noAdd2}, only the `body' has not received any additional indentation. We define + the `body' of a command as any lines following the command name that include its optional or mandatory arguments. + + We may further customise \texttt{noAdditionalIndent} for \texttt{mycommand} as we did in \vref{lst:myenv-noAdd5,lst:myenv-noAdd6}; explicit examples + are given in \cref{lst:mycommand-noAdd3,lst:mycommand-noAdd4}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd3.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd3.yaml}}{lst:mycommand-noAdd3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd4.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd4.yaml}}{lst:mycommand-noAdd4} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl mycommand.tex -l mycommand-noAdd3.yaml +latexindent.pl mycommand.tex -l mycommand-noAdd4.yaml +\end{commandshell} + we receive the respective output given in \cref{lst:mycommand-output-noAdd3,lst:mycommand-output-noAdd4}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd3.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd3}}{lst:mycommand-output-noAdd3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd4.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd4}}{lst:mycommand-output-noAdd4} + \end{minipage} + + Attentive readers will note that the body of \texttt{mycommand} in both \cref{lst:mycommand-output-noAdd3,lst:mycommand-output-noAdd4} + has received no additional indent, even though \texttt{body} is explicitly set to \texttt{0} in both \cref{lst:mycommand-noAdd3,lst:mycommand-noAdd4}. + This is because, by default, \texttt{noAdditionalIndentGlobal} for \texttt{commands} is set to \texttt{1} by default; this can be easily + fixed as in \cref{lst:mycommand-noAdd5,lst:mycommand-noAdd6}.\label{page:command:noAddGlobal} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd5.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd5.yaml}}{lst:mycommand-noAdd5} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mycommand-noAdd6.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{mycommand-noAdd6.yaml}}{lst:mycommand-noAdd6} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl mycommand.tex -l mycommand-noAdd5.yaml +latexindent.pl mycommand.tex -l mycommand-noAdd6.yaml +\end{commandshell} + we receive the respective output given in \cref{lst:mycommand-output-noAdd5,lst:mycommand-output-noAdd6}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd5.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd5}}{lst:mycommand-output-noAdd5} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/mycommand-noAdd6.tex}{\texttt{mycommand.tex} using \cref{lst:mycommand-noAdd6}}{lst:mycommand-output-noAdd6} + \end{minipage} + + Both \texttt{indentRules} and \texttt{indentRulesGlobal} can be adjusted as they were for \emph{environment} code blocks, as in + \vref{lst:myenv-rules3,lst:myenv-rules4} and \vref{lst:indentRulesGlobal:environments,lst:opt-args-indent-rules-glob,lst:mand-args-indent-rules-glob}. diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-and-their-arguments.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-and-their-arguments.tex new file mode 100644 index 00000000000..908c2607b78 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-and-their-arguments.tex @@ -0,0 +1,255 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{Environments and their arguments}\label{subsubsec:env-and-their-args} + There are a few different YAML switches governing the indentation of environments; let's start + with the code shown in \cref{lst:myenvtex}. + + \cmhlistingsfromfile{demonstrations/myenvironment-simple.tex}{\texttt{myenv.tex}}{lst:myenvtex} + +\yamltitle{noAdditionalIndent}*{fields} + If we do not wish \texttt{myenv} to receive any additional indentation, we have a few choices available to us, + as demonstrated in \cref{lst:myenv-noAdd1,lst:myenv-noAdd2}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd1.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd1.yaml}}{lst:myenv-noAdd1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd2.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd2.yaml}}{lst:myenv-noAdd2} + \end{minipage} + + On applying either of the following commands, + \begin{commandshell} +latexindent.pl myenv.tex -l myenv-noAdd1.yaml +latexindent.pl myenv.tex -l myenv-noAdd2.yaml +\end{commandshell} + we obtain the output given in \cref{lst:myenv-output}; note in particular that the environment \texttt{myenv} + has not received any \emph{additional} indentation, but that the \texttt{outer} environment \emph{has} still + received indentation. + + \cmhlistingsfromfile{demonstrations/myenvironment-simple-noAdd-body1.tex}{\texttt{myenv.tex output (using either \cref{lst:myenv-noAdd1} or \cref{lst:myenv-noAdd2})}}{lst:myenv-output} + + Upon changing the YAML files to those shown in \cref{lst:myenv-noAdd3,lst:myenv-noAdd4}, and running either + \begin{commandshell} +latexindent.pl myenv.tex -l myenv-noAdd3.yaml +latexindent.pl myenv.tex -l myenv-noAdd4.yaml +\end{commandshell} + we obtain the output given in \cref{lst:myenv-output-4}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd3.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd3.yaml}}{lst:myenv-noAdd3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd4.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd4.yaml}}{lst:myenv-noAdd4} + \end{minipage} + + \cmhlistingsfromfile{demonstrations/myenvironment-simple-noAdd-body4.tex}{\texttt{myenv.tex output} (using either \cref{lst:myenv-noAdd3} or \cref{lst:myenv-noAdd4})}{lst:myenv-output-4} + + Let's now allow \texttt{myenv} to have some optional and mandatory arguments, as in \cref{lst:myenv-args}. + \cmhlistingsfromfile{demonstrations/myenvironment-args.tex}{\texttt{myenv-args.tex}}{lst:myenv-args} + Upon running + \begin{commandshell} +latexindent.pl -l=myenv-noAdd1.yaml myenv-args.tex +\end{commandshell} + we obtain the output shown in \cref{lst:myenv-args-noAdd1}; note that the optional argument, mandatory argument and body \emph{all} + have received no additional indent. This is because, when \texttt{noAdditionalIndent} is specified in `scalar' form (as in \cref{lst:myenv-noAdd1}), + then \emph{all} parts of the environment (body, optional and mandatory arguments) are assumed to want no additional indent. + \cmhlistingsfromfile{demonstrations/myenvironment-args-noAdd-body1.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-noAdd1}}{lst:myenv-args-noAdd1} + + We may customise \texttt{noAdditionalIndent} for optional and mandatory arguments of the \texttt{myenv} environment, as shown in, for example, \cref{lst:myenv-noAdd5,lst:myenv-noAdd6}. + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd5.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd5.yaml}}{lst:myenv-noAdd5} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-noAdd6.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-noAdd6.yaml}}{lst:myenv-noAdd6} + \end{minipage} + + Upon running + \begin{commandshell} +latexindent.pl myenv.tex -l myenv-noAdd5.yaml +latexindent.pl myenv.tex -l myenv-noAdd6.yaml +\end{commandshell} + we obtain the respective outputs given in \cref{lst:myenv-args-noAdd5,lst:myenv-args-noAdd6}. Note that in \cref{lst:myenv-args-noAdd5} + the text for the \emph{optional} argument has not received any additional indentation, and that in \cref{lst:myenv-args-noAdd6} the + \emph{mandatory} argument has not received any additional indentation; in both cases, the \emph{body} has not received any additional indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-noAdd5.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-noAdd5}}{lst:myenv-args-noAdd5} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-noAdd6.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-noAdd6}}{lst:myenv-args-noAdd6} + \end{minipage} + +\yamltitle{indentRules}*{fields} + We may also specify indentation rules for environment code blocks using the \texttt{indentRules} field; see, for example, + \cref{lst:myenv-rules1,lst:myenv-rules2}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-rules1.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-rules1.yaml}}{lst:myenv-rules1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-rules2.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-rules2.yaml}}{lst:myenv-rules2} + \end{minipage} + + On applying either of the following commands, + \begin{commandshell} +latexindent.pl myenv.tex -l myenv-rules1.yaml +latexindent.pl myenv.tex -l myenv-rules2.yaml +\end{commandshell} + we obtain the output given in \cref{lst:myenv-rules-output}; note in particular that the environment \texttt{myenv} + has received one tab (from the \texttt{outer} environment) plus three spaces from \cref{lst:myenv-rules1} or \ref{lst:myenv-rules2}. + + \cmhlistingsfromfile{demonstrations/myenv-rules1.tex}{\texttt{myenv.tex output (using either \cref{lst:myenv-rules1} or \cref{lst:myenv-rules2})}}{lst:myenv-rules-output} + + If you specify a field in \texttt{indentRules} using anything other than horizontal space, it will be ignored. + + Returning to the example in \cref{lst:myenv-args} that contains optional and mandatory arguments. Upon using \cref{lst:myenv-rules1} as in + \begin{commandshell} +latexindent.pl myenv-args.tex -l=myenv-rules1.yaml +\end{commandshell} + we obtain the output in \cref{lst:myenv-args-rules1}; note that the body, optional argument and mandatory argument have \emph{all} + received the same customised indentation. + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules1.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-rules1}}{lst:myenv-args-rules1} + + You can specify different indentation rules for the different features using, for example, \cref{lst:myenv-rules3,lst:myenv-rules4} + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-rules3.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-rules3.yaml}}{lst:myenv-rules3} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/myenv-rules4.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{myenv-rules4.yaml}}{lst:myenv-rules4} + \end{minipage} + + After running + \begin{commandshell} +latexindent.pl myenv-args.tex -l myenv-rules3.yaml +latexindent.pl myenv-args.tex -l myenv-rules4.yaml +\end{commandshell} + then we obtain the respective outputs given in \cref{lst:myenv-args-rules3,lst:myenv-args-rules4}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules3.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-rules3}}{lst:myenv-args-rules3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules4.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-rules4}}{lst:myenv-args-rules4} + \end{minipage} + + Note that in \cref{lst:myenv-args-rules3}, the optional argument has only received a single space of indentation, while the mandatory argument + has received the default (tab) indentation; the environment body has received three spaces of indentation. + + In \cref{lst:myenv-args-rules4}, the optional argument has received the default (tab) indentation, the mandatory argument has received two tabs + of indentation, and the body has received three spaces of indentation. + +\yamltitle{noAdditionalIndentGlobal}*{fields} + \begin{wrapfigure}[6]{r}[0pt]{7cm} + \cmhlistingsfromfile[firstnumber=247,linerange={247-248},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{env-noAdditionalGlobal.yaml}}{lst:noAdditionalIndentGlobal:environments} + \end{wrapfigure} + Assuming that your environment name is not found within neither \texttt{noAdditionalIndent} nor \texttt{indentRules}, the next + place that \texttt{latexindent.pl} will look is \texttt{noAdditionalIndentGlobal}, and in particular \emph{for the environments} key + (see \cref{lst:noAdditionalIndentGlobal:environments}). Let's say that you change + the value of \texttt{environments} to \texttt{1} in \cref{lst:noAdditionalIndentGlobal:environments}, and that you run + + \begin{widepage} + \begin{commandshell} +latexindent.pl myenv-args.tex -l env-noAdditionalGlobal.yaml +latexindent.pl myenv-args.tex -l myenv-rules1.yaml,env-noAdditionalGlobal.yaml +\end{commandshell} + \end{widepage} + + The respective output from these two commands are in \cref{lst:myenv-args-no-add-global1,lst:myenv-args-no-add-global2}; in \cref{lst:myenv-args-no-add-global1} notice that \emph{both} + environments receive no additional indentation but that the arguments of \texttt{myenv} still \emph{do} receive indentation. In \cref{lst:myenv-args-no-add-global2} + notice that the \emph{outer} environment does not receive additional indentation, but because of the settings from \texttt{myenv-rules1.yaml} (in \vref{lst:myenv-rules1}), the \texttt{myenv} + environment still \emph{does} receive indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules1-noAddGlobal1.tex}{\texttt{myenv-args.tex} using \cref{lst:noAdditionalIndentGlobal:environments}}{lst:myenv-args-no-add-global1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules1-noAddGlobal2.tex}{\texttt{myenv-args.tex} using \cref{lst:noAdditionalIndentGlobal:environments,lst:myenv-rules1}}{lst:myenv-args-no-add-global2} + \end{minipage} + + In fact, \texttt{noAdditionalIndentGlobal} also contains keys that control the indentation of optional and mandatory + arguments; on referencing \cref{lst:opt-args-no-add-glob,lst:mand-args-no-add-glob} + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/opt-args-no-add-glob.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{opt-args-no-add-glob.yaml}}{lst:opt-args-no-add-glob} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mand-args-no-add-glob.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{mand-args-no-add-glob.yaml}}{lst:mand-args-no-add-glob} + \end{minipage} + + we may run the commands + \begin{commandshell} +latexindent.pl myenv-args.tex -local opt-args-no-add-glob.yaml +latexindent.pl myenv-args.tex -local mand-args-no-add-glob.yaml +\end{commandshell} + which produces the respective outputs given in \cref{lst:myenv-args-no-add-opt,lst:myenv-args-no-add-mand}. Notice that in \cref{lst:myenv-args-no-add-opt} + the \emph{optional} argument has not received any additional indentation, and in \cref{lst:myenv-args-no-add-mand} the \emph{mandatory} argument + has not received any additional indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules1-noAddGlobal3.tex}{\texttt{myenv-args.tex} using \cref{lst:opt-args-no-add-glob}}{lst:myenv-args-no-add-opt} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-rules1-noAddGlobal4.tex}{\texttt{myenv-args.tex} using \cref{lst:mand-args-no-add-glob}}{lst:myenv-args-no-add-mand} + \end{minipage} + +\yamltitle{indentRulesGlobal}*{fields} + \begin{wrapfigure}[4]{r}[0pt]{7cm} + \cmhlistingsfromfile[firstnumber=263,linerange={263-264},style=yaml-LST]{../defaultSettings.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{env-indentRulesGlobal.yaml}}{lst:indentRulesGlobal:environments} + \end{wrapfigure} + The final check that \texttt{latexindent.pl} will make is to look for \texttt{indentRulesGlobal} as detailed in \cref{lst:indentRulesGlobal:environments}; if you change the \texttt{environments} + field to anything involving horizontal space, say \lstinline!" "!, and then run the following commands + + \begin{commandshell} +latexindent.pl myenv-args.tex -l env-indentRules.yaml +latexindent.pl myenv-args.tex -l myenv-rules1.yaml,env-indentRules.yaml +\end{commandshell} + then the respective output is shown in \cref{lst:myenv-args-indent-rules-global1,lst:myenv-args-indent-rules-global2}. Note that + in \cref{lst:myenv-args-indent-rules-global1}, both the environment blocks have received a single-space indentation, whereas in + \cref{lst:myenv-args-indent-rules-global2} the \texttt{outer} environment has received single-space indentation (specified by \texttt{indentRulesGlobal}), + but \texttt{myenv} has received \lstinline!" "!, as specified by the particular \texttt{indentRules} for \texttt{myenv} \vref{lst:myenv-rules1}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-global-rules1.tex}{\texttt{myenv-args.tex} using \cref{lst:indentRulesGlobal:environments}}{lst:myenv-args-indent-rules-global1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-global-rules2.tex}{\texttt{myenv-args.tex} using \cref{lst:myenv-rules1,lst:indentRulesGlobal:environments}}{lst:myenv-args-indent-rules-global2} + \end{minipage} + + You can specify \texttt{indentRulesGlobal} for both optional and mandatory arguments, as detailed in \cref{lst:opt-args-indent-rules-glob,lst:mand-args-indent-rules-glob} + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/opt-args-indent-rules-glob.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{opt-args-indent-rules-glob.yaml}}{lst:opt-args-indent-rules-glob} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/mand-args-indent-rules-glob.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{mand-args-indent-rules-glob.yaml}}{lst:mand-args-indent-rules-glob} + \end{minipage} + + Upon running the following commands + \begin{commandshell} +latexindent.pl myenv-args.tex -local opt-args-indent-rules-glob.yaml +latexindent.pl myenv-args.tex -local mand-args-indent-rules-glob.yaml +\end{commandshell} + we obtain the respective outputs in \cref{lst:myenv-args-indent-rules-global3,lst:myenv-args-indent-rules-global4}. Note that the \emph{optional} + argument in \cref{lst:myenv-args-indent-rules-global3} has received two tabs worth of indentation, while the \emph{mandatory} argument has + done so in \cref{lst:myenv-args-indent-rules-global4}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-global-rules3.tex}{\texttt{myenv-args.tex} using \cref{lst:opt-args-indent-rules-glob}}{lst:myenv-args-indent-rules-global3} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/myenvironment-args-global-rules4.tex}{\texttt{myenv-args.tex} using \cref{lst:mand-args-indent-rules-glob}}{lst:myenv-args-indent-rules-global4} + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-with-items.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-with-items.tex new file mode 100644 index 00000000000..82bcc9044f2 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-environments-with-items.tex @@ -0,0 +1,59 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{Environments with items} + With reference to \vref{lst:indentafteritems,lst:itemNames}, some commands + may contain \texttt{item} commands; for the purposes of this discussion, + we will use the code from \vref{lst:itemsbefore}. + + Assuming that you've populated \texttt{itemNames} with the name of your + \texttt{item}, you can put the item name into \texttt{noAdditionalIndent} + as in \cref{lst:item-noAdd1}, although a more efficient approach may be + to change the relevant field in \texttt{itemNames} to \texttt{0}. Similarly, + you can customise the indentation that your \texttt{item} receives using + \texttt{indentRules}, as in \cref{lst:item-rules1} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/item-noAdd1.yaml}[yaml-TCB]{\texttt{item-noAdd1.yaml}}{lst:item-noAdd1} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/item-rules1.yaml}[yaml-TCB]{\texttt{item-rules1.yaml}}{lst:item-rules1} + \end{minipage} + + Upon running the following commands + \begin{commandshell} +latexindent.pl items1.tex -local item-noAdd1.yaml +latexindent.pl items1.tex -local item-rules1.yaml +\end{commandshell} + the respective outputs are given in \cref{lst:items1-noAdd1,lst:items1-rules1}; note that in \cref{lst:items1-noAdd1} + that the text after each \texttt{item} has not received any additional indentation, and in \cref{lst:items1-rules1}, + the text after each \texttt{item} has received a single space of indentation, specified by \cref{lst:item-rules1}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/items1-noAdd1.tex}{\texttt{items1.tex} using \cref{lst:item-noAdd1}}{lst:items1-noAdd1} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/items1-rules1.tex}{\texttt{items1.tex} using \cref{lst:item-rules1}}{lst:items1-rules1} + \end{minipage} + + Alternatively, you might like to populate \texttt{noAdditionalIndentGlobal} or \texttt{indentRulesGlobal} using the \texttt{items} + key, as demonstrated in \cref{lst:items-noAdditionalGlobal,lst:items-indentRulesGlobal}. Note that there is a need to + `reset/remove' the \texttt{item} field from \texttt{indentRules} in both cases (see the hierarchy description given on \cpageref{sec:noadd-indent-rules}) + as the \texttt{item} command is a member of \texttt{indentRules} by default. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/items-noAdditionalGlobal.yaml}[yaml-TCB]{\texttt{items-noAdditionalGlobal.yaml}}{lst:items-noAdditionalGlobal} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/items-indentRulesGlobal.yaml}[yaml-TCB]{\texttt{items-indentRulesGlobal.yaml}}{lst:items-indentRulesGlobal} + \end{minipage} + + Upon running the following commands, + \begin{commandshell} +latexindent.pl items1.tex -local items-noAdditionalGlobal.yaml +latexindent.pl items1.tex -local items-indentRulesGlobal.yaml +\end{commandshell} + the respective outputs from \cref{lst:items1-noAdd1,lst:items1-rules1} are obtained; note, however, that + \emph{all} such \texttt{item} commands without their own individual \texttt{noAdditionalIndent} or \texttt{indentRules} + settings would behave as in these listings. diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-headings.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-headings.tex new file mode 100644 index 00000000000..7c062666978 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-headings.tex @@ -0,0 +1,93 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{\texttt{afterHeading} code blocks}\label{subsubsec-headings-no-add-indent-rules} + Let's use the example \cref{lst:headings2} for demonstration throughout this \namecref{subsubsec-headings-no-add-indent-rules}. + As discussed on \cpageref{lst:headings1}, by default \texttt{latexindent.pl} will not add indentation after headings. + + \cmhlistingsfromfile{demonstrations/headings2.tex}{\texttt{headings2.tex}}{lst:headings2} + + On using the YAML file in \cref{lst:headings3yaml} by running the command + \begin{commandshell} +latexindent.pl headings2.tex -l headings3.yaml + \end{commandshell} + we obtain the output in \cref{lst:headings2-mod3}. Note that the argument of \texttt{paragraph} has received (default) indentation, + and that the body after the heading statement has received (default) indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod3.tex}{\texttt{headings2.tex} using \cref{lst:headings3yaml}}{lst:headings2-mod3} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings3.yaml}[yaml-TCB]{\texttt{headings3.yaml}}{lst:headings3yaml} + \end{minipage} + + If we specify \texttt{noAdditionalIndent} as in \cref{lst:headings4yaml} and run the command + \begin{commandshell} +latexindent.pl headings2.tex -l headings4.yaml + \end{commandshell} + then we receive the output in \cref{lst:headings2-mod4}. Note that the arguments \emph{and} the body after the heading + of \texttt{paragraph} has received no additional indentation, because we have specified \texttt{noAdditionalIndent} in scalar form. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod4.tex}{\texttt{headings2.tex} using \cref{lst:headings4yaml}}{lst:headings2-mod4} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings4.yaml}[yaml-TCB]{\texttt{headings4.yaml}}{lst:headings4yaml} + \end{minipage} + + Similarly, if we specify \texttt{indentRules} as in \cref{lst:headings5yaml} and run analogous commands to those above, + we receive the output in \cref{lst:headings2-mod5}; note that the \emph{body}, \emph{mandatory argument} and content + \emph{after the heading} of \texttt{paragraph} have \emph{all} received three tabs worth of indentation. + + \begin{minipage}{.55\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod5.tex}{\texttt{headings2.tex} using \cref{lst:headings5yaml}}{lst:headings2-mod5} + \end{minipage}% + \hfill + \begin{minipage}{.42\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings5.yaml}[yaml-TCB]{\texttt{headings5.yaml}}{lst:headings5yaml} + \end{minipage} + + We may, instead, specify \texttt{noAdditionalIndent} in `field' form, as in \cref{lst:headings6yaml} which gives the output in \cref{lst:headings2-mod6}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod6.tex}{\texttt{headings2.tex} using \cref{lst:headings6yaml}}{lst:headings2-mod6} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings6.yaml}[yaml-TCB]{\texttt{headings6.yaml}}{lst:headings6yaml} + \end{minipage} + + Analogously, we may specify \texttt{indentRules} as in \cref{lst:headings7yaml} which gives the output in \cref{lst:headings2-mod7}; + note that mandatory argument text has only received a single space of indentation, while the body after the heading has + received three tabs worth of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod7.tex}{\texttt{headings2.tex} using \cref{lst:headings7yaml}}{lst:headings2-mod7} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings7.yaml}[yaml-TCB]{\texttt{headings7.yaml}}{lst:headings7yaml} + \end{minipage} + + Finally, let's consider \texttt{noAdditionalIndentGlobal} and \texttt{indentRulesGlobal} shown in \cref{lst:headings8yaml,lst:headings9yaml} + respectively, with respective output in \cref{lst:headings2-mod8,lst:headings2-mod9}. Note that in \cref{lst:headings8yaml} the + \emph{mandatory argument} of \texttt{paragraph} has received a (default) tab's worth of indentation, while the body after the + heading has received \emph{no additional indentation}. Similarly, in \cref{lst:headings2-mod9}, the \emph{argument} has received both a + (default) tab plus two spaces of indentation (from the global rule specified in \cref{lst:headings9yaml}), and the remaining body + after \texttt{paragraph} has received just two spaces of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod8.tex}{\texttt{headings2.tex} using \cref{lst:headings8yaml}}{lst:headings2-mod8} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings8.yaml}[yaml-TCB]{\texttt{headings8.yaml}}{lst:headings8yaml} + \end{minipage} + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/headings2-mod9.tex}{\texttt{headings2.tex} using \cref{lst:headings9yaml}}{lst:headings2-mod9} + \end{minipage}% + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/headings9.yaml}[yaml-TCB]{\texttt{headings9.yaml}}{lst:headings9yaml} + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-ifelsefi.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-ifelsefi.tex new file mode 100644 index 00000000000..5c9a37dbb22 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-ifelsefi.tex @@ -0,0 +1,70 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{ifelsefi code blocks} + Let's use the simple example shown in \cref{lst:ifelsefi1}; when + \texttt{latexindent.pl} operates on this file, the output as in \cref{lst:ifelsefi1-default}; + note that the body of each of the \lstinline!\if! statements have been indented, + and that the \lstinline!\else! statement has been accounted for correctly. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1.tex}{\texttt{ifelsefi1.tex}}{lst:ifelsefi1} + \end{minipage}% + \hfill + \begin{minipage}{.54\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1-default.tex}{\texttt{ifelsefi1.tex} default output}{lst:ifelsefi1-default} + \end{minipage} + + It is recommended to specify \texttt{noAdditionalIndent} and \texttt{indentRules} in the `scalar' form only + for these type of code blocks, although the `field' form would work, assuming that \texttt{body} was specified. + Examples are shown in \cref{lst:ifnum-noAdd,lst:ifnum-indent-rules}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/ifnum-noAdd.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{ifnum-noAdd.yaml}}{lst:ifnum-noAdd} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/ifnum-indent-rules.yaml}[width=.8\linewidth,before=\centering,yaml-TCB]{\texttt{ifnum-indent-rules.yaml}}{lst:ifnum-indent-rules} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl ifelsefi1.tex -local ifnum-noAdd.yaml +latexindent.pl ifelsefi1.tex -l ifnum-indent-rules.yaml +\end{commandshell} + we receive the respective output given in \cref{lst:ifelsefi1-output-noAdd,lst:ifelsefi1-output-indent-rules}; note that + in \cref{lst:ifelsefi1-output-noAdd}, the \texttt{ifnum} code block has \emph{not} received any additional indentation, + while in \cref{lst:ifelsefi1-output-indent-rules}, the \texttt{ifnum} code block has received one tab and two spaces of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1-noAdd.tex}{\texttt{ifelsefi1.tex} using \cref{lst:ifnum-noAdd}}{lst:ifelsefi1-output-noAdd} + \end{minipage} + \hfill + \begin{minipage}{.5\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1-indent-rules.tex}{\texttt{ifelsefi1.tex} using \cref{lst:ifnum-indent-rules}}{lst:ifelsefi1-output-indent-rules} + \end{minipage} + + We may specify \texttt{noAdditionalIndentGlobal} and \texttt{indentRulesGlobal} as in \cref{lst:ifelsefi-noAdd-glob,lst:ifelsefi-indent-rules-global}. + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/ifelsefi-noAdd-glob.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{ifelsefi-noAdd-glob.yaml}}{lst:ifelsefi-noAdd-glob} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/ifelsefi-indent-rules-global.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{ifelsefi-indent-rules-global.yaml}}{lst:ifelsefi-indent-rules-global} + \end{minipage} + + Upon running the following commands + \begin{commandshell} +latexindent.pl ifelsefi1.tex -local ifelsefi-noAdd-glob.yaml +latexindent.pl ifelsefi1.tex -l ifelsefi-indent-rules-global.yaml +\end{commandshell} + we receive the outputs in \cref{lst:ifelsefi1-output-noAdd-glob,lst:ifelsefi1-output-indent-rules-global}; notice that in + \cref{lst:ifelsefi1-output-noAdd-glob} neither of the \texttt{ifelsefi} code blocks have received indentation, while in + \cref{lst:ifelsefi1-output-indent-rules-global} both code blocks have received a single space of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1-noAdd-glob.tex}{\texttt{ifelsefi1.tex} using \cref{lst:ifelsefi-noAdd-glob}}{lst:ifelsefi1-output-noAdd-glob} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/ifelsefi1-indent-rules-global.tex}{\texttt{ifelsefi1.tex} using \cref{lst:ifelsefi-indent-rules-global}}{lst:ifelsefi1-output-indent-rules-global} + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-no-add-remaining-code-blocks.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-no-add-remaining-code-blocks.tex new file mode 100644 index 00000000000..60063fbb2b7 --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-no-add-remaining-code-blocks.tex @@ -0,0 +1,109 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{The remaining code blocks} + Referencing the different types of code blocks in \vref{tab:code-blocks}, we have a few + code blocks yet to cover; these are very similar to the \texttt{commands} code block type + covered comprehensively in \vref{subsubsec:commands-arguments}, but a small discussion + defining these remaining code blocks is necessary. + + \paragraph{\texttt{keyEqualsValuesBracesBrackets}} + \texttt{latexindent.pl} defines this type of code block by the following criteria: + \begin{itemize} + \item it must immediately follow either \lstinline!{! OR \lstinline![! OR \lstinline!,! with comments + and blank lines allowed; + \item then it has a name made up of the characters detailed in \vref{tab:code-blocks}; + \item then an $=$ symbol; + \item then at least one set of curly braces or square brackets (comments and line breaks allowed throughout). + \end{itemize} + + An example is shown in \cref{lst:pgfkeysbefore}, with the default output given in \cref{lst:pgfkeys1:default}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/pgfkeys1.tex}{\texttt{pgfkeys1.tex}}{lst:pgfkeysbefore} + \end{minipage}% + \hfill + \begin{minipage}{.5\textwidth} + \cmhlistingsfromfile{demonstrations/pgfkeys1-default.tex}{\texttt{pgfkeys1.tex} default output}{lst:pgfkeys1:default} + \end{minipage}% + + In \cref{lst:pgfkeys1:default}, note that the maximum indentation is three tabs, and these come from: + \begin{itemize} + \item the \lstinline!\pgfkeys! command's mandatory argument; + \item the \lstinline!start coordinate/.initial! key's mandatory argument; + \item the \lstinline!start coordinate/.initial! key's body, which is defined as any lines following the name of the + key that include its arguments. This is the part controlled by the \emph{body} field for \texttt{noAdditionalIndent} + and friends from \cpageref{sec:noadd-indent-rules}. + \end{itemize} + \paragraph{\texttt{namedGroupingBracesBrackets}} + This type of code block is mostly motivated by tikz-based code; we define this code block as follows: + \begin{itemize} + \item it must immediately follow either \emph{horizontal space} OR \emph{one or more line breaks} OR \lstinline!{! OR \lstinline![! + OR \lstinline!$!; + \item the name may contain the characters detailed in \vref{tab:code-blocks}; + \item then at least one set of curly braces or square brackets (comments and line breaks allowed throughout). + \end{itemize} + A simple example is given in \cref{lst:child1}, with default output in \cref{lst:child1:default}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/child1.tex}{\texttt{child1.tex}}{lst:child1} + \end{minipage}% + \hfill + \begin{minipage}{.5\textwidth} + \cmhlistingsfromfile{demonstrations/child1-default.tex}{\texttt{child1.tex} default output}{lst:child1:default} + \end{minipage}% + + In particular, \texttt{latexindent.pl} considers \texttt{child}, \texttt{parent} and \texttt{node} all to be \texttt{namedGroupingBracesBrackets}\footnote{ + You may like to verify this by using the \texttt{-tt} option and checking \texttt{indent.log}! }. + Referencing \cref{lst:child1:default}, + note that the maximum indentation is two tabs, and these come from: + \begin{itemize} + \item the \lstinline!child!'s mandatory argument; + \item the \lstinline!child!'s body, which is defined as any lines following the name of the \texttt{namedGroupingBracesBrackets} + that include its arguments. This is the part controlled by the \emph{body} field for \texttt{noAdditionalIndent} + and friends from \cpageref{sec:noadd-indent-rules}. + \end{itemize} + + \paragraph{\texttt{UnNamedGroupingBracesBrackets}} occur in a variety of situations; specifically, we define + this type of code block as satisfying the following criteria: + \begin{itemize} + \item it must immediately follow either \lstinline!{! OR \lstinline![! OR \lstinline!,! OR \lstinline!&! OR \lstinline!)! OR \lstinline!(! + OR \lstinline!$!; + \item then at least one set of curly braces or square brackets (comments and line breaks allowed throughout). + \end{itemize} + + An example is shown in \cref{lst:psforeach1} with default output give in \cref{lst:psforeach:default}. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/psforeach1.tex}{\texttt{psforeach1.tex}}{lst:psforeach1} + \end{minipage}% + \hfill + \begin{minipage}{.5\textwidth} + \cmhlistingsfromfile{demonstrations/psforeach1-default.tex}{\texttt{psforeach1.tex} default output}{lst:psforeach:default} + \end{minipage}% + + Referencing \cref{lst:psforeach:default}, there are \emph{three} sets of unnamed braces. Note also that the maximum value + of indentation is three tabs, and these come from: + \begin{itemize} + \item the \lstinline!\psforeach! command's mandatory argument; + \item the \emph{first} un-named braces mandatory argument; + \item the \emph{first} un-named braces \emph{body}, which we define as any lines following the first opening \lstinline!{! or \lstinline![! + that defined the code block. This is the part controlled by the \emph{body} field for \texttt{noAdditionalIndent} + and friends from \cpageref{sec:noadd-indent-rules}. + \end{itemize} + Users wishing to customise the mandatory and/or optional arguments on a \emph{per-name} basis for the \texttt{UnNamedGroupingBracesBrackets} + should use \texttt{always-un-named}. + + \paragraph{\texttt{filecontents}} code blocks behave just as \texttt{environments}, except that neither arguments nor items are sought. + +\subsubsection{Summary} + Having considered all of the different types of code blocks, the functions of the fields given in + \cref{lst:noAdditionalIndentGlobal,lst:indentRulesGlobal} should now make sense. + + \begin{widepage} + \begin{minipage}{.47\linewidth} + \cmhlistingsfromfile[firstnumber=247,linerange={247-259},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[before=\centering,yaml-TCB]{\texttt{noAdditionalIndentGlobal}}{lst:noAdditionalIndentGlobal} + \end{minipage}% + \hfill + \begin{minipage}{.47\linewidth} + \cmhlistingsfromfile[firstnumber=263,linerange={263-275},style=yaml-LST,numbers=left]{../defaultSettings.yaml}[before=\centering,yaml-TCB]{\texttt{indentRulesGlobal}}{lst:indentRulesGlobal} + \end{minipage}% + \end{widepage} diff --git a/Master/texmf-dist/doc/support/latexindent/subsubsec-special.tex b/Master/texmf-dist/doc/support/latexindent/subsubsec-special.tex new file mode 100644 index 00000000000..8deca581f0d --- /dev/null +++ b/Master/texmf-dist/doc/support/latexindent/subsubsec-special.tex @@ -0,0 +1,60 @@ +% arara: pdflatex: {shell: yes, files: [latexindent]} +\subsubsection{\texttt{specialBeginEnd} code blocks} + Let's use the example from \vref{lst:specialbefore} which has default output shown in + \vref{lst:specialafter}. + + It is recommended to specify \texttt{noAdditionalIndent} and \texttt{indentRules} in the `scalar' form + for these type of code blocks, although the `field' form would work, assuming that \texttt{body} was specified. + Examples are shown in \cref{lst:displayMath-noAdd,lst:displayMath-indent-rules}. + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/displayMath-noAdd.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{displayMath-noAdd.yaml}}{lst:displayMath-noAdd} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/displayMath-indent-rules.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{displayMath-indent-rules.yaml}}{lst:displayMath-indent-rules} + \end{minipage} + + After running the following commands, + \begin{commandshell} +latexindent.pl special1.tex -local displayMath-noAdd.yaml +latexindent.pl special1.tex -l displayMath-indent-rules.yaml +\end{commandshell} + we receive the respective output given in \cref{lst:special1-output-noAdd,lst:special1-output-indent-rules}; note that + in \cref{lst:special1-output-noAdd}, the \texttt{displayMath} code block has \emph{not} received any additional indentation, + while in \cref{lst:special1-output-indent-rules}, the \texttt{displayMath} code block has received three tabs worth of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1-noAdd.tex}{\texttt{special1.tex} using \cref{lst:displayMath-noAdd}}{lst:special1-output-noAdd} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1-indent-rules.tex}{\texttt{special1.tex} using \cref{lst:displayMath-indent-rules}}{lst:special1-output-indent-rules} + \end{minipage} + + We may specify \texttt{noAdditionalIndentGlobal} and \texttt{indentRulesGlobal} as in \cref{lst:special-noAdd-glob,lst:special-indent-rules-global}. + + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/special-noAdd-glob.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{special-noAdd-glob.yaml}}{lst:special-noAdd-glob} + \end{minipage} + \hfill + \begin{minipage}{.49\textwidth} + \cmhlistingsfromfile[style=yaml-LST]{demonstrations/special-indent-rules-global.yaml}[width=.9\linewidth,before=\centering,yaml-TCB]{\texttt{special-indent-rules-global.yaml}}{lst:special-indent-rules-global} + \end{minipage} + + Upon running the following commands + \begin{commandshell} +latexindent.pl special1.tex -local special-noAdd-glob.yaml +latexindent.pl special1.tex -l special-indent-rules-global.yaml +\end{commandshell} + we receive the outputs in \cref{lst:special1-output-noAdd-glob,lst:special1-output-indent-rules-global}; notice that in + \cref{lst:special1-output-noAdd-glob} neither of the \texttt{special} code blocks have received indentation, while in + \cref{lst:special1-output-indent-rules-global} both code blocks have received a single space of indentation. + + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1-noAdd-glob.tex}{\texttt{special1.tex} using \cref{lst:special-noAdd-glob}}{lst:special1-output-noAdd-glob} + \end{minipage} + \hfill + \begin{minipage}{.45\textwidth} + \cmhlistingsfromfile{demonstrations/special1-indent-rules-global.tex}{\texttt{special1.tex} using \cref{lst:special-indent-rules-global}}{lst:special1-output-indent-rules-global} + \end{minipage} diff --git a/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex b/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex deleted file mode 100644 index 04053c027a9..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/alignmentoutsideEnvironments.tex +++ /dev/null @@ -1,29 +0,0 @@ -% 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{tabular} -} -\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} diff --git a/Master/texmf-dist/doc/support/latexindent/success/bigTest.tex b/Master/texmf-dist/doc/support/latexindent/success/bigTest.tex deleted file mode 100644 index e38913da9b3..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/bigTest.tex +++ /dev/null @@ -1,293 +0,0 @@ -% arara: indent: {trace: true, overwrite: yes} -\documentclass[10pt,twoside]{report} -\begin{document} - -% needed for the mini-tableofcontents -\dominitoc -\faketableofcontents - -\fancyhf{} % delete current header and footer -\fancyhead[LE,RO]{\bfseries\thepage} -\fancyhead[LO,RE]{\tiny\rightmark} -\fancyheadoffset[LE,LO]{4cm} - -\pagestyle{fancy} -%\include{coverpage} -\include{functions} -%\include{exponentialfunctions} -%\include{functions2} -%\include{logarithms} -%\include{polyrat} -%\include{ideas} - -%======================= -% BEGIN SOLUTIONS -%======================= - -% change the page geometry using \newgeometry -%\cleardoublepage -\clearpage -%\setbool{@twoside}{false} -\fancyheadoffset[RE,RO]{2cm} -\fancyheadoffset[LE,LO]{1cm} -\renewcommand{\rightmark}{Solutions to Section \thesection} -\fancyhead[LO,RE]{\rightmark} -\newgeometry{left=4cm,right=4cm,showframe=true, - marginratio=1:1, - top=1.5cm,bottom=1.5cm,bindingoffset=0cm} - -% finish the php file -\Writetofile{crossrefsWEB}{?>} - -% close the solutions files -\Closesolutionfile{shortsolutions} -\Closesolutionfile{longsolutions} -%\Closesolutionfile{hints} -\Closesolutionfile{crossrefsWEB} - -% when itemized lists are used in the solutions, they -% are actually at 2nd depth because the solution environment -% uses an \itemize environment to get the indendation correct -\setlist[itemize,2]{label=\textbullet} - -% SHORT solution to problem (show only odd, even, all) -% Note: this renewenvironment needs to go here -% so that the answers package can still -% display correctly to the page if needed -\newbool{oddproblemnumber} -\renewenvironment{shortSoln}[1]{% - \exploregroups % needed to ignore {} - % before the environment starts - this is a stretchable space - \vskip 0.1cm plus 2cm minus 0.1cm% - \fullexpandarg % need this line so that '.' are counted - % - % either problems, or subproblems, e.g: 3.1 or 3.1.4 respectively - % determine which one by counting the '.' - \StrCount{#1}{.}[\numberofdecimals] - % - % find the problem number by splitting the string - \ifnumequal{\numberofdecimals}{0}% - {% - % problems, such as 4, 5, 6, ... - \def\problemnumber{#1}% - }% - {}% - \ifnumequal{\numberofdecimals}{1}% - {% - % subproblems, such as 4.3, 1.2, 10.5 - \StrBefore{#1}{.}[\problemnumber]% - }% - {}% - \ifnumequal{\numberofdecimals}{2}% - {% - % subproblems such as 1.3.1, 1.2.4, 7.5.6 - % note that these aren't currently used, but maybe someday - \StrBehind{#1}{.}[\newbit]% - \StrBefore{\newbit}{.}[\problemnumber]% - }% - {}% - % - % determine if the problem number is odd or even - % and depending on our choices above, display or not - \ifnumodd{\problemnumber}% - {% - % set a boolean that says the problem number is odd (used later) - \setbool{oddproblemnumber}{true}% - % display or not - \ifbool{showoddsolns}% - {% - % if we want to show the odd problems - \ifbool{coreproblemYesNo}% - {% Core problem - \expandafter\itemize[label=\llap{$\bigstar$ }\bfseries \hyperlink{prob:#1:\thechapter:\thesection}{#1}.]\item% - }% - {% NOT Core problem - \expandafter\itemize[label=\bfseries \hyperlink{prob:#1:\thechapter:\thesection}{#1}.]\item% - }% - }% - {% - % otherwise don't show them! - \expandafter\comment% - }% - }% - {% - % even numbered problem, set the boolean (used later) - \setbool{oddproblemnumber}{false}% - \ifbool{showevensolns}% - {% - % if we want to show the even problems - \ifbool{coreproblemYesNo}% - {% Core problem - \expandafter\itemize[label=\llap{$\bigstar$ }\itshape \hyperlink{prob:#1:\thechapter:\thesection}{#1}.]\item% - }% - {% NOT Core problem - \expandafter\itemize[label=\itshape \hyperlink{prob:#1:\thechapter:\thesection}{#1}.]\item% - }% - }% - {% - % otherwise don't show them! - \expandafter\comment% - }% - }% -}% -{% - % after the environment finishes - \ifbool{oddproblemnumber}% - {% - % odd numbered problems - \ifbool{showoddsolns}% - {% - % if we want to show the odd problems - % then the environment is finished - \enditemize% - }% - {% - % otherwise we need to finish the comment - \expandafter\endcomment% - }% - }% - {% - % even numbered problems - \ifbool{showevensolns}% - {% - % if we want to show the even problems - % then the environment is finished - \enditemize% - }% - {% - % otherwise we need to finish the comment - \expandafter\endcomment% - }% - }% -} - -% LONG solution to problem (show only odd, even, all) -% Note: this renewenvironment needs to go here -% so that the answers package can still -% display correctly to the page if needed -\renewenvironment{longSoln}[1]{% - \exploregroups % needed to ignore {} - % before the environment starts - this is a stretchable space - \vskip 0.1cm plus 2cm minus 0.1cm% - \fullexpandarg % need this line so that '.' are counted - % - % either problems, or subproblems, e.g: 3.1 or 3.1.4 respectively - % determine which one by counting the '.' - \StrCount{#1}{.}[\numberofdecimals] - % - % find the problem number by splitting the string - \ifnumequal{\numberofdecimals}{0}% - {% - % problems, such as 4, 5, 6, ... - \def\problemnumber{#1}% - }% - {}% - \ifnumequal{\numberofdecimals}{1}% - {% - % problems, such as 4.3, 1.2, 10.5 - \StrBefore{#1}{.}[\problemnumber]% - }% - {}% - \ifnumequal{\numberofdecimals}{2}% - {% - % subproblems such as 1.3.1, 1.2.4, 7.5.6 - \StrBehind{#1}{.}[\newbit]% - \StrBefore{\newbit}{.}[\problemnumber]% - }% - {}% - % - % determine if the problem number is odd or even - % and depending on our choices above, display or not - \ifnumodd{\problemnumber}% - {% - % set a boolean that says the problem number is odd (used later) - \setbool{oddproblemnumber}{true}% - % display or not - \ifbool{showoddsolns}% - {% - % if we want to show the odd problems - {\bfseries \hyperlink{prob:#1:\thechapter:\thesection}{#1}.}% - }% - {% - % otherwise don't show them! - \expandafter\comment% - }% - }% - {% - % even numbered problem, set the boolean (used later) - \setbool{oddproblemnumber}{false}% - \ifbool{showevensolns}% - {% - % if we want to show the even problems - {\itshape \hyperlink{prob:#1:\thechapter:\thesection}{#1}.}% - }% - {% - % otherwise don't show them! - \expandafter\comment% - }% - }% -}% -{% - % after the environment finishes - \ifbool{oddproblemnumber}% - {% - % odd numbered problems - \ifbool{showoddsolns}% - {% - % if we want to show the odd problems - % then the environment is finished - }% - {% - % otherwise we need to finish the comment - \expandafter\endcomment% - }% - }% - {% - % even numbered problems - \ifbool{showevensolns}% - {% - % if we want to show the even problems - % then the environment is finished - }% - {% - % otherwise we need to finish the comment - \expandafter\endcomment% - }% - }% -} - -% renew tikzpicture environment to make it use valign=t -% on every one, which fixes vertical alignment of tikzpicture -% with the solution label: http://tex.stackexchange.com/questions/30367/aligning-enumerate-labels-to-top-of-image -\BeforeBeginEnvironment{tikzpicture}{\begin{adjustbox}{valign=t}} -\AfterEndEnvironment{tikzpicture}{\end{adjustbox}} - -% do the same for the tabular environment -\BeforeBeginEnvironment{tabular}{\begin{adjustbox}{valign=t}} -\AfterEndEnvironment{tabular}{\end{adjustbox}} - -% set every picture in the solutions to have \solutionfigurewidth -\pgfplotsset{ - every axis/.append style={% - width=\solutionfigurewidth}} - -% input the SHORT solutions file -\IfFileExists{shortsolutions.tex}{\input{shortsolutions.tex}}{} - -\clearpage -% input the LONG solutions file -%\IfFileExists{longsolutions.tex}{\input{longsolutions.tex}}{} - -\clearpage -% input the HINTS file -%\IfFileExists{hints.tex}{\input{hints.tex}}{} -%======================= -% END SOLUTIONS -%======================= - -%======================= -% INDEX -%======================= -\printindex - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex b/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex deleted file mode 100644 index b389b436602..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/braceTest.tex +++ /dev/null @@ -1,57 +0,0 @@ -% arara: indent: { overwrite: on} - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - } - }% - %--------------------------------------------------------------------------- -} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - } -}} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep -}}} - -some other text -some other text -some other text - - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - }} -} - -some other text -some other text -some other text - -\parbox{ - \begin{something} - - \end{something} -} - -some other text -some other text -some other text diff --git a/Master/texmf-dist/doc/support/latexindent/success/braceTestsmall.tex b/Master/texmf-dist/doc/support/latexindent/success/braceTestsmall.tex deleted file mode 100644 index 38b7f495db6..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/braceTestsmall.tex +++ /dev/null @@ -1,31 +0,0 @@ -% arara: indent: {trace: on, overwrite: on} -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep }% - }% - %--------------------------------------------------------------------------- -} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep }}% -} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={\someothercommand{here}% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep }}} - -some other text -some other text -some other text diff --git a/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex b/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex deleted file mode 100644 index 34cf9df16fb..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/bracketTest.tex +++ /dev/null @@ -1,6 +0,0 @@ -\cmh[ - here is some text -] -\cmh{ - here is some text -} diff --git a/Master/texmf-dist/doc/support/latexindent/success/conditional.tex b/Master/texmf-dist/doc/support/latexindent/success/conditional.tex deleted file mode 100644 index 9a857e0af64..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/conditional.tex +++ /dev/null @@ -1,12 +0,0 @@ -% arara: indent: {overwrite: yes} -% add these lines to a localSettings.yaml file -%constructIfElseFi: -% if@isu@draftcls@: 1 -\newif\if@isu@draftcls@ -\if@isu@draftcls@ - \RequirePackage[firstpage]{draftwatermark} - \RequirePackage{datetime} - \newcommand{\isu@draftfooter}{DRAFT --- rendered \today\ at \currenttime} -\else - \newcommand{\isu@draftfooter}{} -\fi diff --git a/Master/texmf-dist/doc/support/latexindent/success/environments.tex b/Master/texmf-dist/doc/support/latexindent/success/environments.tex deleted file mode 100644 index 986474dca79..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/environments.tex +++ /dev/null @@ -1,39 +0,0 @@ -% arara: indent: { cruft: /home/cmhughes/Desktop/tmp/, overwrite: on, trace: yes, silent: yes, onlyDefault: no} -some -other -text -\begin{enumerate} - \item $3x^3y(-4x^3+y) = -12x^6y+3x^3y^2$ - \item $3x^3+y(-4x^3+y) = 3x^3-4x^3y+y^2$ - \item - \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 - \end{align*} -\end{enumerate} -\begin{enumerate} - \item $3x^3y(-4x^3+y) = -12x^6y+3x^3y^2$ - \item $3x^3+y(-4x^3+y) = 3x^3-4x^3y+y^2$ - \item - \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 - \end{align*} -\end{enumerate} - -\begin{something} - \begin{else} - again - \end{else} -\end{something} -no -environments -here -\[ x^2+ 3x\] -other text -\[ - x^2+ 3x -\] -other text diff --git a/Master/texmf-dist/doc/support/latexindent/success/figureValign.tex b/Master/texmf-dist/doc/support/latexindent/success/figureValign.tex deleted file mode 100644 index 8c2bc33281a..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/figureValign.tex +++ /dev/null @@ -1,124 +0,0 @@ -% arara: pdflatex -% !arara: indent: {overwrite: yes} -\documentclass{article} -\usepackage{lipsum} -\usepackage{graphicx} -\usepackage{environ} -\usepackage[showframe=true]{geometry} - -\newsavebox{\vabox} - -\NewEnviron{verticallyaligned}{% - % temporarily set \vamaxheight to nothing during the measurements - \let\vamaxheight\relax - % measure the height of the body - \begin{lrbox}{\vabox} - \BODY% - \end{lrbox}% - % set the height of the minipage box - \newlength{\vamaxheight} - \setlength{\vamaxheight}{\ht\vabox} - % output the body, which now contains the new height :) - \noindent\makebox[\linewidth][c]{\mbox{}\hfill\BODY\hfill\mbox{}}% -} - -\begin{document} - -\sbox{\vabox}{% - \begin{minipage}[b][][b]{.10\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-a} - \end{minipage}% - \begin{minipage}[b][][t]{.15\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-b} - \end{minipage}% - \begin{minipage}[b][][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-c} - \end{minipage}% - \begin{minipage}[b][][c]{.10\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \end{minipage}% - \begin{minipage}[b][][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \end{minipage}% -}% - -\noindent -\begin{minipage}[b][\ht\vabox][b]{.10\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-a} -\end{minipage}% -\hfill -\begin{minipage}[b][\ht\vabox][t]{.15\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-b} -\end{minipage}% -\hfill -\begin{minipage}[b][\ht\vabox][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-c} -\end{minipage}% -\hfill -\begin{minipage}[b][\ht\vabox][c]{.10\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} -\end{minipage}% -\hfill -\begin{minipage}[b][\ht\vabox][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} -\end{minipage}% -\par\lipsum - - -\begin{verticallyaligned} - \noindent\begin{minipage}[b][\vamaxheight][b]{.30\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-a} - \end{minipage}% - \hfill - \begin{minipage}[b][\vamaxheight][t]{.10\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-b} - \end{minipage}% - \hfill - \begin{minipage}[b][\vamaxheight][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image-c} - \end{minipage}% - \hfill - \begin{minipage}[b][\vamaxheight][c]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \end{minipage}% - \hfill - \begin{minipage}[b][\vamaxheight][t]{.20\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \end{minipage}% -\end{verticallyaligned} - -\lipsum[1] - -\begin{figure} - \begin{verticallyaligned} - \noindent\begin{minipage}[b][\vamaxheight][c]{.50\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \caption{} - \end{minipage}% - \hfill - \begin{minipage}[b][\vamaxheight][t]{.40\textwidth} - \centering - \includegraphics[width=\textwidth]{example-image} - \caption{} - \end{minipage}% - \end{verticallyaligned} - \caption{} -\end{figure} - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/filecontents.tex b/Master/texmf-dist/doc/support/latexindent/success/filecontents.tex deleted file mode 100644 index ccc35c32684..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/filecontents.tex +++ /dev/null @@ -1,73 +0,0 @@ -% arara: indent: {overwrite: true, trace: false, localSettings: yes} - -% used with localSettings.yaml as follows -%indentPreamble: 1 -%indentRules: -% @online: "\t\t\t\t" -% #myenvironment: "\t\t" -% myotherenvironment: "\t\t" -% \[: "\t\t" -% tabular: "\t\t\t" -%noAdditionalIndent: -% @online: 0 -% myotherenvironment: 1 -% \[: 0 -% \]: 0 -% tabular: 0 -% something: 0 -% parbox: 1 -%verbatimEnvironments: -% myotherenvironment: 1 -% tabular: 0 -% someothername: 0 - - -% \begin{noindent} -here we are in a block -% \end{noindent} -some more -\begin{tabular}{cccc} - 1 & 2 & 3 & 4 \\ - 5 & & 6 & \\ -\end{tabular} - -another test -\begin{tabular}{cccc} - 1 & 2 & 3 & 4 \\ - 5 & & 6 & \\ -\end{tabular} - -\begin{something} - \parbox{something - else - goes - here - } - some text some text - some text some text - some text some text - \[ - x^2+2x - \] - some text some text - some text some text - some text some text - some text some text - some text some text -\end{something} -\begin{filecontents}{mybib.bib} - @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} - -\begin{myotherenvironment} - some text goes here - some text goes here - some text goes here - some text goes here -\end{myotherenvironment} - diff --git a/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex b/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex deleted file mode 100644 index 46e501ebaa0..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/filecontents1.tex +++ /dev/null @@ -1,18 +0,0 @@ -% 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 deleted file mode 100644 index 54307023361..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/filecontents2.tex +++ /dev/null @@ -1,21 +0,0 @@ -% 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/ifelsefi.tex b/Master/texmf-dist/doc/support/latexindent/success/ifelsefi.tex deleted file mode 100644 index 389985acaed..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/ifelsefi.tex +++ /dev/null @@ -1,103 +0,0 @@ -% !arara: pdflatex -% arara: indent: {overwrite: yes, trace: yes, localSettings: yes} -\documentclass{report} -\usepackage{etoolbox} -\usepackage{pgfplots} -\usepackage{lipsum} - -\makeatletter -\newcommand{\totalchapters}[1]{% - \@ifundefined{c@totalchapters} - {% - \newcounter{totalchapters} - \setcounter{totalchapters}{#1} - \typeout{Defining a new counter: totalchapters (#1)} - }% - {% - \ifodd\value{totalchapters}=#1 - \typeout{Total Chapters match auxilary file (#1)} - \else - \typeout{Warning: total Chapter count updated from \the\value{totalchapters} to #1-- recompile to fix} - \fi - \setcounter{totalchapters}{#1} - }% -} -\newcommand{\definetotalpagecount}[2]{% - \@ifundefined{c@totalpages\@roman{#1}}% - {% - \newcounter{totalpages\@roman{#1}} - \setcounter{totalpages\@roman{#1}}{#2} - \typeout{Defining a new counter: totalpages\@roman{#1}} - }% - {% - \ifnum\value{totalpages\@roman{#1}}=#2 - \typeout{Total pages for Chapter #1 match auxilary file (#2)} - \else - \typeout{Warning: total pages for Chapter #1 updated from \the\value{totalpages\@roman{#1}} to #2-- recompile to fix} - \fi - \setcounter{totalpages\@roman{#1}}{#2} - }% -} - - -\preto\chapter{% - \ifnum\value{chapter}>0 - \immediate\write\@auxout{% - \string\definetotalpagecount\string{\thechapter\string}\string{\the\value{page}\string} - } - \fi -} - -\AtEndDocument{% - \immediate\write\@auxout{% - \string\definetotalpagecount\string{\thechapter\string}\string{\the\value{page}\string} - \string\totalchapters\string{\thechapter\string}% - } -} - -\newcommand{\drawPageChart}{% - \begin{tikzpicture} - \begin{axis}[ - xbar stacked, - xmin=-0.1, - %ymin=0,ymax=1, - bar width=40pt, - nodes near coords, - axis lines=none, - nodes near coords align={horizontal}, - visualization depends on=x \as \myxcoord, - nodes near coords={\pgfmathprintnumber\myxcoord}, - every node near coord/.append style={ - anchor=east}, - ] - \@ifundefined{c@totalchapters} - {} - {% - \foreach \i in {1,...,\thetotalchapters}{% - \addplot coordinates {(\the\value{totalpages\@roman{\i}},0)}; - } - } - \end{axis} - \end{tikzpicture} -} -\begin{document} - -\begin{figure}[!htb] - \centering - \drawPageChart - \caption{Blueprint of my thesis} -\end{figure} - - -\chapter{} - \lipsum -\chapter{} - \lipsum - \lipsum -\chapter{} - \lipsum - \lipsum - \lipsum - \lipsum - \lipsum -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/ifelsefiONE.tex b/Master/texmf-dist/doc/support/latexindent/success/ifelsefiONE.tex deleted file mode 100644 index 0d3c4f39322..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/ifelsefiONE.tex +++ /dev/null @@ -1,43 +0,0 @@ -% arara: indent: {overwrite: yes, trace: yes} -\documentclass[tikz]{standalone} -\usepackage{tikz} -\usetikzlibrary{decorations.pathmorphing,decorations.shapes} - -\begin{document} - -\foreach \radius in {1,2,...,20} -{ - \begin{tikzpicture} - % background rectangle - \filldraw[black] (-3,-3) rectangle (5,3); - % skyline - \filldraw[black!80!blue](-3,-3)--(-3,-2)--(-2.5,-2)--(-2.5,-1)--(-2.25,-1)--(-2.25,-2)--(-2,-2) - --(-2,-1)--(-1.75,-0.75)--(-1.5,-1) - --(-1.5,-2)--(-1.1,-2)--(-1.1,0)--(-0.5,0)--(-0.5,-2) - --(0,-2)--(0,-1.5)--(1,-1.5)--(1.25,-0.5)--(1.5,-1.5)--(1.5,-2) - --(2,-2)--(2,0)--(2.5,0)--(2.5,-2) - --(3,-2)--(3,-1)--(4,-1)--(4,-2)--(5,-2)--(5,-3)--cycle; - % moon- what a hack! - \filldraw[white] (4,2.5) arc (90:-90:20pt); - \filldraw[black] (3.8,2.5) arc (90:-90:20pt); - % fireworks - \pgfmathparse{100-(\radius-1)*10}; - % red firework - \ifnum\radius<11 - \draw[decorate,decoration={crosses},red!\pgfmathresult!black] (0,0) circle (\radius ex); - \fi - % orange firework - \pgfmathparse{100-(\radius-6)*10}; - \ifnum\radius>5 - \ifnum\radius<16 - \draw[decorate,decoration={crosses},orange!\pgfmathresult!black] (1,1) circle ( \radius ex-5ex); - \fi - \fi - % yellow firework - \pgfmathparse{100-(\radius-11)*10}; - \ifnum\radius>10 - \draw[decorate,decoration={crosses},yellow!\pgfmathresult!black] (2.5,1) circle (\radius ex-10ex); - \fi - \end{tikzpicture} -} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex b/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex deleted file mode 100644 index f4b4bad3e64..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/ifelsefiSmall.tex +++ /dev/null @@ -1,10 +0,0 @@ -\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 deleted file mode 100644 index 29be75d5fdc..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/items1.tex +++ /dev/null @@ -1,10 +0,0 @@ -\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 deleted file mode 100644 index 76d70b95729..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/items2.tex +++ /dev/null @@ -1,21 +0,0 @@ -\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 deleted file mode 100644 index 30460f40e72..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/items3.tex +++ /dev/null @@ -1,22 +0,0 @@ -\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 deleted file mode 100644 index 49383c47e1a..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/items4.tex +++ /dev/null @@ -1,22 +0,0 @@ -\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 deleted file mode 100644 index 79c959e1ba2..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/matrix.tex +++ /dev/null @@ -1,14 +0,0 @@ -% arara: indent: {overwrite: true, trace: true} -\[ - \begin{matrix}[cc|cccccc|c] - & & & & & & {\color{blue}\downarrow} & {\color{blue}\downarrow} & S \\\hline - & 6 & {\color{red}\newmoon} & & & & & & {\color{red}\leftarrow} \\ - {\color{blue}*} & 5 & & & & & & {\color{blue}\newmoon} & \\ - & 4 & & & & {\color{red}\newmoon} & & & {\color{red}\leftarrow} \\ - & 3 & & {\color{red}\newmoon} & & & & & {\color{red}\leftarrow} \\ - & 2 & & & \fullmoon & & & & \\ - {\color{blue}*} & 1 & & & & & {\color{blue}\newmoon} & & \\\hline - & & 1 & 2 & 3 & 4 & 5 & 6 & \\ - \% & & {\color{red}*} & {\color{red}*} & & {\color{red}*} & & & - \end{matrix} -\] diff --git a/Master/texmf-dist/doc/support/latexindent/success/multipleBraces.tex b/Master/texmf-dist/doc/support/latexindent/success/multipleBraces.tex deleted file mode 100644 index 63a2967dab3..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/multipleBraces.tex +++ /dev/null @@ -1,15 +0,0 @@ -% arara: indent: {overwrite: yes, trace: on} -\xapptocmd{\tableofcontents}{% - \end{singlespace}% - \pagestyle{plain}% - \clearpage}{}{} - -\xapptocmd{\tableofcontents}{% - \end{singlespace}% - \pagestyle{plain}% - \clearpage}{}{} - -\xapptocmd{\tableofcontents}{% - \end{singlespace}% - \pagestyle{plain}% - \clearpage}{}{} diff --git a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex b/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex deleted file mode 100644 index 6578b4f4e00..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment.tex +++ /dev/null @@ -1,33 +0,0 @@ -% arara: indent: { overwrite: on, trace: yes} -\begin{tabular}{p{3cm}|c|p{8cm}} - Example & Choice & Why \\ \hline \hline - \( - \left\{ - \begin{array}{rl} - x+y & =6 \\ - 2x+y & =8 - \end{array} - \right. - \) - & 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 - \( - \left\{ - \begin{array}{rl} - 3x-7y & =13 \\ - 6x+5y & =7 - \end{array} - \right. - \) - & Addition & Because there is no obvious way to use substitution \\ \hline - \( - \left\{ - \begin{array}{rl} - x-7y & =13 \\ - 6x+5y & =7 - \end{array} - \right. - \) - & 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 deleted file mode 100644 index 9a19ca8da43..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/nestedalignment1.tex +++ /dev/null @@ -1,25 +0,0 @@ -% arara: indent: { overwrite: on, silent: no, trace: yes} -\begin{tabular}{p{3cm}|c|p{8cm}} - x+y & = & 6 \\ - 2x+y & \&\%=8 % \% & - \%\&\%\% & & \\ % & & 2x+y & =8 - x+y & = & 6 \\ - 2x+y & =8 - 2x+y \&\& & = & 8 % trailine comment -\end{tabular} - -here's another line $\{ x^2 + 5x \}$ -\begin{minipage}{\textwidth} - content - content - content - content - content -\end{minipage}\\[3cm] -\begin{minipage}{\textwidth} - content - content - content - content - content -\end{minipage}\\[3cm] diff --git a/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex b/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex deleted file mode 100644 index aac040a48c7..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/outputfile.tex +++ /dev/null @@ -1,57 +0,0 @@ -% arara: indent: { overwrite: yes} - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - } - }% - %--------------------------------------------------------------------------- -} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - } -}} - -some other text -some other text -some other text - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep -}}} - -some other text -some other text -some other text - - -\hypersetup{% - pdfstartview={% - FitH \hypercalcbp{\paperheight-\topmargin-0in - -\headheight-\headsep - }} -} - -some other text -some other text -some other text - -\parbox{ - \begin{something} - - \end{something} -} - -some other text -some other text -some other text diff --git a/Master/texmf-dist/doc/support/latexindent/success/preamble.tex b/Master/texmf-dist/doc/support/latexindent/success/preamble.tex deleted file mode 100644 index 749e9819c20..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/preamble.tex +++ /dev/null @@ -1,29 +0,0 @@ -% arara: indent: {trace: on, overwrite: yes} -\documentclass[10pt,twoside]{report} -\newenvironment{widepage}{\begin{adjustwidth}{-\offsetpage}{}% - \addtolength{\textwidth}{\offsetpage}}% -{\end{adjustwidth}} - -% Define fix command -% - it puts a comment in the margin -% - it writes to a file with a list of things that need fixing -\newcommand{\fixthis}[1] -{% - \marginpar{\huge \color{red} \framebox{FIX}}% - \typeout{FIXTHIS: p\thepage : #1^^J}% -} - -% Define pccname command -% - it writes to the log file with a detail of the name- -% this is useful for tracking names for diversity purposes -\newcommand{\pccname}[1] -{% - #1% - \typeout{PCCNAME: p\thepage : #1}% -} - -\begin{document} - -some text - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/pstricks1.tex b/Master/texmf-dist/doc/support/latexindent/success/pstricks1.tex deleted file mode 100644 index ff55548b6c7..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/pstricks1.tex +++ /dev/null @@ -1,26 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -\documentclass[pstricks]{standalone} -\usepackage{pstricks,multido} - -\def\Bottle#1{{\pscustom[linewidth=2pt]{% - \rotate{#1} - \psline(-1,3.5)(-1,4)(1,4)(1,3.5) - \pscurve(3,2)(1,0)\psline(-1,0) - \pscurve(-3,2)(-1,3.5)}}} - -\def\BottleWithWater(#1)#2{% - \rput[c]{#2}(#1){% - \rput{*0}(0,0){% - \psclip{\Bottle{#2}} - \psframe*[linecolor=gray](-6,-2)(6,2) - \endpsclip}\rput{*0}(0,0){\Bottle{#2}}}} - -\begin{document} - -\multido{\iA=-45+5}{19}{% - \begin{pspicture}(-2.5,-0.5)(6,5.5) - \BottleWithWater(1.5,1){\iA} - \end{pspicture} -} - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/pstricks2.tex b/Master/texmf-dist/doc/support/latexindent/success/pstricks2.tex deleted file mode 100644 index 7690da820e7..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/pstricks2.tex +++ /dev/null @@ -1,68 +0,0 @@ -% arara: indent: {overwrite: true, trace: true, localSettings: off} -\documentclass[pstricks,border=12pt]{standalone} -\usepackage{pst-eucl} -\usepackage[nomessages]{fp} - -\definecolor{myblue}{RGB}{37,111,197} -\definecolor{mybrown}{RGB}{211,200,134} - -\def\rOne{0.75} -\def\rTwo{0.75} -\def\tOne{20} -\def\tTwo{-45} -\FPset\RowMaxIndex{4}% because zero based index -\FPset\ColMaxIndex{4}% because zero based index - - -\psset -{ - PointName=none, - PointSymbol=none, - fillstyle=solid, - linejoin=1, -} - -\def\Bar(#1,#2)#3{% - \rput(!#2 \rTwo\space mul \tTwo\space PtoC){% - \rput(!#1 \rOne\space mul \tOne\space 180 add PtoC){% - \pstGeonode{O}(\rOne;\tOne){One}(\rTwo;\tTwo){Two} - \pstTranslation{O}{Two}{One}[Three] - \pnode(0,\stripH){O'} - \pstTranslation{O}{O'}{One,Two,Three} - \pnode(0,#3){O''} - \pstTranslation{O}{O''}{One,Two,Three}[One'',Two'',Three''] - \psset{fillcolor=mybrown} - \pspolygon(O'')(O)(Two)(Two'') - \pspolygon(Two'')(Two)(Three)(Three'') - \pspolygon(One'')(O'')(Two'')(Three'') - \psset{fillcolor=myblue,opacity=0.75,linestyle=none,linewidth=0} - \FPifeq{#1}{\RowMaxIndex}\pspolygon(O')(O)(Two)(Two')\fi - \FPifeq{#2}{\ColMaxIndex}\pspolygon(Two')(Two)(Three)(Three')\fi - \FPiflt{#3}{\stripH}\pspolygon(One')(O')(Two')(Three')\fi - }% - }% -} - -\newcount\OuterIndex -\def\SaveListContents#1\relax{\def\Contents{#1}} - -\def\Picture#1{% - \def\stripH{#1}% - \begin{pspicture}[showgrid=false](-2.5,-3.35)(3.05,3.05) - \psforeach{\row}{% - {{3,2.8,2.7,3,3.1}},% <=== Only this row must use double curly braces. It is a feature! - {2.8,1,1.2,2,3},% - {2.8,1,1.2,2,2.8},% - {2.6,1.6,1.8,1.9,1.8},% - {2.4,1.5,1.7,1.9,1.5}% - }{% - \expandafter\SaveListContents\row\relax - \OuterIndex=\psLoopIndex\relax - \psforeach{\col}{\Contents}{\Bar(\the\OuterIndex,\the\psLoopIndex){\col}}% - \psLoopIndex=\OuterIndex\relax - } - \end{pspicture}} - -\begin{document} -\multido{\n=0.0+0.2}{17}{\Picture{\n}} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/pstricks3.tex b/Master/texmf-dist/doc/support/latexindent/success/pstricks3.tex deleted file mode 100644 index 09c132f5c73..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/pstricks3.tex +++ /dev/null @@ -1,49 +0,0 @@ -% arara: indent: {overwrite: yes} -\documentclass[pstricks,border=12pt]{standalone} -\usepackage{pst-node} -\addtopsstyle{gridstyle}{gridlabels=0pt,strokeopacity=.25} - -\begin{document} -\begin{pspicture}[showgrid=top](8,8) - \multips(0,.5)(0,1){8}{% - \multips(.5,0)(1,0){8}{% - \psline[linecolor=red](6pt;-135)(6pt;45) - \psline[linecolor=red](6pt;135)(6pt;-45)}} - \pscustom - [ - dimen=middle, - fillstyle=eovlines*, - fillcolor=white, - hatchcolor=blue, - linecolor=blue, - ] - { - \psframe(8,8) - \pspolygon - (3,1) - (3,4) - (1,4) - (1,6) - (2,6) - (2,7) - (7,7) - (7,4) - (6,4) - (6,6) - (5,6) - (5,4) - (6,4) - (6,3) - (7,3) - (7,1) - (6,1) - (6,2) - (5,2) - (5,1) - } - \psset{linecolor=blue,nodesep=7pt} - \pscircle*(4,2){2pt} - \pscircle*(4,3){2pt} - \pcline(4,2)(4,3) -\end{pspicture} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex b/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex deleted file mode 100644 index b1f37474fe0..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/sampleAFTER.tex +++ /dev/null @@ -1,5819 +0,0 @@ -% arara: indent: {overwrite: yes} -% A sample chapter file- it contains a lot of -% environments, including tabulars, align, etc -% -% Don't try and compile this file using pdflatex etc, just -% compare the *format* of it to the format of the -% sampleAFTER.tex -% -% In particular, compare the tabular and align-type -% environments before and after running the script - -\section{Polynomial functions} - \reformatstepslist{P} % the steps list should be P1, P2, \ldots - In your previous mathematics classes you have studied \emph{linear} and - \emph{quadratic} functions. The most general forms of these types of - functions can be represented (respectively) by the functions $f$ - and $g$ that have formulas - \begin{equation}\label{poly:eq:linquad} - f(x)=mx+b, \qquad g(x)=ax^2+bx+c - \end{equation} - We know that $m$ is the slope of $f$, and that $a$ is the \emph{leading coefficient} - of $g$. We also know that the \emph{signs} of $m$ and $a$ completely - determine the behavior of the functions $f$ and $g$. For example, if $m>0$ - then $f$ is an \emph{increasing} function, and if $m<0$ then $f$ is - 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} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$m>0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{-(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$m<0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a>0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{-(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a<0$} - \end{subfigure} - \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 - %=================================== - \begin{essentialskills} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Quadratic functions] - Every quadratic function has the form $y=ax^2+bx+c$; state the value - of $a$ for each of the following functions, and hence decide if the - parabola that represents the function opens upward or downward. - \begin{multicols}{2} - \begin{subproblem} - $F(x)=x^2+3$ - \begin{shortsolution} - $a=1$; the parabola opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $G(t)=4-5t^2$ - \begin{shortsolution} - $a=-5$; the parabola opens downward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $H(y)=4y^2-96y+8$ - \begin{shortsolution} - $a=4$; the parabola opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $K(z)=-19z^2$ - \begin{shortsolution} - $m=-19$; the parabola opens downward. - \end{shortsolution} - \end{subproblem} - \end{multicols} - Now let's generalize our findings for the most general quadratic function $g$ - that has formula $g(x)=a_2x^2+a_1x+a_0$. Complete the following sentences. - \begin{subproblem} - When $a_2>0$, the parabola that represents $y=g(x)$ opens $\ldots$ - \begin{shortsolution} - When $a_2>0$, the parabola that represents the function opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - When $a_2<0$, the parabola that represents $y=g(x)$ opens $\ldots$ - \begin{shortsolution} - When $a_2<0$, the parabola that represents the function opens downward. - \end{shortsolution} - \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? - \begin{pccdefinition}[Power functions] - Power functions have the form - \[ - 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 - %=================================== - \begin{pccexample}[Power functions with odd positive exponents] - \label{poly:ex:oddpow} - Graph each of the following functions, state their domain, and their - long-run behavior as $x\rightarrow\pm\infty$ - \[ - f(x)=x^3, \qquad g(x)=x^5, \qquad h(x)=x^7 - \] - \begin{pccsolution} - The functions $f$, $g$, and $h$ are plotted in \cref{poly:fig:oddpow}. - The domain of each of the functions $f$, $g$, and $h$ is $(-\infty,\infty)$. Note that - 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 - \end{align*} - The same results hold for $g$ and $h$. - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htb] - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-1.5,xmax=1.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,1.0}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\textwidth, - legend pos=north west, - ] - \addplot expression[domain=-1.5:1.5]{x^3}; - \addplot expression[domain=-1.379:1.379]{x^5}; - \addplot expression[domain=-1.258:1.258]{x^7}; - \addplot[soldot]coordinates{(-1,-1)} node[axisnode,anchor=north west]{$(-1,-1)$}; - \addplot[soldot]coordinates{(1,1)} node[axisnode,anchor=south east]{$(1,1)$}; - \legend{$f$,$g$,$h$} - \end{axis} - \end{tikzpicture} - \caption{Odd power functions} - \label{poly:fig:oddpow} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-2.5,xmax=2.5, - ymin=-5,ymax=5, - xtick={-2.0,-1.5,...,2.0}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\textwidth, - legend pos=south east, - ] - \addplot expression[domain=-2.236:2.236]{x^2}; - \addplot expression[domain=-1.495:1.495]{x^4}; - \addplot expression[domain=-1.307:1.307]{x^6}; - \addplot[soldot]coordinates{(-1,1)} node[axisnode,anchor=east]{$(-1,1)$}; - \addplot[soldot]coordinates{(1,1)} node[axisnode,anchor=west]{$(1,1)$}; - \legend{$F$,$G$,$H$} - \end{axis} - \end{tikzpicture} - \caption{Even power functions} - \label{poly:fig:evenpow} - \end{minipage}% - \end{figure} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Power functions with even positive exponents]\label{poly:ex:evenpow}% - Graph each of the following functions, state their domain, and their - long-run behavior as $x\rightarrow\pm\infty$ - \[ - F(x)=x^2, \qquad G(x)=x^4, \qquad H(x)=x^6 - \] - \begin{pccsolution} - The functions $F$, $G$, and $H$ are plotted in \cref{poly:fig:evenpow}. The domain - of each of the functions is $(-\infty,\infty)$. Note that 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 - \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) - \begin{subproblem} - $f(x)=-x^3, \qquad g(x)=-x^5, \qquad h(x)=-x^7$ - \begin{shortsolution} - The functions $f$, $g$, and $h$ have domain $(-\infty,\infty)$ and - are graphed below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-1.5,xmax=1.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,0.5}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - legend pos=north east, - ] - \addplot expression[domain=-1.5:1.5]{-x^3}; - \addplot expression[domain=-1.379:1.379]{-x^5}; - \addplot expression[domain=-1.258:1.258]{-x^7}; - \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 - \end{align*} - The same is true for $g$ and $h$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $F(x)=-x^2, \qquad G(x)=-x^4, \qquad H(x)=-x^6$ - \begin{shortsolution} - The functions $F$, $G$, and $H$ have domain $(-\infty,\infty)$ and - are graphed below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-2.5,xmax=2.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,0.5}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - legend pos=north east, - ] - \addplot expression[domain=-2.236:2.236]{-x^2}; - \addplot expression[domain=-1.495:1.495]{-x^4}; - \addplot expression[domain=-1.307:1.307]{-x^6}; - \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 - \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 - with our opening discussion about linear and quadratic functions (see - $f$ and $g$ in \cref{poly:eq:linquad}) then there is every chance - that you'll be able to master polynomial functions as well; just remember - that polynomial functions are a natural generalization of linear - 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 - %=================================== - \begin{pccdefinition}[Polynomial functions] - Polynomial functions have the form - \[ - p(x)=a_nx^n+a_{n-1}x^{n-1}+\ldots+a_1x+a_0 - \] - where $a_n$, $a_{n-1}$, $a_{n-2}$, \ldots, $a_0$ are real numbers. - \begin{itemize} - \item We call $n$ the degree of the polynomial, and require that $n$ - is a non-negative integer; - \item $a_n$, $a_{n-1}$, $a_{n-2}$, \ldots, $a_0$ are called the coefficients; - \item We typically write polynomial functions in descending powers of $x$. - \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 - %=================================== - \begin{pccexample}[Polynomial or not] - Identify the following functions as polynomial or not; if the function - is a polynomial, state its degree. - \begin{multicols}{3} - \begin{enumerate} - \item $p(x)=x^2-3$ - \item $q(x)=-4x^{\nicefrac{1}{2}}+10$ - \item $r(x)=10x^5$ - \item $s(x)=x^{-2}+x^{23}$ - \item $f(x)=-8$ - \item $g(x)=3^x$ - \item $h(x)=\sqrt[3]{x^7}-x^2+x$ - \item $k(x)=4x(x+2)(x-3)$ - \item $j(x)=x^2(x-4)(5-x)$ - \end{enumerate} - \end{multicols} - \begin{pccsolution} - \begin{enumerate} - \item $p$ is a polynomial, and its degree is $2$. - \item $q$ is \emph{not} a polynomial, because $\frac{1}{2}$ is not an integer. - \item $r$ is a polynomial, and its degree is $5$. - \item $s$ is \emph{not} a polynomial, because $-2$ is not a positive integer. - \item $f$ is a polynomial, and its degree is $0$. - \item $g$ is \emph{not} a polynomial, because the independent - variable, $x$, is in the exponent. - \item $h$ is \emph{not} a polynomial, because $\frac{7}{3}$ is not an integer. - \item $k$ is a polynomial, and its degree is $3$. - \item $j$ is a polynomial, and its degree is $4$. - \end{enumerate} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Typical graphs]\label{poly:ex:typical} - \Cref{poly:fig:typical} shows graphs of some polynomial functions; - the ticks have deliberately been left off the axis to allow us to concentrate - on the features of each graph. Note in particular that: - \begin{itemize} - \item \cref{poly:fig:typical1} shows a degree-$1$ polynomial (you might also - classify the function as linear) whose leading coefficient, $a_1$, is positive. - \item \cref{poly:fig:typical2} shows a degree-$2$ polynomial (you might also - classify the function as quadratic) whose leading coefficient, $a_2$, is positive. - \item \cref{poly:fig:typical3} shows a degree-$3$ polynomial whose leading coefficient, $a_3$, - is positive| compare its overall - shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. - \item \cref{poly:fig:typical4} shows a degree-$4$ polynomial whose leading coefficient, $a_4$, - is positive|compare its overall shape and long-run behavior to the functions described in \cref{poly:ex:evenpow}. - \item \cref{poly:fig:typical5} shows a degree-$5$ polynomial whose leading coefficient, $a_5$, - is positive| compare its overall - shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. - \end{itemize} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{\textwidth/6} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$a_1>0$} - \label{poly:fig:typical1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_2>0$} - \label{poly:fig:typical2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-7.5:7.5]{0.05*(x+6)*x*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_3>0$} - \label{poly:fig:typical3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-2.35:5.35,samples=100]{0.2*(x-5)*x*(x-3)*(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$a_4>0$} - \label{poly:fig:typical4} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-5.5:6.3,samples=100]{0.01*(x+2)*x*(x-3)*(x+5)*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_5>0$} - \label{poly:fig:typical5} - \end{subfigure} - \end{widepage} - \caption{Graphs to illustrate typical curves of polynomial functions.} - \label{poly:fig:typical} - \end{figure} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{doyouunderstand} - \begin{problem} - Use \cref{poly:ex:typical} and \cref{poly:fig:typical} to help you sketch - the graphs of polynomial functions that have negative leading coefficients| note - that there are many ways to do this! The intention with this problem - is to use your knowledge of transformations- in particular, \emph{reflections}- - to guide you. - \begin{shortsolution} - $a_1<0$: - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{-(x+2)}; - \end{axis} - \end{tikzpicture} - - $a_2<0$ - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{-(x^2-6)}; - \end{axis} - \end{tikzpicture} - - $a_3<0$ - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \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, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \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, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-5.5:6.3,samples=100]{-0.01*(x+2)*x*(x-3)*(x+5)*(x-6)}; - \end{axis} - \end{tikzpicture} - \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 - %=================================== - \begin{pccexample}[Multiple zeros] - Consider the polynomial functions $p$, $q$, and $r$ which are - graphed in \cref{poly:fig:moremultiple}. - The formulas for $p$, $q$, and $r$ are as follows - \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 - \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} - \begin{tikzpicture} - \begin{axis}[ - xmin=-6,xmax=5, - ymin=-30,ymax=200, - xtick={-4,-2,...,4}, - width=\textwidth, - ] - \addplot expression[domain=-5.63733:4.63733,samples=50]{(x-3)^2*(x+4)^2}; - \addplot[soldot]coordinates{(3,0)(-4,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=p(x)$} - \label{poly:fig:bouncep} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-3,xmax=4, - xtick={-2,...,3}, - ymin=-60,ymax=40, - width=\textwidth, - ] - \addplot+[samples=50] expression[domain=-2.49011:3.11054]{x*(x+2)^2*(x-1)^2*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(0,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=q(x)$} - \label{poly:fig:bounceq} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-2,xmax=4, - xtick={-1,...,3}, - ymin=-40,ymax=40, - width=\textwidth, - ] - \addplot expression[domain=-1.53024:3.77464,samples=50]{x*(x-3)^3*(x+1)^2}; - \addplot[soldot]coordinates{(-1,0)(0,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=r(x)$} - \label{poly:fig:bouncer} - \end{subfigure} - \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 - \begin{itemize} - \item if the factor $(x-a)$ is repeated an even number of times, the graph of $y=p(x)$ does not - cross the $x$ axis at $a$, but `bounces' off the horizontal axis at $a$. - \item if the factor $(x-a)$ is repeated an odd number of times, the graph of $y=p(x)$ crosses the - horizontal axis at $a$, but it looks `flattened' there - \end{itemize} - If $n=1$, then we say that $p$ has a \emph{simple} zero at $a$. - \end{pccdefinition} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{pccexample}[Find a formula] - Find formulas for the polynomial functions, $p$ and $q$, graphed in \cref{poly:fig:findformulademoboth}. - \begin{figure}[!htb] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - minor xtick={-3,-1,...,3}, - ytick={-8,-6,...,8}, - width=\textwidth, - grid=both] - \addplot expression[domain=-3.25842:2.25842,samples=50]{-x*(x-2)*(x+3)*(x+1)}; - \addplot[soldot]coordinates{(1,8)}node[axisnode,inner sep=.35cm,anchor=west]{$(1,8)$}; - \addplot[soldot]coordinates{(-3,0)(-1,0)(0,0)(2,0)}; - \end{axis} - \end{tikzpicture} - \caption{$p$} - \label{poly:fig:findformulademo} - \end{subfigure} - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - minor xtick={-3,-1,...,3}, - ytick={-8,-6,...,8}, - width=\textwidth, - grid=both] - \addplot expression[domain=-4.33:4.08152]{-.25*(x+2)^2*(x-3)}; - \addplot[soldot]coordinates{(2,4)}node[axisnode,anchor=south west]{$(2,4)$}; - \addplot[soldot]coordinates{(-2,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$q$} - \label{poly:fig:findformulademo1} - \end{subfigure} - \caption{} - \label{poly:fig:findformulademoboth} - \end{figure} - \begin{pccsolution} - \begin{enumerate} - \item We begin by noting that the horizontal intercepts of $p$ are $(-3,0)$, $(-1,0)$, $(0,0)$ and $(2,0)$. - We also note that each zero is simple (multiplicity $1$). - If we assume that $p$ has no other zeros, then we can start by writing - \begin{align*} - p(x) & =(x+3)(x+1)(x-0)(x-2) \\ - & =x(x+3)(x+1)(x-2) \\ - \end{align*} - According to \cref{poly:fig:findformulademo}, the point $(1,8)$ lies - on the curve $y=p(x)$. - Let's check if the formula we have written satisfies this requirement - \begin{align*} - p(1) & = (1)(4)(2)(-1) \\ - & = -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 - \[ - p(x)=kx(x+3)(x+1)(x-2) - \] - Then $p(1)=-8k$, and if this is to equal $8$, then $k=-1$. Therefore - the formula for $p(x)$ is - \[ - p(x)=-x(x+3)(x+1)(x-2) - \] - \item The function $q$ has a zero at $-2$ of multiplicity $2$, and zero of - multiplicity $1$ at $3$ (so $3$ is a simple zero of $q$); we can therefore assume that $q$ has the form - \[ - q(x)=k(x+2)^2(x-3) - \] - where $k$ is some real number. In order to find $k$, we use the given ordered pair, $(2,4)$, and - evaluate $p(2)$ - \begin{align*} - p(2) & =k(4)^2(-1) \\ - & =-16k - \end{align*} - We solve the equation $4=-8k$ and obtain $k=-\frac{1}{4}$ and conclude that the - formula for $q(x)$ is - \[ - q(x)=-\frac{1}{4}(x+2)^2(x-3) - \] - \end{enumerate} - \end{pccsolution} - \end{pccexample} - - - \fixthis{Chris: need sketching polynomial problems} - \begin{pccspecialcomment}[Steps to follow when sketching polynomial functions] - \begin{steps} - \item \label{poly:step:first} Determine the degree of the polynomial, - its leading term and leading coefficient, and hence determine - the long-run behavior of the polynomial| does it behave like $\pm x^2$ or $\pm x^3$ - as $x\rightarrow\pm\infty$? - \item Determine the zeros and their multiplicity. Mark all zeros - and the vertical intercept on the graph using solid circles $\bullet$. - \item \label{poly:step:last} Deduce the overall shape of the curve, and sketch it. If there isn't - enough information from the previous steps, then construct a table of values. - \end{steps} - Remember that until we have the tools of calculus, we won't be able to - find the exact coordinates of local minimums, local maximums, and points - of inflection. - \end{pccspecialcomment} - Before we demonstrate some examples, it is important to remember the following: - \begin{itemize} - \item our sketches will give a good representation of the overall - shape of the graph, but until we have the tools of calculus (from MTH 251) - we can not find local minimums, local maximums, and inflection points algebraically. This - means that we will make our best guess as to where these points are. - \item we will not concern ourselves too much with the vertical scale (because of - our previous point)| we will, however, mark the vertical intercept (assuming there is one), - and any horizontal asymptotes. - \end{itemize} - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{poly:ex:simplecubic} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $p$ - that has formula - \[ - p(x)=\frac{1}{2}(x-4)(x-1)(x+3) - \] - \begin{pccsolution} - \begin{steps} - \item $p$ has degree $3$. The leading term of $p$ is $\frac{1}{2}x^3$, so the leading coefficient of $p$ - is $\frac{1}{2}$. The long-run behavior of $p$ is therefore similar to that of $x^3$. - \item The zeros of $p$ are $-3$, $1$, and $4$; each zero is simple (i.e, it has multiplicity $1$). - This means that the curve of $p$ cuts the horizontal axis at each zero. The vertical - intercept of $p$ is $(0,6)$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=15, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(1,0)(4,0)(0,6)}node[axisnode,anchor=south west]{$(0,6)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:simplecubicp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=15, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(1,0)(4,0)(0,6)}node[axisnode,anchor=south west]{$(0,6)$}; - \addplot[pccplot] expression[domain=-3.57675:4.95392,samples=100]{.5*(x-4)*(x-1)*(x+3)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:simplecubicp2} - \end{subfigure}% - \caption{$y=\dfrac{1}{2}(x-4)(x-1)(x+3)$} - \label{poly:fig:simplecubic} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{poly:ex:degree5} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $q$ - that has formula - \[ - q(x)=\frac{1}{200}(x+7)^2(2-x)(x-6)^2 - \] - \begin{pccsolution} - \begin{steps} - \item $q$ has degree $4$. The leading term of $q$ is - \[ - -\frac{1}{200}x^5 - \] - so the leading coefficient of $q$ is $-\frac{1}{200}$. The long-run behavior of $q$ - is therefore similar to that of $-x^5$. - \item The zeros of $q$ are $-7$ (multiplicity 2), $2$ (simple), and $6$ (multiplicity $2$). - The curve of $q$ bounces off the horizontal axis at the zeros with multiplicity $2$ and - cuts the horizontal axis at the simple zeros. The vertical intercept of $q$ is $\left( 0,\frac{441}{25} \right)$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=40, - xtick={-8,-6,...,8}, - ytick={-5,0,...,35}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-7,0)(2,0)(6,0)(0,441/25)}node[axisnode,anchor=south west]{$\left( 0, \frac{441}{25} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree5p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=40, - xtick={-8,-6,...,8}, - ytick={-5,0,...,35}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-7,0)(2,0)(6,0)(0,441/25)}node[axisnode,anchor=south west]{$\left( 0, \frac{441}{25} \right)$}; - \addplot[pccplot] expression[domain=-8.83223:7.34784,samples=50]{1/200*(x+7)^2*(2-x)*(x-6)^2}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree5p2} - \end{subfigure}% - \caption{$y=\dfrac{1}{200}(x+7)^2(2-x)(x-6)^2$} - \label{poly:fig:degree5} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $r$ - that has formula - \[ - r(x)=\frac{1}{100}x^3(x+4)(x-4)(x-6) - \] - \begin{pccsolution} - \begin{steps} - \item $r$ has degree $6$. The leading term of $r$ is - \[ - \frac{1}{100}x^6 - \] - so the leading coefficient of $r$ is $\frac{1}{100}$. The long-run behavior of $r$ - is therefore similar to that of $x^6$. - \item The zeros of $r$ are $-4$ (simple), $0$ (multiplicity $3$), $4$ (simple), - and $6$ (simple). The vertical intercept of $r$ is $(0,0)$. The curve of $r$ - cuts the horizontal axis at the simple zeros, and goes through the axis - at $(0,0)$, but does so in a flattened way. - \item We mark the zeros and vertical intercept on \cref{poly:fig:degree6p1}. Given that - 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} - \begin{axis}[ - xmin=-5,xmax=10, - ymin=-20,ymax=10, - xtick={-4,-2,...,8}, - ytick={-15,-10,...,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,0)(4,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree6p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=10, - ymin=-20,ymax=10, - xtick={-4,-2,...,8}, - ytick={-15,-10,...,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,0)(4,0)(6,0)}; - \addplot[pccplot] expression[domain=-4.16652:6.18911,samples=100]{1/100*(x+4)*x^3*(x-4)*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree6p2} - \end{subfigure}% - \caption{$y=\dfrac{1}{100}(x+4)x^3(x-4)(x-6)$} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[An open-topped box] - A cardboard company makes open-topped boxes for their clients. The specifications - dictate that the box must have a square base, and that it must be open-topped. - The company uses sheets of cardboard that are $\unit[1200]{cm^2}$. Assuming that - the base of each box has side $x$ (measured in cm), it can be shown that the volume of each box, $V(x)$, - has formula - \[ - V(x)=\frac{x}{4}(1200-x^2) - \] - Find the dimensions of the box that maximize the volume. - \begin{pccsolution} - We graph $y=V(x)$ in \cref{poly:fig:opentoppedbox}. Note that because - $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} - \begin{axis}[framed, - xmin=-50,xmax=50, - ymin=-5000,ymax=5000, - xtick={-40,-30,...,40}, - minor xtick={-45,-35,...,45}, - minor ytick={-3000,-1000,1000,3000}, - width=.75\textwidth, - height=.5\textwidth, - grid=both] - \addplot[pccplot,dashed,<-] expression[domain=-40:0,samples=50]{x/4*(1200-x^2)}; - \addplot[pccplot,-] expression[domain=0:34.64,samples=50]{x/4*(1200-x^2)}; - \addplot[pccplot,dashed,->] expression[domain=34.64:40,samples=50]{x/4*(1200-x^2)}; - \addplot[soldot] coordinates{(20,4000)}; - \end{axis} - \end{tikzpicture} - \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. - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample}\label{poly:ex:complx} - Consider the polynomial function $c$ that has formula - \[ - c(x)=x(x^2+1) - \] - It is clear that $c$ has degree $3$, and that $c$ has a (simple) zero at $0$. Does - $c$ have any other zeros, i.e, can we find any values of $x$ that satisfy the equation - \begin{equation}\label{poly:eq:complx} - 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} - \Cref{poly:ex:complx} shows that not every degree-$3$ polynomial has $3$ - \emph{real} zeros; however, if we are prepared to venture into the complex numbers, - then we can state the following theorem. - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccspecialcomment}[The fundamental theorem of algebra] - Every polynomial function of degree $n$ has $n$ roots, some of which may - be complex, and some may be repeated. - \end{pccspecialcomment} - \fixthis{Fundamental theorem of algebra: is this wording ok? do we want - it as a theorem?} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample} - Find all the zeros of the polynomial function $p$ that has formula - \[ - p(x)=x^4-2x^3+5x^2 - \] - \begin{pccsolution} - We begin by factoring $p$ - \begin{align*} - p(x) & =x^4-2x^3+5x^2 \\ - & =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 - \[ - x^2-2x+5=0 - \] - This equation can not be factored, so we use the quadratic formula - \begin{align*} - x & =\frac{2\pm\sqrt{(-2)^2}-20}{2(1)} \\ - & =\frac{2\pm\sqrt{-16}}{2} \\ - & =1\pm 2i - \end{align*} - We conclude that $p$ has $4$ zeros: $0$ (multiplicity $2$), and $1\pm 2i$ (simple). - \end{pccsolution} - \end{pccexample} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample} - Find a polynomial that has zeros at $2\pm i\sqrt{2}$. - \begin{pccsolution} - 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 - \end{align*} - We conclude that a possible formula for a polynomial function, $p$, - that has zeros at $2\pm i\sqrt{2}$ is - \[ - p(x)=x^2-4x+6 - \] - Note that we could multiply $p$ by any real number and still ensure - that $p$ has the same zeros. - \end{pccsolution} - \end{pccexample} - \investigation*{} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a graph] - For each of the polynomials in \cref{poly:fig:findformula} - \begin{enumerate} - \item count the number of times the curve turns round, and cuts/bounces off the $x$ axis; - \item approximate the degree of the polynomial; - \item use your information to find the linear factors of each polynomial, and therefore write a possible formula for each; - \item make sure your polynomial goes through the given ordered pair. - \end{enumerate} - \begin{shortsolution} - \Vref{poly:fig:findformdeg2}: - \begin{enumerate} - \item the curve turns round once; - \item the degree could be 2; - \item based on the zeros, the linear factors are $(x+5)$ and $(x-3)$; since the - graph opens downwards, we will assume the leading coefficient is negative: $p(x)=-k(x+5)(x-3)$; - \item $p$ goes through $(2,2)$, so we need to solve $2=-k(7)(-1)$ and therefore $k=\nicefrac{2}{7}$, so - \[ - p(x)=-\frac{2}{7}(x+5)(x-3) - \] - \end{enumerate} - \Vref{poly:fig:findformdeg3}: - \begin{enumerate} - \item the curve turns around twice; - \item the degree could be 3; - \item based on the zeros, the linear factors are $(x+2)^2$, and $(x-1)$; - based on the behavior of $p$, we assume that the leading coefficient is positive, and try $p(x)=k(x+2)^2(x-1)$; - \item $p$ goes through $(0,-2)$, so we need to solve $-2=k(4)(-1)$ and therefore $k=\nicefrac{1}{2}$, so - \[ - p(x)=\frac{1}{2}(x+2)^2(x-1) - \] - \end{enumerate} - \Vref{poly:fig:findformdeg5}: - \begin{enumerate} - \item the curve turns around 4 times; - \item the degree could be 5; - \item based on the zeros, the linear factors are $(x+5)^2$, $(x+1)$, $(x-2)$, $(x-3)$; - based on the behavior of $p$, we assume that the leading coefficient is positive, and try $p(x)=k(x+5)^2(x+1)(x-2)(x-3)$; - \item $p$ goes through $(-3,-50)$, so we need to solve $-50=k(64)(-2)(-5)(-6)$ and therefore $k=\nicefrac{5}{384}$, so - \[ - p(x)=\frac{5}{384}(x+5)^2(x+1)(x-2)(x-3) - \] - \end{enumerate} - \end{shortsolution} - \end{problem} - - - \begin{figure}[!htb] - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-2,ymax=5, - width=\textwidth, - ] - \addplot expression[domain=-4.5:3.75]{-1/3*(x+4)*(x-3)}; - \addplot[soldot] coordinates{(-4,0)(3,0)(2,2)} node[axisnode,above right]{$(2,2)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-3,xmax=2, - ymin=-2,ymax=4, - xtick={-2,...,1}, - width=\textwidth, - ] - \addplot expression[domain=-2.95:1.75]{1/3*(x+2)^2*(x-1)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(0,-1.33)}node[axisnode,anchor=north west]{$(0,-2)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-100,ymax=150, - width=\textwidth, - ] - \addplot expression[domain=-4.5:3.4,samples=50]{(x+4)^2*(x+1)*(x-2)*(x-3)}; - \addplot[soldot]coordinates{(-4,0)(-1,0)(2,0)(3,0)(-3,-60)}node[axisnode,anchor=north]{$(-3,-50)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg5} - \end{subfigure} - \caption{} - \label{poly:fig:findformula} - \end{figure} - - - - - \begin{exercises} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Prerequisite classifacation skills] - Decide if each of the following functions are linear or quadratic. - \begin{multicols}{3} - \begin{subproblem} - $f(x)=2x+3$ - \begin{shortsolution} - $f$ is linear. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x)=10-7x$ - \begin{shortsolution} - $g$ is linear - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x)=-x^2+3x-9$ - \begin{shortsolution} - $h$ is quadratic. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x)=-17$ - \begin{shortsolution} - $k$ is linear. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(x)=-82x^2-4$ - \begin{shortsolution} - $l$ is quadratic - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(x)=6^2x-8$ - \begin{shortsolution} - $m$ is linear. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Prerequisite slope identification] - State the slope of each of the following linear functions, and - hence decide if each function is increasing or decreasing. - \begin{multicols}{4} - \begin{subproblem} - $\alpha(x)=4x+1$ - \begin{shortsolution} - $m=4$; $\alpha$ is increasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\beta(x)=-9x$ - \begin{shortsolution} - $m=-9$; $\beta$ is decreasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\gamma(t)=18t+100$ - \begin{shortsolution} - $m=18$; $\gamma$ is increasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\delta(y)=23-y$ - \begin{shortsolution} - $m=-1$; $\delta$ is decreasing. - \end{shortsolution} - \end{subproblem} - \end{multicols} - Now let's generalize our findings for the most general linear function $f$ - that has formula $f(x)=mx+b$. Complete the following sentences. - \begin{subproblem} - When $m>0$, the function $f$ is $\ldots$ - \begin{shortsolution} - When $m>0$, the function $f$ is $\ldots$ \emph{increasing}. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - When $m<0$, the function $f$ is $\ldots$ - \begin{shortsolution} - When $m<0$, the function $f$ is $\ldots$ \emph{decreasing}. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Polynomial or not?] - Identify whether each of the following functions is a polynomial or not. - If the function is a polynomial, state its degree. - \begin{multicols}{3} - \begin{subproblem} - $p(x)=2x+1$ - \begin{shortsolution} - $p$ is a polynomial (you might also describe $p$ as linear). The degree of $p$ is 1. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=7x^2+4x$ - \begin{shortsolution} - $p$ is a polynomial (you might also describe $p$ as quadratic). The degree of $p$ is 2. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=\sqrt{x}+2x+1$ - \begin{shortsolution} - $p$ is not a polynomial; we require the powers of $x$ to be integer values. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=2^x-45$ - \begin{shortsolution} - $p$ is not a polynomial; the $2^x$ term is exponential. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=6x^4-5x^3+9$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $6$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=-5x^{17}+9x+2$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is 17. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=4x(x+7)^2(x-3)^3$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $6$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=4x^{-5}-x^2+x$ - \begin{shortsolution} - $p$ is not a polynomial because $-5$ is not a positive integer. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=-x^6(x^2+1)(x^3-2)$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $11$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Polynomial graphs] - Three polynomial functions $p$, $m$, and $n$ are shown in \crefrange{poly:fig:functionp}{poly:fig:functionn}. - The functions have the following formulas - \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) - \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, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{(x-1)*(x+2)*(x-3)}; - \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, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{-1*(x-1)*(x+2)*(x-3)}; - \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, - ymin=-90,ymax=70, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-4.15:3.15,samples=50]{(x-1)*(x+2)*(x-3)*(x+1)*(x+4)}; - \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} - \end{subproblem} - \begin{subproblem} - Write down the degree, how many times the curve of each function `turns around', - and how many zeros it has - \begin{shortsolution} - \begin{itemize} - \item The degree of $p$ is 3, and the curve $y=p(x)$ turns around twice. - \item The degree of $q$ is also 3, and the curve $y=q(x)$ turns around twice. - \item The degree of $n$ is $5$, and the curve $y=n(x)$ turns around 4 times. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-10,ymax=10, - ytick={-5,5}, - width=\textwidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{(x-1)*(x+2)*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=p(x)$} - \label{poly:fig:functionp} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-10,ymax=10, - ytick={-5,5}, - width=\textwidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{-1*(x-1)*(x+2)*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=m(x)$} - \label{poly:fig:functionm} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-90,ymax=70, - width=\textwidth, - ] - \addplot expression[domain=-4.15:3.15,samples=100]{(x-1)*(x+2)*(x-3)*(x+1)*(x+4)}; - \addplot[soldot]coordinates{(-4,0)(-2,0)(-1,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=n(x)$} - \label{poly:fig:functionn} - \end{subfigure} - \caption{} - \end{widepage} - \end{figure} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Horizontal intercepts]\label{poly:prob:matchpolys}% - State the horizontal intercepts (as ordered pairs) of the following polynomials. - \begin{multicols}{2} - \begin{subproblem}\label{poly:prob:degree5} - $p(x)=(x-1)(x+2)(x-3)(x+1)(x+4)$ - \begin{shortsolution} - $(-4,0)$, $(-2,0)$, $(-1,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(x)=-(x-1)(x+2)(x-3)$ - \begin{shortsolution} - $(-2,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(x)=(x-1)(x+2)(x-3)$ - \begin{shortsolution} - $(-2,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{poly:prob:degree2} - $s(x)=(x-2)(x+2)$ - \begin{shortsolution} - $(-2,0)$, $(2,0)$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Minimums, maximums, and concavity]\label{poly:prob:incdec} - Four polynomial functions are graphed in \cref{poly:fig:incdec}. The formulas - for these functions are (not respectively) - \begin{gather*} - p(x)=\frac{x^3}{6}-\frac{x^2}{4}-3x, \qquad q(x)=\frac{x^4}{20}+\frac{x^3}{15}-\frac{6}{5}x^2+1\\ - r(x)=-\frac{x^5}{50}-\frac{x^4}{40}+\frac{2x^3}{5}+6, \qquad s(x)=-\frac{x^6}{6000}-\frac{x^5}{2500}+\frac{67x^4}{4000}+\frac{17x^3}{750}-\frac{42x^2}{125} - \end{gather*} - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{.23\textwidth} - \centering - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=major, - ] - \addplot expression[domain=-5.28:4.68,samples=50]{-x^5/50-x^4/40+2*x^3/5+6}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10,ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=major, - ] - \addplot expression[domain=-6.08:4.967,samples=50]{x^4/20+x^3/15-6/5*x^2+1}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-6,xmax=8,ymin=-10,ymax=10, - xtick={-4,-2,...,6}, - ytick={-8,-4,4,8}, - minor ytick={-6,-2,...,6}, - grid=both, - ] - \addplot expression[domain=-4.818:6.081,samples=50]{x^3/6-x^2/4-3*x}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10,ymin=-10,ymax=10, - xtick={-8,-4,4,8}, - ytick={-8,-4,4,8}, - minor xtick={-6,-2,...,6}, - minor ytick={-6,-2,...,6}, - grid=both, - ] - \addplot expression[domain=-9.77:8.866,samples=50]{-x^6/6000-x^5/2500+67*x^4/4000+17/750*x^3-42/125*x^2}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec4} - \end{subfigure} - \caption{Graphs for \cref{poly:prob:incdec}.} - \label{poly:fig:incdec} - \end{widepage} - \end{figure} - \begin{subproblem} - Match each of the formulas with one of the given graphs. - \begin{shortsolution} - \begin{itemize} - \item $p$ is graphed in \vref{poly:fig:incdec1}; - \item $q$ is graphed in \vref{poly:fig:incdec2}; - \item $r$ is graphed in \vref{poly:fig:incdec3}; - \item $s$ is graphed in \vref{poly:fig:incdec4}. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the zeros of each function using the appropriate graph. - \begin{shortsolution} - \begin{itemize} - \item $p$ has simple zeros at about $-3.8$, $0$, and $5$. - \item $q$ has simple zeros at about $-5.9$, $-1$, $1$, and $4$. - \item $r$ has simple zeros at about $-5$, $-2.9$, and $4.1$. - \item $s$ has simple zeros at about $-9$, $-6$, $4.2$, $8.1$, and a zero of multiplicity $2$ at $0$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the local maximums and minimums of each of the functions. - \begin{shortsolution} - \begin{itemize} - \item $p$ has a local maximum of approximately $3.9$ at $-2$, and a local minimum of approximately $-6.5$ at $3$. - \item $q$ has a local minimum of approximately $-10$ at $-4$, and $-4$ at $3$; $q$ has a local maximum of approximately $1$ at $0$. - \item $r$ has a local minimum of approximately $-5.5$ at $-4$, and a local maximum of approximately $10$ at $3$. - \item $s$ has a local maximum of approximately $5$ at $-8$, $0$ at $0$, and $5$ at $7$; $s$ has local minimums - of approximately $-3$ at $-4$, and $-1$ at $3$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the global maximums and minimums of each of the functions. - \begin{shortsolution} - \begin{itemize} - \item $p$ does not have a global maximum, nor a global minimum. - \item $q$ has a global minimum of approximately $-10$; it does not have a global maximum. - \item $r$ does not have a global maximum, nor a global minimum. - \item $s$ has a global maximum of approximately $5$; it does not have a global minimum. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the intervals on which each function is increasing and decreasing. - \begin{shortsolution} - \begin{itemize} - \item $p$ is increasing on $(-\infty,-2)\cup (3,\infty)$, and decreasing on $(-2,3)$. - \item $q$ is increasing on $(-4,0)\cup (3,\infty)$, and decreasing on $(-\infty,-4)\cup (0,3)$. - \item $r$ is increasing on $(-4,3)$, and decreasing on $(-\infty,-4)\cup (3,\infty)$. - \item $s$ is increasing on $(-\infty,-8)\cup (-4,0)\cup (3,5)$, and decreasing on $(-8,-4)\cup (0,3)\cup (5,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the intervals on which each function is concave up and concave down. - \begin{shortsolution} - \begin{itemize} - \item $p$ is concave up on $(1,\infty)$, and concave down on $(-\infty,1)$. - \item $q$ is concave up on $(-\infty,-1)\cup (1,\infty)$, and concave down on $(-1,1)$. - \item $r$ is concave up on $(-\infty,-3)\cup (0,2)$, and concave down on $(-3,0)\cup (2,\infty)$. - \item $s$ is concave up on $(-6,-2)\cup (2,5)$, and concave down on $(-\infty,-6)\cup (-2,2)\cup (5,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - The degree of $q$ is $5$. Assuming that all of the real zeros of $q$ are - shown in its graph, how many complex zeros does $q$ have? - \begin{shortsolution} - \Vref{poly:fig:incdec2} shows that $q$ has $3$ real zeros - since the curve of $q$ cuts the horizontal axis $3$ times. - Since $q$ has degree $5$, $q$ must have $2$ complex zeros. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Long-run behaviour of polynomials] - Describe the long-run behavior of each of polynomial functions in - \crefrange{poly:prob:degree5}{poly:prob:degree2}. - \begin{shortsolution} - $\dd\lim_{x\rightarrow-\infty}p(x)=-\infty$, - $\dd\lim_{x\rightarrow\infty}p(x)=\infty$, - $\dd\lim_{x\rightarrow-\infty}q(x)=\infty$, - $\dd\lim_{x\rightarrow\infty}q(x)=-\infty$, - $\dd\lim_{x\rightarrow-\infty}r(x)=-\infty$, - $\dd\lim_{x\rightarrow\infty}r(x)=\infty$, - $\dd\lim_{x\rightarrow-\infty}s(x)=\infty$, - $\dd\lim_{x\rightarrow\infty}s(x)=\infty$, - \end{shortsolution} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[True of false?] - Let $p$ be a polynomial function. - Label each of the following statements as true (T) or false (F); if they are false, - provide an example that supports your answer. - \begin{subproblem} - If $p$ has degree $3$, then $p$ has $3$ distinct zeros. - \begin{shortsolution} - False. Consider $p(x)=x^2(x+1)$ which has only 2 distinct zeros. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has degree $4$, then $\dd\lim_{x\rightarrow-\infty}p(x)=\infty$ and $\dd\lim_{x\rightarrow\infty}p(x)=\infty$. - \begin{shortsolution} - False. Consider $p(x)=-x^4$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has even degree, then it is possible that $p$ can have no real zeros. - \begin{shortsolution} - True. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has odd degree, then it is possible that $p$ can have no real zeros. - \begin{shortsolution} - False. All odd degree polynomials will cut the horizontal axis at least once. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a possible formula for a polynomial - function that has the specified properties. - \begin{subproblem} - Degree 2 and has zeros at $4$ and $5$. - \begin{shortsolution} - Possible option: $p(x)=(x-4)(x-5)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 3 and has zeros at $4$,$5$ and $-3$. - \begin{shortsolution} - Possible option: $p(x)=(x-4)(x-5)(x+3)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 4 and has zeros at $0$, $4$, $5$, $-3$. - \begin{shortsolution} - Possible option: $p(x)=x(x-4)(x-5)(x+3)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 4, with zeros that make the graph cut at $2$, $-5$, and a zero that makes the graph touch at $-2$; - \begin{shortsolution} - Possible option: $p(x)=(x-2)(x+5)(x+2)^2$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 3, with only one zero at $-1$. - \begin{shortsolution} - Possible option: $p(x)=(x+1)^3$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{poly:step:last}] - \pccname{Saheed} is graphing a polynomial function, $p$. - He is following \crefrange{poly:step:first}{poly:step:last} and has so far - marked the zeros of $p$ on \cref{poly:fig:optionsp1}. Saheed tells you that - $p$ has degree $3$, but does \emph{not} say if the leading coefficient - of $p$ is positive or negative. - \begin{figure}[!htbp] - \begin{widepage} - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\textwidth, - height=.5\textwidth, - ] - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:optionsp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\textwidth, - height=.5\textwidth, - ] - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:optionsp2} - \end{subfigure}% - \caption{} - \end{widepage} - \end{figure} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp1} to help sketch $p$, assuming that the leading coefficient - is positive. - \begin{shortsolution} - Assuming that $a_3>0$: - - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-6.78179:8.35598,samples=50]{1/20*(x+5)*(x-2)*(x-6)}; - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp1} to help sketch $p$, assuming that the leading coefficient - is negative. - \begin{shortsolution} - Assuming that $a_3<0$: - - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-6.78179:8.35598,samples=50]{-1/20*(x+5)*(x-2)*(x-6)}; - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - Saheed now turns his attention to another polynomial function, $q$. He finds - the zeros of $q$ (there are only $2$) and marks them on \cref{poly:fig:optionsp2}. - Saheed knows that $q$ has degree $3$, but doesn't know if the leading - coefficient is positive or negative. - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp2} to help sketch $q$, assuming that the leading - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-8.68983:7.31809,samples=50]{1/20*(x+5)^2*(x-6)}; - \addplot expression[domain=-6.31809:9.68893,samples=50]{1/20*(x+5)*(x-6)^2}; - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp2} to help sketch $q$, assuming that the leading - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-8.68983:7.31809,samples=50]{-1/20*(x+5)^2*(x-6)}; - \addplot expression[domain=-6.31809:9.68893,samples=50]{-1/20*(x+5)*(x-6)^2}; - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Zeros] - Find all zeros of each of the following polynomial functions, making - sure to detail their multiplicity. Note that - you may need to use factoring, or the quadratic formula, or both! Also note - that some zeros may be repeated, and some may be complex. - \begin{multicols}{3} - \begin{subproblem} - $p(x)=x^2+1$ - \begin{shortsolution} - $\pm i$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(y)=(y^2-9)(y^2-7)$ - \begin{shortsolution} - $\pm 3$, $\pm \sqrt{7}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(z)=-4z^3(z^2+3)(z^2+64)$ - \begin{shortsolution} - $0$ (multiplicity $3$), $\pm\sqrt{3}$ (simple), $\pm\sqrt{8}$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $a(x)=x^4-81$ - \begin{shortsolution} - $\pm 3$, $\pm 3i$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $b(y)=y^3-8$ - \begin{shortsolution} - $2$, $-1\pm i\sqrt{3}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $c(m)=m^3-m^2$ - \begin{shortsolution} - $0$ (multiplicity $2$), $1$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(n)=(n+1)(n^2+4)$ - \begin{shortsolution} - $-1$, $\pm 2i$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $f(\alpha)=(\alpha^2-16)(\alpha^2-5\alpha+4)$ - \begin{shortsolution} - $-4$ (simple), $4$ (multiplicity $2$), $1$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(\beta)=(\beta^2-25)(\beta^2-5\beta-4)$ - \begin{shortsolution} - $\pm 5$, $\dfrac{5\pm\sqrt{41}}{2}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Given zeros, find a formula] - In each of the following problems you are given the zeros of a polynomial. - Write a possible formula for each polynomial| you may leave your - answer in factored form, but it may not contain complex numbers. Unless - otherwise stated, assume that the zeros are simple. - \begin{multicols}{3} - \begin{subproblem} - $1$, $2$ - \begin{shortsolution} - $p(x)=(x-1)(x-2)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $0$, $5$, $13$ - \begin{shortsolution} - $p(x)=x(x-5)(x-13)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $-7$, $2$ (multiplicity $3$), $5$ - \begin{shortsolution} - $p(x)=(x+7)(x-2)^3(x-5)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $0$, $\pm i$ - \begin{shortsolution} - $p(x)=x(x^2+1)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\pm 2i$, $\pm 7$ - \begin{shortsolution} - $p(x)=(x^2+4)(x^2-49)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $-2\pm i\sqrt{6}$ - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Composition of polynomials] - Let $p$ and $q$ be polynomial functions that have formulas - \[ - p(x)=(x+1)(x+2)(x+5), \qquad q(x)=3-x^4 - \] - Evaluate each of the following. - \begin{multicols}{4} - \begin{subproblem} - $(p\circ q)(0)$ - \begin{shortsolution} - $160$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(q\circ p)(0)$ - \begin{shortsolution} - $-9997$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(p\circ q)(1)$ - \begin{shortsolution} - $84$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(p\circ p)(0)$ - \begin{shortsolution} - $1980$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Piecewise polynomial functions] - Let $P$ be the piecewise-defined function with formula - \[ - P(x)=\begin{cases} - (1-x)(2x+5)(x^2+1), & x\leq -3\\ - 4-x^2, & -3m$ then $r$ will have an oblique asymptote as $x\rightarrow\pm\infty$ (more on this in \cref{rat:sec:oblique}) - \end{itemize} - \end{pccdefinition} - We will concentrate on functions that have horizontal asymptotes until - we reach \cref{rat:sec:oblique}. - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}[Long-run behavior graphically]\label{rat:ex:horizasymp} - \pccname{Kebede} has graphed the following functions in his graphing calculator - \[ - r(x)=\frac{x+1}{x-3}, \qquad s(x)=\frac{2(x+1)}{x-3}, \qquad t(x)=\frac{3(x+1)}{x-3} - \] - 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} - \begin{tikzpicture}[/pgf/declare function={f=2*(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:2]{f}; - \addplot[pccplot] expression[domain=5:15]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:2.42857,samples=50]{f}; - \addplot[pccplot] expression[domain=3.8:15,samples=50]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{1}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=3*(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:1.6666,samples=50]{f}; - \addplot[pccplot] expression[domain=7:15]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp3} - \end{subfigure} - \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. - In particular, Oscar notes that - \begin{itemize} - \item the curve shown in \cref{rat:fig:horizasymp1} has a horizontal asymptote with equation $y=2$; - \item the curve shown in \cref{rat:fig:horizasymp2} has a horizontal asymptote with equation $y=1$; - \item the curve shown in \cref{rat:fig:horizasymp3} has a horizontal asymptote with equation $y=3$. - \end{itemize} - Oscar is able to tie it all together for Kebede by referencing \cref{rat:def:longrun}. He says - 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 - %=================================== - \begin{pccexample}[Long-run behavior numerically] - \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 - \[ - R(x)=\frac{-5(x+1)}{x-3}, \qquad S(x)=\frac{7(x-5)}{2(x+1)} - \] - In \cref{rat:tab:plusinfty} they model the behavior of $R$ and $S$ as $x\rightarrow\infty$, - and in \cref{rat:tab:minusinfty} they model the behavior of $R$ and $S$ as $x\rightarrow-\infty$ - by substituting very large values of $|x|$ into each function. - \begin{table}[!htb] - \begin{minipage}{.5\textwidth} - \centering - \caption{$R$ and $S$ as $x\rightarrow\infty$} - \label{rat:tab:plusinfty} - \begin{tabular}{crr} - \beforeheading - $x$ & $R(x)$ & $S(x)$ \\ \afterheading - $1\times 10^2$ & $-5.20619$ & $3.29208$ \\\normalline - $1\times 10^3$ & $-5.02006$ & $3.47902$ \\\normalline - $1\times 10^4$ & $-5.00200$ & $3.49790$ \\\normalline - $1\times 10^5$ & $-5.00020$ & $3.49979$ \\\normalline - $1\times 10^6$ & $-5.00002$ & $3.49998$ \\\lastline - \end{tabular} - \end{minipage}% - \begin{minipage}{.5\textwidth} - \centering - \caption{$R$ and $S$ as $x\rightarrow-\infty$} - \label{rat:tab:minusinfty} - \begin{tabular}{crr} - \beforeheading - $x$ & $R(x)$ & $S(x)$ \\ \afterheading - $-1\times 10^2$ & $-4.80583$ & $3.71212$ \\\normalline - $-1\times 10^3$ & $-4.98006$ & $3.52102$ \\\normalline - $-1\times 10^4$ & $-4.99800$ & $3.50210$ \\\normalline - $-1\times 10^5$ & $-4.99980$ & $3.50021$ \\\normalline - $-1\times 10^6$ & $-4.99998$ & $3.50002$ \\\lastline - \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 - %=================================== - \begin{pccexample}[Repeated factors in the numerator] - Consider the functions $f$, $g$, and $h$ that have formulas - \[ - f(x)=\frac{(x-2)^2}{(x-3)(x+1)}, \qquad g(x)=\frac{x-2}{(x-3)(x+1)}, \qquad h(x)=\frac{(x-2)^3}{(x-3)(x+1)} - \] - which are graphed in \cref{rat:fig:repfactn}. We note that each function has vertical - asymptotes at $-1$ and $3$, and so the domain of each function is - \[ - (-\infty,-1)\cup(-1,3)\cup(3,\infty) - \] - 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 - $f$ does not cut the horizontal axis| it bounces off it; - \item $g$ also has a horizontal intercept $(2,0)$, and the curve - of $g$ \emph{does} cut the horizontal axis; - \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} - \item $f$ has a horizontal asymptote with equation $y=1$; - \item $g$ has a horizontal asymptote with equation $y=0$; - \item $h$ does \emph{not} have a horizontal asymptote| it has an oblique asymptote (we'll - study this more in \cref{rat:sec:oblique}). - \end{itemize} - \end{pccexample} - - \begin{figure}[!htb] - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)^2/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - ytick={-8,-4,...,8}, - % grid=both, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.248,samples=50]{f}; - \addplot[pccplot] expression[domain=-0.794:2.976,samples=50]{f}; - \addplot[pccplot] expression[domain=3.026:5,samples=50]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-6:6]({-1},{x}); - % \addplot[asymptote,domain=-6:6]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{(x-2)^2}{(x+1)(x-3)}$} - \label{rat:fig:repfactn1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - ytick={-8,-4,...,8}, - % grid=both, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.075]{f}; - \addplot[pccplot] expression[domain=-0.925:2.975]{f}; - \addplot[pccplot] expression[domain=3.025:5]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-6:6]({-1},{x}); - % \addplot[asymptote,domain=-6:6]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{x-2}{(x+1)(x-3)}$} - \label{rat:fig:repfactn2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)^3/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - xtick={-8,-6,...,8}, - % grid=both, - ymin=-30,ymax=30, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.27]{f}; - \addplot[pccplot] expression[domain=-0.806:2.99185]{f}; - \addplot[pccplot] expression[domain=3.0085:5]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-30:30]({-1},{x}); - % \addplot[asymptote,domain=-30:30]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{(x-2)^3}{(x+1)(x-3)}$} - \label{rat:fig:repfactn3} - \end{subfigure} - \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 - function has a \emph{hole} at $a$. - \begin{pccdefinition}[Holes] - The rational function - \[ - r(x)=\frac{p(x)}{q(x)} - \] - has a hole at $a$ if $p(a)=q(a)=0$. Note that holes are different from - a vertical asymptotes. We represent that $r$ has a hole at the point - $(a,r(a))$ on the curve $y=r(x)$ by - using a hollow circle, $\circ$. - \end{pccdefinition} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample} - \pccname{Mohammed} and \pccname{Sue} have graphed the function $r$ that has formula - \[ - r(x)=\frac{x^2+x-6}{(x-2)} - \] - 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 - \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 - \[ - (-\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] - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-4,...,8}, - ytick={-8,-4,...,8}, - grid=both, - width=\textwidth, - ] - \addplot expression[domain=-10:7]{x+3}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:hole} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-4,...,8}, - ytick={-8,-4,...,8}, - grid=both, - width=\textwidth, - ] - \addplot expression[domain=-10:7]{x+3}; - \addplot[holdot] coordinates{(2,5)}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:hole1} - \end{minipage}% - \end{figure} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{pccexample} - Consider the function $f$ that has formula - \[ - f(x)=\frac{x(x+3)}{x^2-4x} - \] - The domain of $f$ is $(-\infty,0)\cup(0,4)\cup(4,\infty)$ because both $0$ and $4$ - make the denominator equal to $0$. Notice that - \begin{align*} - f(x) & = \frac{x(x+3)}{x(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 - \begin{tikzpicture}[/pgf/declare function={f=(x+3)/(x-4);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - ] - \addplot[pccplot] expression[domain=-10:3.36364,samples=50]{f}; - \addplot[pccplot] expression[domain=4.77:10]{f}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[holdot]coordinates{(0,-0.75)}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{x(x+3)}{x^2-4x}$} - \label{rat:fig:holeex} - \end{figure} - \end{pccexample} - - - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Minimums and maximums] - \pccname{Seamus} and \pccname{Trang} are discussing rational functions. Seamus says that - 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 - \[ - f(x)=-\frac{32(x-1)(x+1)}{(x-2)^2(x+2)^2}, \qquad g(x)=\frac{32(x-1)(x+1)}{(x-2)^2(x+2)^2} - \] - 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);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.01]{f}; - \addplot[pccplot] expression[domain=-1.45:1.45]{f}; - \addplot[pccplot] expression[domain=3.01:10]{f}; - \addplot[soldot] coordinates{(-1,0)(1,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=f(x)$} - \label{rat:fig:minmax1} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=32*(x-1)*(x+1)/(( x-2)^2*(x+2)^2);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.01]{f}; - \addplot[pccplot] expression[domain=-1.45:1.45]{f}; - \addplot[pccplot] expression[domain=3.01:10]{f}; - \addplot[soldot] coordinates{(-1,0)(1,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=g(x)$} - \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 - % Date: March 2012 - %=================================== - \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} - \centering - \captionof{table}{} - \label{rat:tab:spaghetti} - \begin{tabular}{cc} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - $1$ & \\\normalline - $2$ & \\\normalline - $3$ & \\\normalline - $4$ & \\\normalline - $5$ & \\\normalline - $6$ & \\\normalline - $7$ & \\\normalline - $8$ & \\\normalline - $9$ & \\\normalline - $10$ & \\\lastline - \end{tabular} - \end{margintable} - \begin{subproblem}\label{rat:prob:spaggt1} - Help the Queen complete \cref{rat:tab:spaghetti}, and use $2$ digits after the decimal - where appropriate. - \begin{shortsolution} - \begin{tabular}[t]{ld{2}} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - $1$ & 100 \\\normalline - $2$ & 50 \\\normalline - $3$ & 33.33 \\\normalline - $4$ & 25 \\\normalline - $5$ & 20 \\\normalline - $6$ & 16.67 \\\normalline - $7$ & 14.29 \\\normalline - $8$ & 12.50 \\\normalline - $9$ & 11.11 \\\normalline - $10$ & 10 \\\lastline - \end{tabular} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What do you notice about the number of $\unit{mg}$ that it takes to break - the spaghetti as $x$ increases? - \begin{shortsolution} - It seems that the number of $\unit{mg}$ that it takes to break the spaghetti decreases - as $x$ increases. - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:spaglt1} - The Queen wonders what happens when $x$ gets very small| help the Queen construct - a table of values for $x$ and $y$ when $x=0.0001, 0.001, 0.01, 0.1, 0.5, 1$. - \begin{shortsolution} - \begin{tabular}[t]{d{2}l} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - 0.0001 & $1000000$ \\\normalline - 0.001 & $100000$ \\\normalline - 0.01 & $10000$ \\\normalline - 0.1 & $1000$ \\\normalline - 0.5 & $200$ \\\normalline - 1 & $100$ \\\lastline - \end{tabular} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What do you notice about the number of $\unit{mg}$ that it takes to break the spaghetti - as $x\rightarrow 0$? Would it ever make sense to let $x=0$? - \begin{shortsolution} - The number of $\unit{mg}$ required to break the spaghetti increases as $x\rightarrow 0$. - We can not allow $x$ to be $0$, as we can not divide by $0$, and we can not - be $0$ inches from the edge of the table. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Plot your results from \cref{rat:prob:spaggt1,rat:prob:spaglt1} on the same graph, - and join the points using a smooth curve| set the maximum value of $y$ as $200$, and - 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, - xmin=-2,xmax=11, - ymin=-20,ymax=200, - xtick={2,4,...,10}, - ytick={20,40,...,180}, - grid=major, - width=\solutionfigurewidth, - ] - \addplot+[-] expression[domain=0.5:10]{100/x}; - \addplot[soldot] coordinates{(0.5,200)(1,100)(2,50)(3,33.33) - (4,25)(5,20)(16.67)(7,14.29)(8,12.50)(9,11.11)(10,10)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Using your graph, observe what happens to $y$ as $x$ increases. If we could somehow - construct a piece of uncooked spaghetti that was $\unit[101]{inches}$ long, how many - $\unit{mg}$ would it take to break the spaghetti? - \begin{shortsolution} - As $x$ increases, $y\rightarrow 0$. If we could construct a piece of spaghetti - $\unit[101]{inches}$ long, it would only take $\unit[1]{mg}$ to break it $\left(\frac{100}{100}=1\right)$. Of course, - the weight of spaghetti would probably cause it to break without the weight. - \end{shortsolution} - \end{subproblem} - The Queen looks forward to more food-related investigations from her jester. - \end{problem} - - - - %=================================== - % Author: Adams (Hughes) - % Date: March 2012 - %=================================== - \begin{problem}[Debt Amortization] - To amortize a debt means to pay it off in a given length of time using - equal periodic payments. The payments include interest on the unpaid - balance. The following formula gives the monthly payment, $M$, in dollars - that is necessary to amortize a debt of $P$ dollars in $n$ months - at a monthly interest rate of $i$ - \[ - M=\frac{P\cdot i}{1-(1+i)^{-n}} - \] - Use this formula in each of the following problems. - \begin{subproblem} - What monthly payments are necessary on a credit card debt of \$2000 at - $\unit[1.5]{\%}$ monthly if you want to pay off the debt in $2$ years? - In one year? How much money will you save by paying off the debt in the - shorter amount of time? - \begin{shortsolution} - 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 - \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 - \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. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - To purchase a home, a family needs a loan of \$300,000 at $\unit[5.2]{\%}$ - annual interest. Compare a $20$ year loan to a $30$ year loan and make - a recommendation for the family. - (Note: when given an annual interest rate, it is a common business practice to divide by - $12$ to get a monthly rate.) - \begin{shortsolution} - 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 - \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 - \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} - \begin{subproblem} - \pccname{Ellen} wants to make monthly payments of \$100 to pay off a debt of \$3000 - at \unit[12]{\%} annual interest. How long will it take her to pay off the - debt? - \begin{shortsolution} - We are given $M=100$, $P=3000$, $i=0.01$, and we need to find $n$ - in the equation - \[ - 100 = \frac{3000\cdot 0.01}{1-(1+0.01)^{-n}} - \] - Using logarithms, we find that $n\approx 36$. It will take - Ellen about $3$ years to pay off the debt. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - \pccname{Jake} is going to buy a new car. He puts \$2000 down and wants to finance the - remaining \$14,000. The dealer will offer him \unit[4]{\%} annual interest for - $5$ years, or a \$2000 - rebate which he can use to reduce the amount of the loan and \unit[8]{\%} - annual interest for 5 years. Which should he choose? - \begin{shortsolution} - \begin{description} - \item[Option 1:] $\unit[4]{\%}$ annual interest for $5$ years on \$14,000. - 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 - \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. - \item[Option 2:] $\unit[8]{\%}$ annual interest for $5$ years on \$12,000. - 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 - \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 - interest. - \end{description} - Jake should choose option 1 to minimize the amount of interest - he has to pay. - \end{shortsolution} - \end{subproblem} - \end{problem} - - \begin{exercises} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Rational or not] - Decide if each of the following functions are rational or not. If - they are rational, state their domain. - \begin{multicols}{3} - \begin{subproblem} - $r(x)=\dfrac{3}{x}$ - \begin{shortsolution} - $r$ is rational; the domain of $r$ is $(-\infty,0)\cup (0,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $s(y)=\dfrac{y}{6}$ - \begin{shortsolution} - $s$ is not rational ($s$ is linear). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $t(z)=\dfrac{4-x}{7-8z}$ - \begin{shortsolution} - $t$ is rational; the domain of $t$ is $\left( -\infty,\dfrac{7}{8} \right)\cup \left( \dfrac{7}{8},\infty \right)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $u(w)=\dfrac{w^2}{(w-3)(w+4)}$ - \begin{shortsolution} - $u$ is rational; the domain of $w$ is $(-\infty,-4)\cup(-4,3)\cup(3,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $v(x)=\dfrac{4}{(x-2)^2}$ - \begin{shortsolution} - $v$ is rational; the domain of $v$ is $(-\infty,2)\cup(2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $w(x)=\dfrac{9-x}{x+17}$ - \begin{shortsolution} - $w$ is rational; the domain of $w$ is $(-\infty,-17)\cup(-17,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $a(x)=x^2+4$ - \begin{shortsolution} - $a$ is not rational ($a$ is quadratic, or a polynomial of degree $2$). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $b(y)=3^y$ - \begin{shortsolution} - $b$ is not rational ($b$ is exponential). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $c(z)=\dfrac{z^2}{z^3}$ - \begin{shortsolution} - $c$ is rational; the domain of $c$ is $(-\infty,0)\cup (0,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $d(x)=x^2(x+3)(5x-7)$ - \begin{shortsolution} - $d$ is not rational ($d$ is a polynomial). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $e(\alpha)=\dfrac{\alpha^2}{\alpha^2-1}$ - \begin{shortsolution} - $e$ is rational; the domain of $e$ is $(-\infty,-1)\cup(-1,1)\cup(1,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $f(\beta)=\dfrac{3}{4}$ - \begin{shortsolution} - $f$ is not rational ($f$ is constant). - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Function evaluation] - Let $r$ be the function that has formula - \[ - r(x)=\frac{(x-2)(x+3)}{(x+5)(x-7)} - \] - Evaluate each of the following (if possible); if the value is undefined, - then state so. - \begin{multicols}{4} - \begin{subproblem} - $r(0)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(0) & =\frac{(0-2)(0+3)}{(0+5)(0-7)} \\ - & =\frac{-6}{-35} \\ - & =\frac{6}{35} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(1)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(1) & =\frac{(1-2)(1+3)}{(1+5)(1-7)} \\ - & =\frac{-4}{-36} \\ - & =\frac{1}{9} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(2)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(2) & =\frac{(2-2)(2+3)}{(2+5)(2-7)} \\ - & = \frac{0}{-50} \\ - & =0 - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(4)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(4) & =\frac{(4-2)(4+3)}{(4+5)(4-7)} \\ - & =\frac{14}{-27} \\ - & =-\frac{14}{27} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(7)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(7) & =\frac{(7-2)(7+3)}{(7+5)(7-7)} \\ - & =\frac{50}{0} - \end{aligned}$ - - $r(7)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(-3)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(-3) & =\frac{(-3-2)(-3+3)}{(-3+5)(-3-7)} \\ - & =\frac{0}{-20} \\ - & =0 - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(-5)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(-5) & =\frac{(-5-2)(-5+3)}{(-5+5)(-5-7)} \\ - & =\frac{14}{0} - \end{aligned}$ - - $r(-5)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r\left( \frac{1}{2} \right)$ - \begin{shortsolution} - $\begin{aligned}[t] - 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} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Holes or asymptotes?] - State the domain of each of the following rational functions. Identify - any holes or asymptotes. - \begin{multicols}{3} - \begin{subproblem} - $f(x)=\dfrac{12}{x-2}$ - \begin{shortsolution} - $f$ has a vertical asymptote at $2$; the domain of $f$ is $(-\infty,2)\cup (2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x)=\dfrac{x^2+x}{(x+1)(x-2)}$ - \begin{shortsolution} - $g$ has a vertical asymptote at $2$, and a hole at $-1$; the domain of $g$ is $(-\infty,-1)\cup(-1,2)\cup(2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x)=\dfrac{x^2+5x+4}{x^2+x-12}$ - \begin{shortsolution} - $h$ has a vertical asymptote at $3$, and a whole at $-4$; the domain of $h$ is $(-\infty,-4)\cup(-4,3)\cup(3,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(z)=\dfrac{z+2}{2z-3}$ - \begin{shortsolution} - $k$ has a vertical asymptote at $\dfrac{3}{2}$; the domain of $k$ is $\left( -\infty,\dfrac{3}{2} \right)\cup\left( \dfrac{3}{2},\infty \right)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(w)=\dfrac{w}{w^2+1}$ - \begin{shortsolution} - $l$ does not have any vertical asymptotes nor holes; the domain of $w$ is $(-\infty,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(t)=\dfrac{14}{13-t^2}$ - \begin{shortsolution} - $m$ has vertical asymptotes at $\pm\sqrt{13}$; the domain of $m$ is $(-\infty,\sqrt{13})\cup(-\sqrt{13},\sqrt{13})\cup(\sqrt{13},\infty)$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a graph] - Consider the rational functions graphed in \cref{rat:fig:findformula}. Find - the vertical asymptotes for each function, together with any zeros, and - give a possible formula for each. - \begin{shortsolution} - \begin{itemize} - \item \Vref{rat:fig:formula1}: possible formula is $r(x)=\dfrac{1}{x+5}$ - \item \Vref{rat:fig:formula2}: possible formula is $r(x)=\dfrac{(x+3)}{(x-5)}$ - \item \Vref{rat:fig:formula3}: possible formula is $r(x)=\dfrac{1}{(x-4)(x+3)}$. - \end{itemize} - \end{shortsolution} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=1/(x+4);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-6,ymax=6, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-4.16667,samples=50]{f}; - \addplot[pccplot] expression[domain=-3.83333:10,samples=50]{f}; - \addplot[asymptote,domain=-6:6]({-4},{x}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x+3)/(x-5);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-6,ymax=6, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:3.85714]{f}; - \addplot[pccplot] expression[domain=6.6:10]{f}; - \addplot[soldot] coordinates{(-3,0)}; - \addplot[asymptote,domain=-6:6]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=1/((x-4)*(x+3));}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-3,ymax=3, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.0473]{f}; - \addplot[pccplot] expression[domain=-2.95205:3.95205]{f}; - \addplot[pccplot] expression[domain=4.0473:10]{f}; - \addplot[asymptote,domain=-3:3]({-3},{x}); - \addplot[asymptote,domain=-3:3]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula3} - \end{subfigure} - \caption{} - \label{rat:fig:findformula} - \end{widepage} - \end{figure} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a formula of a rational - function that has the listed properties. - \begin{subproblem} - Vertical asymptote at $2$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{1}{x-2}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Vertical asymptote at $5$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{1}{x-5}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Vertical asymptote at $-2$, and zero at $6$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{x-6}{x+2}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Zeros at $2$ and $-5$ and vertical asymptotes at $1$ and $-7$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{(x-2)(x+5)}{(x-1)(x+7)}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Given formula, find horizontal asymptotes] - Each of the following functions has a horizontal asymptote. Write the equation - of the horizontal asymptote for each function. - \begin{multicols}{3} - \begin{subproblem} - $f(x) = \dfrac{1}{x}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x) = \dfrac{2x+3}{x}$ - \begin{shortsolution} - $y=2$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x) = \dfrac{x^2+2x}{x^2+3}$ - \begin{shortsolution} - $y=1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x) = \dfrac{x^2+7}{x}$ - \begin{shortsolution} - $y=1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(x)=\dfrac{3x-2}{5x+8}$ - \begin{shortsolution} - $y=\dfrac{3}{5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(x)=\dfrac{3x-2}{5x^2+8}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $n(x)=\dfrac{(6x+1)(x-7)}{(11x-8)(x-5)}$ - \begin{shortsolution} - $y=\dfrac{6}{11}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=\dfrac{19x^3}{5-x^4}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(x)=\dfrac{14x^2+x}{1-7x^2}$ - \begin{shortsolution} - $y=-2$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{problem}[Given horizontal asymptotes, find formula] - In each of the following problems, give a formula for a function that - has the given horizontal asymptote. Note that there may be more than one option. - \begin{multicols}{4} - \begin{subproblem} - $y=7$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{7(x-2)}{x+1}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $7$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-1$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{5-x^2}{x^2+10}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $10$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=53$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{53x^3}{x^3+4x^2-7}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $53$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-17$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{34(x+2)}{7-2x}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $-17$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{3}{2}$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{3x+4}{2(x+1)}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $\dfrac{3}{2}$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=0$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{4}{x}$. Note that there - are other options, provided that the degree of the numerator is less than the degree - of the denominator. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-1$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{10x}{5-10x}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $-1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=2$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{8x-3}{4x+1}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $2$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a formula for a function that - has the prescribed properties. Note that there may be more than one option. - \begin{subproblem} - $f(x)\rightarrow 3$ as $x\rightarrow\pm\infty$. - \begin{shortsolution} - Possible option: $f(x)=\dfrac{3(x-2)}{x+7}$. Note that - the zero and asymptote of $f$ could be changed, and $f$ would still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(x)\rightarrow -4$ as $x\rightarrow\pm\infty$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{-4(x-2)}{x+7}$. Note that - the zero and asymptote of $r$ could be changed, and $r$ would still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x)\rightarrow 2$ as $x\rightarrow\pm\infty$, and $k$ has vertical asymptotes at $-3$ and $5$. - \begin{shortsolution} - Possible option: $k(x)=\dfrac{2x^2}{(x+3)(x-5)}$. Note that the denominator - must have the given factors; the numerator could be any degree $2$ polynomial, provided the - leading coefficient is $2$. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: Feb 2011 - %=================================== - \begin{problem} - Let $r$ be the rational function that has - \[ - r(x) = \frac{(x+2)(x-1)}{(x+3)(x-4)} - \] - Each of the following questions are in relation to this function. - \begin{subproblem} - What is the vertical intercept of this function? State your answer as an - ordered pair. \index{rational functions!vertical intercept} - \begin{shortsolution} - $\left(0,\frac{1}{6}\right)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:rational} - What values of $x$ make the denominator equal to $0$? - \begin{shortsolution} - $-3,4$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use your answer to \cref{rat:prob:rational} to write the domain of the function in - both interval, and set builder notation. %\index{rational functions!domain}\index{domain!rational functions} - \begin{shortsolution} - Interval notation: $(-\infty,-3)\cup (-3,4)\cup (4,\infty)$. - Set builder: $\{x|x\ne -3, \mathrm{and}\, x\ne 4\}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What are the vertical asymptotes of the function? State your answers in - the form $x=$ - \begin{shortsolution} - $x=-3$ and $x=4$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:zeroes} - What values of $x$ make the numerator equal to $0$? - \begin{shortsolution} - $-2,1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use your answer to \cref{rat:prob:zeroes} to write the horizontal intercepts of - $r$ as ordered pairs. - \begin{shortsolution} - $(-2,0)$ and $(1,0)$ - \end{shortsolution} - \end{subproblem} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Holes] - \pccname{Josh} and \pccname{Pedro} are discussing the function - \[ - r(x)=\frac{x^2-1}{(x+3)(x-1)} - \] - \begin{subproblem} - What is the domain of $r$? - \begin{shortsolution} - The domain of $r$ is $(-\infty,-3)\cup(-3,1)\cup(1,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Josh notices that the numerator can be factored- can you see how? - \begin{shortsolution} - $(x^2-1)=(x-1)(x+1)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Pedro asks, `Doesn't that just mean that - \[ - r(x)=\frac{x+1}{x+3} - \] - for all values of $x$?' Josh says, `Nearly\ldots but not for all values of $x$'. - What does Josh mean? - \begin{shortsolution} - $r(x)=\dfrac{x+1}{x+3}$ provided that $x\ne -1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Where does $r$ have vertical asymptotes, and where does it have holes? - \begin{shortsolution} - The function $r$ has a vertical asymptote at $-3$, and a hole at $1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Sketch a graph of $r$. - \begin{shortsolution} - A graph of $r$ is shown below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:-3.25]{(x+1)/(x+3)}; - \addplot[pccplot] expression[domain=-2.75:10]{(x+1)/(x+3)}; - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[holdot]coordinates{(1,0.5)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: July 2012 - %=================================== - \begin{problem}[Function algebra] - Let $r$ and $s$ be the rational functions that have formulas - \[ - r(x)=\frac{2-x}{x+3}, \qquad s(x)=\frac{x^2}{x-4} - \] - Evaluate each of the following (if possible). - \begin{multicols}{4} - \begin{subproblem} - $(r+s)(5)$ - \begin{shortsolution} - $\frac{197}{8}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r-s)(3)$ - \begin{shortsolution} - $\frac{53}{6}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r\cdot s)(4)$ - \begin{shortsolution} - Undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\left( \frac{r}{s} \right)(1)$ - \begin{shortsolution} - $-\frac{3}{4}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: July 2012 - %=================================== - \begin{problem}[Transformations: given the transformation, find the formula] - Let $r$ be the rational function that has formula. - \[ - r(x)=\frac{x+5}{2x-3} - \] - In each of the following problems apply the given transformation to the function $r$ and - write a formula for the transformed version of $r$. - \begin{multicols}{2} - \begin{subproblem} - Shift $r$ to the right by $3$ units. - \begin{shortsolution} - $r(x-3)=\frac{x+2}{2x-9}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ to the left by $4$ units. - \begin{shortsolution} - $r(x+4)=\frac{x+9}{2x+5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ up by $\pi$ units. - \begin{shortsolution} - $r(x)+\pi=\frac{x+5}{2x-3}+\pi$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ down by $17$ units. - \begin{shortsolution} - $r(x)-17=\frac{x+5}{2x-3}-17$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Reflect $r$ over the horizontal axis. - \begin{shortsolution} - $-r(x)=-\frac{x+5}{2x-3}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Reflect $r$ over the vertical axis. - \begin{shortsolution} - $r(-x)=\frac{x-5}{2x+3}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \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 - \caption{Tables for \cref{rat:prob:findformula}} - \label{rat:tab:findformula} - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=r(x)$} - \label{rat:tab:findformular} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{7}{2}$ \\\normalline - $-3$ & $-18$ \\\normalline - $-2$ & X \\\normalline - $-1$ & $-4$ \\\normalline - $0$ & $\nicefrac{-3}{2}$ \\\normalline - $1$ & $\nicefrac{-2}{3}$ \\\normalline - $2$ & $\nicefrac{-1}{4}$ \\\normalline - $3$ & $0$ \\\normalline - $4$ & $\nicefrac{1}{6}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=s(x)$} - \label{rat:tab:findformulas} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{-2}{21}$ \\\normalline - $-3$ & $\nicefrac{-1}{12}$ \\\normalline - $-2$ & $0$ \\\normalline - $-1$ & X \\\normalline - $0$ & $\nicefrac{-2}{3}$ \\\normalline - $1$ & $\nicefrac{-3}{4}$ \\\normalline - $2$ & $\nicefrac{-4}{3}$ \\\normalline - $3$ & X \\\normalline - $4$ & $\nicefrac{6}{5}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=t(x)$} - \label{rat:tab:findformulat} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{3}{5}$ \\\normalline - $-3$ & $0$ \\\normalline - $-2$ & X \\\normalline - $-1$ & $3$ \\\normalline - $0$ & $3$ \\\normalline - $1$ & X \\\normalline - $2$ & $0$ \\\normalline - $3$ & $\nicefrac{3}{5}$ \\\normalline - $4$ & $\nicefrac{7}{9}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=u(x)$} - \label{rat:tab:findformulau} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{16}{7}$ \\\normalline - $-3$ & X \\\normalline - $-2$ & $-\nicefrac{4}{5}$ \\\normalline - $-1$ & $-\nicefrac{1}{8}$ \\\normalline - $0$ & $0$ \\\normalline - $1$ & $-\nicefrac{1}{8}$ \\\normalline - $2$ & $-\nicefrac{4}{5}$ \\\normalline - $3$ & X \\\normalline - $4$ & $\nicefrac{16}{7}$ \\\lastline - \end{tabular} - \end{subtable} - \end{widepage} - \end{table} - \begin{subproblem} - Given that the formula for $r(x)$ has the form $r(x)=\dfrac{x-A}{x-B}$, use \cref{rat:tab:findformular} - to find values of $A$ and $B$. - \begin{shortsolution} - $A=3$ and $B=-2$, so $r(x)=\dfrac{x-3}{x+2}$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Check your formula by computing $r(x)$ at the values specified in the table. - \begin{shortsolution} - $\begin{aligned}[t] - r(-4) & = \frac{-4-3}{-4+2} \\ - & = \frac{7}{2} \\ - \end{aligned}$ - - $r(-3)=\ldots$ etc - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - The function $s$ in \cref{rat:tab:findformulas} has two vertical asymptotes and one zero. - Can you find a formula for $s(x)$? - \begin{shortsolution} - $s(x)=\dfrac{x+2}{(x-3)(x+1)}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Check your formula by computing $s(x)$ at the values specified in the table. - \begin{shortsolution} - $\begin{aligned}[t] - s(-4) & =\frac{-4+2}{(-4-3)(-4+1)} \\ - & =-\frac{2}{21} - \end{aligned}$ - - $s(-3)=\ldots$ etc - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Given that the formula for $t(x)$ has the form $t(x)=\dfrac{(x-A)(x-B)}{(x-C)(x-D)}$, use \cref{rat:tab:findformulat} to find the - values of $A$, $B$, $C$, and $D$; hence write a formula for $t(x)$. - \begin{shortsolution} - $t(x)=\dfrac{(x+3)(x-2)}{(x+2)(x+1)}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Given that the formula for $u(x)$ has the form $u(x)=\dfrac{(x-A)^2}{(x-B)(x-C)}$, use \cref{rat:tab:findformulau} to find the - values of $A$, $B$, and $C$; hence write a formula for $u(x)$. - \begin{shortsolution} - $u(x)=\dfrac{x^2}{(x+3)(x-3)}$ - \end{shortsolution} - \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 - \[ - r(x)=\frac{p(x)}{q(x)} - \] - In this section we will restrict attention to the case when - \[ - \text{degree of }p\leq \text{degree of }q - \] - Note that this necessarily means that each function that we consider - 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 - shape of the graph, but until we have the tools of calculus (from MTH 251) - we can not find local minimums, local maximums, and inflection points algebraically. This - means that we will make our best guess as to where these points are. - \item We will not concern ourselves too much with the vertical scale (because of - our previous point)| we will, however, mark the vertical intercept (assuming there is one), - and any horizontal asymptotes. - \end{itemize} - \begin{pccspecialcomment}[Steps to follow when sketching rational functions]\label{rat:def:stepsforsketch} - \begin{steps} - \item \label{rat:step:first} Find all vertical asymptotes and holes, and mark them on the - graph using dashed vertical lines and open circles $\circ$ respectively. - \item Find any intercepts, and mark them using solid circles $\bullet$; - determine if the curve cuts the axis, or bounces off it at each zero. - \item Determine the behavior of the function around each asymptote| does - it behave like $\frac{1}{x}$ or $\frac{1}{x^2}$? - \item \label{rat:step:penultimate} Determine the long-run behavior of the function, and mark the horizontal - asymptote using a dashed horizontal line. - \item \label{rat:step:last} Deduce the overall shape of the curve, and sketch it. If there isn't - enough information from the previous steps, then construct a table of values - including sample points from each branch. - \end{steps} - Remember that until we have the tools of calculus, we won't be able to - 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 - %=================================== - \begin{pccexample}\label{rat:ex:1overxminus2p2} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $r$ - that has formula - \[ - r(x)=\frac{1}{x-2} - \] - \begin{pccsolution} - \begin{steps} - \item $r$ has a vertical asymptote at $2$; $r$ does not have any holes. The curve of - $r$ will have $2$ branches. - \item $r$ does not have any zeros since the numerator is never equal to $0$. The - vertical intercept of $r$ is $\left( 0,-\frac{1}{2} \right)$. - \item $r$ behaves like $\frac{1}{x}$ around its vertical asymptote since $(x-2)$ - is raised to the power $1$. - \item Since the degree of the numerator is less than the degree of the denominator, - according to \vref{rat:def:longrun} the horizontal asymptote of $r$ has equation $y=0$. - \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} - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htbp] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-5,ymax=5, - width=\textwidth, - ] - \addplot[asymptote,domain=-5:5]({2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \addplot[soldot] coordinates{(0,-0.5)}node[axisnode,anchor=north east]{$\left( 0,-\frac{1}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxminus2p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=1/(x-2);}] - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-5,ymax=5, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-5:1.8,samples=50]{f}; - \addplot[pccplot] expression[domain=2.2:5]{f}; - \addplot[asymptote,domain=-5:5]({2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \addplot[soldot] coordinates{(0,-0.5)}node[axisnode,anchor=north east]{$\left( 0,-\frac{1}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxminus2p2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:1overxp1} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $v$ - that has formula - \[ - v(x)=\frac{10}{x} - \] - \begin{pccsolution} - \begin{steps} - \item $v$ has a vertical asymptote at $0$. $v$ does not have - any holes. The curve of $v$ will have $2$ branches. - \item $v$ does not have any zeros (since $10\ne 0$). Furthermore, $v$ - does not have a vertical intercept since $v(0)$ is undefined. - \item $v$ behaves like $\frac{1}{x}$ around its vertical asymptote. - \item $v$ has a horizontal asymptote with equation $y=0$. - \item We put the details we have obtained so far in \cref{rat:fig:1overxp1}. - We do not have enough information to sketch $v$ yet (because $v$ does - not have any intercepts), so let's pick a sample - point in either of the $2$ branches| it doesn't matter where our sample point - is, because we know what the overall shape will be. Let's compute $v(2)$ - \begin{align*} - v(2) & =\dfrac{10}{2} \\ - & = 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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-5,5}, - ytick={-5,5}, - axis line style={color=white}, - width=\textwidth, - ] - \addplot[asymptote,<->,domain=-10:10]({0},{x}); - \addplot[asymptote,<->,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=10/x;}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-5,5}, - ytick={-5,5}, - axis line style={color=white}, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-1]{f}; - \addplot[pccplot] expression[domain=1:10]{f}; - \addplot[soldot] coordinates{(2,5)}node[axisnode,anchor=south west]{$(2,5)$}; - \addplot[asymptote,<->,domain=-10:10]({0},{x}); - \addplot[asymptote,<->,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxp2} - \end{subfigure}% - \caption{$y=\dfrac{10}{x}$} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{rat:ex:asympandholep1} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $u$ - that has formula - \[ - u(x)=\frac{-4(x^2-9)}{x^2-8x+15} - \] - \begin{pccsolution} - \begin{steps} - \item We begin by factoring both the numerator and denominator of $u$ to help - us find any vertical asymptotes or holes - \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} - \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. - \item $u$ has a simple zero at $-3$. The vertical intercept of $u$ is $\left( 0,\frac{12}{5} \right)$. - \item $u$ behaves like $\frac{1}{x}$ around its vertical asymptote at $4$. - \item Using \vref{rat:def:longrun} the equation of the horizontal asymptote of $u$ is $y=-4$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,10}, - width=\textwidth, - ] - \addplot[asymptote,domain=-20:20]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-4}); - \addplot[soldot] coordinates{(-3,0)(0,2.4)}node[axisnode,anchor=south east]{$\left( 0,\frac{12}{5} \right)$}; - \addplot[holdot] coordinates{(3,12)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:asympandholep1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=-4*(x+3)/(x-5);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,10}, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:3.6666,samples=50]{f}; - \addplot[pccplot] expression[domain=7:10]{f}; - \addplot[asymptote,domain=-20:20]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{-4}); - \addplot[soldot] coordinates{(-3,0)(0,2.4)}node[axisnode,anchor=south east]{$\left( 0,\frac{12}{5} \right)$}; - \addplot[holdot] coordinates{(3,12)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:asympandholep2} - \end{subfigure}% - \caption{$y=\dfrac{-4(x+3)}{x-5}$} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:sketchtwoasymp} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $w$ - that has formula - \[ - w(x)=\frac{2(x+3)(x-5)}{(x+5)(x-4)} - \] - \begin{pccsolution} - \begin{steps} - \item $w$ has vertical asymptotes at $-5$ and $4$. $w$ does not have - any holes. The curve of $w$ will have $3$ branches. - \item $w$ has simple zeros at $-3$ and $5$. The vertical intercept of $w$ - is $\left( 0,\frac{3}{2} \right)$. - \item $w$ behaves like $\frac{1}{x}$ around both of its vertical - asymptotes. - \item The degree of the numerator of $w$ is $2$ and the degree of the - denominator of $w$ is also $2$. Using the ratio of the leading coefficients - 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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[soldot] coordinates{(-3,0)(5,0)}; - \addplot[soldot] coordinates{(0,1.5)}node[axisnode,anchor=north west]{$\left( 0,\frac{3}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:sketchtwoasymptp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=2*(x+3)*(x-5)/( (x+5)*(x-4));}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[soldot] coordinates{(-3,0)(5,0)}; - \addplot[soldot] coordinates{(0,1.5)}node[axisnode,anchor=north west]{$\left( 0,\frac{3}{2} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.56708]{f}; - \addplot[pccplot] expression[domain=-4.63511:3.81708]{f}; - \addplot[pccplot] expression[domain=4.13511:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:sketchtwoasymptp2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:2asympnozeros} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $f$ - that has formula - \[ - f(x)=\frac{100}{(x+5)(x-4)^2} - \] - \begin{pccsolution} - \begin{steps} - \item $f$ has vertical asymptotes at $-5$ and $4$. $f$ does not have - any holes. The curve of $f$ will have $3$ branches. - \item $f$ does not have any zeros (since $100\ne 0$). The vertical intercept of $f$ - is $\left( 0,\frac{5}{4} \right)$. - \item $f$ behaves like $\frac{1}{x}$ around $-5$ and behaves like $\frac{1}{x^2}$ - around $4$. - \item The degree of the numerator of $f$ is $0$ and the degree of the - 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 - be able to find local minimums more precisely. - \end{steps} - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htbp] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(0,1.25)}node[axisnode,anchor=south east]{$\left( 0,\frac{5}{4} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2asympnozerosp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=100/( (x+5)*(x-4)^2);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(0,1.25)}node[axisnode,anchor=south east]{$\left( 0,\frac{5}{4} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.12022]{f}; - \addplot[pccplot] expression[domain=-4.87298:2.87298,samples=50]{f}; - \addplot[pccplot] expression[domain=5:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2asympnozerosp2} - \end{subfigure}% - \caption{$y=\dfrac{100}{(x+5)(x-4)^2}$} - \end{figure} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{rat:ex:2squaredasymp} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $g$ - that has formula - \[ - g(x)=\frac{50(2-x)}{(x+3)^2(x-5)^2} - \] - \begin{pccsolution} - \begin{steps} - \item $g$ has vertical asymptotes at $-3$ and $5$. $g$ does - not have any holes. The curve of $g$ will have $3$ branches. - \item $g$ has a simple zero at $2$. The vertical intercept of $g$ is - $\left( 0,\frac{4}{9} \right)$. - \item $g$ behaves like $\frac{1}{x^2}$ around both of its - vertical asymptotes. - \item The degree of the numerator of $g$ is $1$ and the degree of the denominator - of $g$ is $4$. Using \vref{rat:def:longrun}, we calculate that - the horizontal asymptote of $g$ has equation $y=0$. - \item The details that we have found so far have been drawn in - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(2,0)(0,4/9)}node[axisnode,anchor=south west]{$\left( 0,\frac{4}{9} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2squaredasymp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=50*(2-x)/( (x+3)^2*(x-5)^2);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(2,0)(0,4/9)}node[axisnode,anchor=south west]{$\left( 0,\frac{4}{9} \right)$}; - \addplot[pccplot] expression[domain=-10:-3.61504]{f}; - \addplot[pccplot] expression[domain=-2.3657:4.52773]{f}; - \addplot[pccplot] expression[domain=5.49205:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2squaredasymp2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:doublezero} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $g$ - that has formula - \[ - h(x)=\frac{(x-3)^2}{(x+4)(x-6)} - \] - \begin{pccsolution} - \begin{steps} - \item $h$ has vertical asymptotes at $-4$ and $6$. $h$ does - not have any holes. The curve of $h$ will have $3$ branches. - \item $h$ has a zero at $3$ that has \emph{multiplicity $2$}. - The vertical intercept of $h$ is - $\left( 0,-\frac{3}{8} \right)$. - \item $h$ behaves like $\frac{1}{x}$ around both of its - vertical asymptotes. - \item The degree of the numerator of $h$ is $2$ and the degree of the denominator - of $h$ is $2$. Using \vref{rat:def:longrun}, we calculate that - the horizontal asymptote of $h$ has equation $y=1$. - \item The details that we have found so far have been drawn in - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - ytick={-3,3}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-4},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot] coordinates{(3,0)(0,-3/8)}node[axisnode,anchor=north west]{$\left( 0,-\frac{3}{8} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:doublezerop1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-3)^2/((x+4)*(x-6));}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - ytick={-3,3}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-4},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot] coordinates{(3,0)(0,-3/8)}node[axisnode,anchor=north west]{$\left( 0,-\frac{3}{8} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.20088]{f}; - \addplot[pccplot] expression[domain=-3.16975:5.83642,samples=50]{f}; - \addplot[pccplot] expression[domain=6.20088:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:doublezerop2} - \end{subfigure}% - \caption{$y=\dfrac{(x-3)^2}{(x+4)(x-6)}$} - \end{figure} - \begin{exercises} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{rat:step:last}]\label{rat:prob:deduce} - \pccname{Katie} is working on graphing rational functions. She - has been concentrating on functions that have the form - \begin{equation}\label{rat:eq:deducecurve} - f(x)=\frac{a(x-b)}{x-c} - \end{equation} - Katie notes that functions with this type of formula have a zero - 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 - more thing to do to complete the graphs| follow \cref{rat:step:last}. - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,12/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \addplot[pccplot] expression[domain=-10:-5.42857]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(2,0)(0,-3/2)}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-3}); - \addplot[pccplot] expression[domain=-10:3.53846,samples=50]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(6,0)(0,3)}; - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[pccplot] expression[domain=-10:3.5,samples=50]{f}; - \addplot[pccplot] expression[domain=4.3333:10]{f}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,12/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve1} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(2,0)(0,-3/2)}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve2} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(6,0)(0,3)}; - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve4} - \end{subfigure} - \caption{Graphs for \cref{rat:prob:deduce}} - \label{rat:fig:deducecurve} - \end{widepage} - \end{figure} - - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{rat:step:last} for more complicated rational functions]\label{rat:prob:deducehard} - \pccname{David} is also working on graphing rational functions, and - has been concentrating on functions that have the form - \[ - r(x)=\frac{a(x-b)(x-c)}{(x-d)(x-e)} - \] - David notices that functions with this type of formula have simple zeros - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(6,0)(0,9/2)}; - \addplot[asymptote,domain=-10:10]({-1},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[pccplot] expression[domain=-10:-1.24276]{f}; - \addplot[pccplot] expression[domain=-0.6666:3.66667]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(2,0)(0,3/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \addplot[pccplot] expression[domain=-10:-5.4861]{f}; - \addplot[pccplot] expression[domain=-4.68395:5.22241]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(7,0)(0,1.4)}; - \addplot[asymptote,domain=-10:10]({-6},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[pccplot] expression[domain=-10:-6.91427]{f}; - \addplot[pccplot] expression[domain=-5.42252:4.66427]{f}; - \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} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(6,0)(0,9/2)}; - \addplot[asymptote,domain=-10:10]({-1},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard1} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(2,0)(0,3/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard2} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(7,0)(0,1.4)}; - \addplot[asymptote,domain=-10:10]({-6},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard3} - \end{subfigure}% - \hfill - \caption{Graphs for \cref{rat:prob:deducehard}} - \label{rat:fig:deducehard} - \end{widepage} - \end{figure} - %=================================== - % Author: Adams (Hughes) - % Date: March 2012 - %=================================== - \begin{problem}[\Crefrange{rat:step:first}{rat:step:last}] - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of - each of the following functions - \fixthis{need 2 more subproblems here} - \begin{multicols}{4} - \begin{subproblem} - $y=\dfrac{4}{x+2}$ - \begin{shortsolution} - Vertical intercept: $(0,2)$; vertical asymptote: $x=-2$, horizontal asymptote: $y=0$. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-2.8]{4/(x+2)}; - \addplot[pccplot] expression[domain=-1.2:5]{4/(x+2)}; - \addplot[soldot]coordinates{(0,2)}; - \addplot[asymptote,domain=-5:5]({-2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{2x-1}{x^2-9}$ - \begin{shortsolution} - 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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-3.23974]{(2*x-1)/(x^2-9)}; - \addplot[pccplot,samples=50] expression[domain=-2.77321:2.83974]{(2*x-1)/(x^2-9)}; - \addplot[pccplot] expression[domain=3.17321:5]{(2*x-1)/(x^2-9)}; - \addplot[soldot]coordinates{(0,1/9)(1/2,0)}; - \addplot[asymptote,domain=-5:5]({-3},{x}); - \addplot[asymptote,domain=-5:5]({3},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{x+3}{x-5}$ - \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, - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:3.666]{(x+3)/(x-5)}; - \addplot[pccplot] expression[domain=7:10]{(x+3)/(x-5)}; - \addplot[asymptote,domain=-5:5]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot]coordinates{(0,-3/5)(-3,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{2x+3}{3x-1}$ - \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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:0.1176]{f}; - \addplot[pccplot] expression[domain=0.6153:5]{f}; - \addplot[asymptote,domain=-5:5]({1/3},{x}); - \addplot[asymptote,domain=-5:5]({x},{2/3}); - \addplot[soldot]coordinates{(0,-3)(-3/2,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{4-x^2}{x^2-9}$ - \begin{shortsolution} - 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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-3.20156]{f}; - \addplot[pccplot,samples=50] expression[domain=-2.85774:2.85774]{f}; - \addplot[pccplot] expression[domain=3.20156:5]{f}; - \addplot[asymptote,domain=-5:5]({-3},{x}); - \addplot[asymptote,domain=-5:5]({3},{x}); - \addplot[asymptote,domain=-5:5]({x},{-1}); - \addplot[soldot] coordinates{(-2,0)(2,0)(0,-4/9)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{(4x+5)(3x-4)}{(2x+5)(x-5)}$ - \begin{shortsolution} - 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, - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,0,...,10}, - minor ytick={-15,-5,...,15}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:-2.73416]{f}; - \addplot[pccplot] expression[domain=-2.33689:4.2792]{f}; - \addplot[pccplot] expression[domain=6.26988:10]{f}; - \addplot[asymptote,domain=-20:20]({-5/2},{x}); - \addplot[asymptote,domain=-20:20]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{6}); - \addplot[soldot]coordinates{(0,4/5)(-5/4,0)(4/3,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Inverse functions] - Each of the following rational functions are invertible - \[ - F(x)=\frac{2x+1}{x-3}, \qquad G(x)= \frac{1-4x}{x+3} - \] - \begin{subproblem} - State the domain of each function. - \begin{shortsolution} - \begin{itemize} - \item The domain of $F$ is $(-\infty,3)\cup(3,\infty)$. - \item The domain of $G$ is $(-\infty,-3)\cup(-3,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Find the inverse of each function, and state its domain. - \begin{shortsolution} - \begin{itemize} - \item $F^{-1}(x)=\frac{3x+1}{x-2}$; the domain of $F^{-1}$ is $(-\infty,2)\cup(2,\infty)$. - \item $G^{-1}(x)=\frac{3x+1}{x+4}$; the domain of $G^{-1}$ is $(-\infty,-4)\cup(-4,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Hence state the range of the original functions. - \begin{shortsolution} - \begin{itemize} - \item The range of $F$ is the domain of $F^{-1}$, which is $(-\infty,2)\cup(2,\infty)$. - \item The range of $G$ is the domain of $G^{-1}$, which is $(-\infty,-4)\cup(-4,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - State the range of each inverse function. - \begin{shortsolution} - \begin{itemize} - \item The range of $F^{-1}$ is the domain of $F$, which is $(-\infty,3)\cup(3,\infty)$. - \item The range of $G^{-1}$ is the domain of $G$, which is $(-\infty,-3)\cup(-3,\infty)$. - \end{itemize}<++> - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Composition] - Let $r$ and $s$ be the rational functions that have formulas - \[ - r(x)=\frac{3}{x^2},\qquad s(x)=\frac{4-x}{x+5} - \] - Evaluate each of the following. - \begin{multicols}{3} - \begin{subproblem} - $(r\circ s)(0)$ - \begin{shortsolution} - $\frac{75}{16}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(0)$ - \begin{shortsolution} - $(s\circ r)(0)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r\circ s)(2)$ - \begin{shortsolution} - $\frac{147}{4}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(3)$ - \begin{shortsolution} - $192$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(4)$ - \begin{shortsolution} - $(s\circ r)(4)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(x)$ - \begin{shortsolution} - $\dfrac{4x^2-3}{1+5x^2}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Piecewise rational functions] - The function $R$ has formula - \[ - R(x)= - \begin{dcases} - \frac{2}{x+3}, & x<-5 \\ - \frac{x-4}{x-10}, & x\geq -5 - \end{dcases} - \] - Evaluate each of the following. - \begin{multicols}{4} - \begin{subproblem} - $R(-6)$ - \begin{shortsolution} - $-\frac{2}{3}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(-5)$ - \begin{shortsolution} - $\frac{3}{5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(-3)$ - \begin{shortsolution} - $\frac{7}{13}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(5)$ - \begin{shortsolution} - $-\frac{1}{5}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \begin{subproblem} - What is the domain of $R$? - \begin{shortsolution} - $(-\infty,10)\cup(10,\infty)$ - \end{shortsolution} - \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}$ - \begin{shortsolution} - \begin{enumerate} - \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, - xmin=-20,xmax=20, - ymin=-30,ymax=30, - xtick={-10,10}, - minor xtick={-15,-5,...,15}, - minor ytick={-10,10}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot,samples=50] expression[domain=-20:3.54724]{f}; - \addplot[pccplot,samples=50] expression[domain=4.80196:20]{f}; - \addplot[asymptote,domain=-30:30]({4},{x}); - \end{axis} - \end{tikzpicture} - \end{enumerate} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{x^3(x+3)}{x-5}$ - \begin{shortsolution} - \begin{enumerate} - \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, - xmin=-10,xmax=10, - ymin=-500,ymax=2500, - xtick={-8,-6,...,8}, - ytick={500,1000,1500,2000}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot,samples=50] expression[domain=-10:4]{f}; - \addplot[pccplot] expression[domain=5.6068:9.777]{f}; - \addplot[asymptote,domain=-500:2500]({5},{x}); - \end{axis} - \end{tikzpicture} - \end{enumerate} - \end{shortsolution} - \end{subproblem} diff --git a/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex b/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex deleted file mode 100644 index ae704bd4bc1..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/sampleBEFORE.tex +++ /dev/null @@ -1,5819 +0,0 @@ -% arara: indent: {overwrite: true, trace: on} -% A sample chapter file- it contains a lot of -% environments, including tabulars, align, etc -% -% Don't try and compile this file using pdflatex etc, just -% compare the *format* of it to the format of the -% sampleAFTER.tex -% -% In particular, compare the tabular and align-type -% environments before and after running the script - -\section{Polynomial functions} - \reformatstepslist{P} % the steps list should be P1, P2, \ldots - In your previous mathematics classes you have studied \emph{linear} and - \emph{quadratic} functions. The most general forms of these types of - functions can be represented (respectively) by the functions $f$ - and $g$ that have formulas - \begin{equation}\label{poly:eq:linquad} - f(x)=mx+b, \qquad g(x)=ax^2+bx+c - \end{equation} - We know that $m$ is the slope of $f$, and that $a$ is the \emph{leading coefficient} - of $g$. We also know that the \emph{signs} of $m$ and $a$ completely - determine the behavior of the functions $f$ and $g$. For example, if $m>0$ - then $f$ is an \emph{increasing} function, and if $m<0$ then $f$ is - 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} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$m>0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{-(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$m<0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a>0$} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{-(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a<0$} - \end{subfigure} - \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 - %=================================== - \begin{essentialskills} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Quadratic functions] - Every quadratic function has the form $y=ax^2+bx+c$; state the value - of $a$ for each of the following functions, and hence decide if the - parabola that represents the function opens upward or downward. - \begin{multicols}{2} - \begin{subproblem} - $F(x)=x^2+3$ - \begin{shortsolution} - $a=1$; the parabola opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $G(t)=4-5t^2$ - \begin{shortsolution} - $a=-5$; the parabola opens downward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $H(y)=4y^2-96y+8$ - \begin{shortsolution} - $a=4$; the parabola opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $K(z)=-19z^2$ - \begin{shortsolution} - $m=-19$; the parabola opens downward. - \end{shortsolution} - \end{subproblem} - \end{multicols} - Now let's generalize our findings for the most general quadratic function $g$ - that has formula $g(x)=a_2x^2+a_1x+a_0$. Complete the following sentences. - \begin{subproblem} - When $a_2>0$, the parabola that represents $y=g(x)$ opens $\ldots$ - \begin{shortsolution} - When $a_2>0$, the parabola that represents the function opens upward. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - When $a_2<0$, the parabola that represents $y=g(x)$ opens $\ldots$ - \begin{shortsolution} - When $a_2<0$, the parabola that represents the function opens downward. - \end{shortsolution} - \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? - \begin{pccdefinition}[Power functions] - Power functions have the form - \[ - 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 - %=================================== - \begin{pccexample}[Power functions with odd positive exponents] - \label{poly:ex:oddpow} - Graph each of the following functions, state their domain, and their - long-run behavior as $x\rightarrow\pm\infty$ - \[ - f(x)=x^3, \qquad g(x)=x^5, \qquad h(x)=x^7 - \] - \begin{pccsolution} - The functions $f$, $g$, and $h$ are plotted in \cref{poly:fig:oddpow}. - The domain of each of the functions $f$, $g$, and $h$ is $(-\infty,\infty)$. Note that - 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 - \end{align*} - The same results hold for $g$ and $h$. - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htb] - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-1.5,xmax=1.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,1.0}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\textwidth, - legend pos=north west, - ] - \addplot expression[domain=-1.5:1.5]{x^3}; - \addplot expression[domain=-1.379:1.379]{x^5}; - \addplot expression[domain=-1.258:1.258]{x^7}; - \addplot[soldot]coordinates{(-1,-1)} node[axisnode,anchor=north west]{$(-1,-1)$}; - \addplot[soldot]coordinates{(1,1)} node[axisnode,anchor=south east]{$(1,1)$}; - \legend{$f$,$g$,$h$} - \end{axis} - \end{tikzpicture} - \caption{Odd power functions} - \label{poly:fig:oddpow} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-2.5,xmax=2.5, - ymin=-5,ymax=5, - xtick={-2.0,-1.5,...,2.0}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\textwidth, - legend pos=south east, - ] - \addplot expression[domain=-2.236:2.236]{x^2}; - \addplot expression[domain=-1.495:1.495]{x^4}; - \addplot expression[domain=-1.307:1.307]{x^6}; - \addplot[soldot]coordinates{(-1,1)} node[axisnode,anchor=east]{$(-1,1)$}; - \addplot[soldot]coordinates{(1,1)} node[axisnode,anchor=west]{$(1,1)$}; - \legend{$F$,$G$,$H$} - \end{axis} - \end{tikzpicture} - \caption{Even power functions} - \label{poly:fig:evenpow} - \end{minipage}% - \end{figure} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Power functions with even positive exponents]\label{poly:ex:evenpow}% - Graph each of the following functions, state their domain, and their - long-run behavior as $x\rightarrow\pm\infty$ - \[ - F(x)=x^2, \qquad G(x)=x^4, \qquad H(x)=x^6 - \] - \begin{pccsolution} - The functions $F$, $G$, and $H$ are plotted in \cref{poly:fig:evenpow}. The domain - of each of the functions is $(-\infty,\infty)$. Note that 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 - \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) - \begin{subproblem} - $f(x)=-x^3, \qquad g(x)=-x^5, \qquad h(x)=-x^7$ - \begin{shortsolution} - The functions $f$, $g$, and $h$ have domain $(-\infty,\infty)$ and - are graphed below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-1.5,xmax=1.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,0.5}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - legend pos=north east, - ] - \addplot expression[domain=-1.5:1.5]{-x^3}; - \addplot expression[domain=-1.379:1.379]{-x^5}; - \addplot expression[domain=-1.258:1.258]{-x^7}; - \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 - \end{align*} - The same is true for $g$ and $h$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $F(x)=-x^2, \qquad G(x)=-x^4, \qquad H(x)=-x^6$ - \begin{shortsolution} - The functions $F$, $G$, and $H$ have domain $(-\infty,\infty)$ and - are graphed below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-2.5,xmax=2.5, - ymin=-5,ymax=5, - xtick={-1.0,-0.5,...,0.5}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - legend pos=north east, - ] - \addplot expression[domain=-2.236:2.236]{-x^2}; - \addplot expression[domain=-1.495:1.495]{-x^4}; - \addplot expression[domain=-1.307:1.307]{-x^6}; - \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 - \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 - with our opening discussion about linear and quadratic functions (see - $f$ and $g$ in \cref{poly:eq:linquad}) then there is every chance - that you'll be able to master polynomial functions as well; just remember - that polynomial functions are a natural generalization of linear - 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 - %=================================== - \begin{pccdefinition}[Polynomial functions] - Polynomial functions have the form - \[ - p(x)=a_nx^n+a_{n-1}x^{n-1}+\ldots+a_1x+a_0 - \] - where $a_n$, $a_{n-1}$, $a_{n-2}$, \ldots, $a_0$ are real numbers. - \begin{itemize} - \item We call $n$ the degree of the polynomial, and require that $n$ - is a non-negative integer; - \item $a_n$, $a_{n-1}$, $a_{n-2}$, \ldots, $a_0$ are called the coefficients; - \item We typically write polynomial functions in descending powers of $x$. - \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 - %=================================== - \begin{pccexample}[Polynomial or not] - Identify the following functions as polynomial or not; if the function - is a polynomial, state its degree. - \begin{multicols}{3} - \begin{enumerate} - \item $p(x)=x^2-3$ - \item $q(x)=-4x^{\nicefrac{1}{2}}+10$ - \item $r(x)=10x^5$ - \item $s(x)=x^{-2}+x^{23}$ - \item $f(x)=-8$ - \item $g(x)=3^x$ - \item $h(x)=\sqrt[3]{x^7}-x^2+x$ - \item $k(x)=4x(x+2)(x-3)$ - \item $j(x)=x^2(x-4)(5-x)$ - \end{enumerate} - \end{multicols} - \begin{pccsolution} - \begin{enumerate} - \item $p$ is a polynomial, and its degree is $2$. - \item $q$ is \emph{not} a polynomial, because $\frac{1}{2}$ is not an integer. - \item $r$ is a polynomial, and its degree is $5$. - \item $s$ is \emph{not} a polynomial, because $-2$ is not a positive integer. - \item $f$ is a polynomial, and its degree is $0$. - \item $g$ is \emph{not} a polynomial, because the independent - variable, $x$, is in the exponent. - \item $h$ is \emph{not} a polynomial, because $\frac{7}{3}$ is not an integer. - \item $k$ is a polynomial, and its degree is $3$. - \item $j$ is a polynomial, and its degree is $4$. - \end{enumerate} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Typical graphs]\label{poly:ex:typical} - \Cref{poly:fig:typical} shows graphs of some polynomial functions; - the ticks have deliberately been left off the axis to allow us to concentrate - on the features of each graph. Note in particular that: - \begin{itemize} - \item \cref{poly:fig:typical1} shows a degree-$1$ polynomial (you might also - classify the function as linear) whose leading coefficient, $a_1$, is positive. - \item \cref{poly:fig:typical2} shows a degree-$2$ polynomial (you might also - classify the function as quadratic) whose leading coefficient, $a_2$, is positive. - \item \cref{poly:fig:typical3} shows a degree-$3$ polynomial whose leading coefficient, $a_3$, - is positive| compare its overall - shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. - \item \cref{poly:fig:typical4} shows a degree-$4$ polynomial whose leading coefficient, $a_4$, - is positive|compare its overall shape and long-run behavior to the functions described in \cref{poly:ex:evenpow}. - \item \cref{poly:fig:typical5} shows a degree-$5$ polynomial whose leading coefficient, $a_5$, - is positive| compare its overall - shape and long-run behavior to the functions described in \cref{poly:ex:oddpow}. - \end{itemize} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{\textwidth/6} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$a_1>0$} - \label{poly:fig:typical1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{(x^2-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_2>0$} - \label{poly:fig:typical2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-7.5:7.5]{0.05*(x+6)*x*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_3>0$} - \label{poly:fig:typical3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-2.35:5.35,samples=100]{0.2*(x-5)*x*(x-3)*(x+2)}; - \end{axis} - \end{tikzpicture} - \caption{$a_4>0$} - \label{poly:fig:typical4} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\textwidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-5.5:6.3,samples=100]{0.01*(x+2)*x*(x-3)*(x+5)*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{$a_5>0$} - \label{poly:fig:typical5} - \end{subfigure} - \end{widepage} - \caption{Graphs to illustrate typical curves of polynomial functions.} - \label{poly:fig:typical} - \end{figure} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{doyouunderstand} - \begin{problem} - Use \cref{poly:ex:typical} and \cref{poly:fig:typical} to help you sketch - the graphs of polynomial functions that have negative leading coefficients| note - that there are many ways to do this! The intention with this problem - is to use your knowledge of transformations- in particular, \emph{reflections}- - to guide you. - \begin{shortsolution} - $a_1<0$: - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-10:8]{-(x+2)}; - \end{axis} - \end{tikzpicture} - - $a_2<0$ - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-4:4]{-(x^2-6)}; - \end{axis} - \end{tikzpicture} - - $a_3<0$ - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \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, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \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, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - xtick={-11}, - ytick={-11}, - ] - \addplot expression[domain=-5.5:6.3,samples=100]{-0.01*(x+2)*x*(x-3)*(x+5)*(x-6)}; - \end{axis} - \end{tikzpicture} - \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 - %=================================== - \begin{pccexample}[Multiple zeros] - Consider the polynomial functions $p$, $q$, and $r$ which are - graphed in \cref{poly:fig:moremultiple}. - The formulas for $p$, $q$, and $r$ are as follows - \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 - \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} - \begin{tikzpicture} - \begin{axis}[ - xmin=-6,xmax=5, - ymin=-30,ymax=200, - xtick={-4,-2,...,4}, - width=\textwidth, - ] - \addplot expression[domain=-5.63733:4.63733,samples=50]{(x-3)^2*(x+4)^2}; - \addplot[soldot]coordinates{(3,0)(-4,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=p(x)$} - \label{poly:fig:bouncep} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-3,xmax=4, - xtick={-2,...,3}, - ymin=-60,ymax=40, - width=\textwidth, - ] - \addplot+[samples=50] expression[domain=-2.49011:3.11054]{x*(x+2)^2*(x-1)^2*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(0,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=q(x)$} - \label{poly:fig:bounceq} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-2,xmax=4, - xtick={-1,...,3}, - ymin=-40,ymax=40, - width=\textwidth, - ] - \addplot expression[domain=-1.53024:3.77464,samples=50]{x*(x-3)^3*(x+1)^2}; - \addplot[soldot]coordinates{(-1,0)(0,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=r(x)$} - \label{poly:fig:bouncer} - \end{subfigure} - \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 - \begin{itemize} - \item if the factor $(x-a)$ is repeated an even number of times, the graph of $y=p(x)$ does not - cross the $x$ axis at $a$, but `bounces' off the horizontal axis at $a$. - \item if the factor $(x-a)$ is repeated an odd number of times, the graph of $y=p(x)$ crosses the - horizontal axis at $a$, but it looks `flattened' there - \end{itemize} - If $n=1$, then we say that $p$ has a \emph{simple} zero at $a$. - \end{pccdefinition} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{pccexample}[Find a formula] - Find formulas for the polynomial functions, $p$ and $q$, graphed in \cref{poly:fig:findformulademoboth}. - \begin{figure}[!htb] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - minor xtick={-3,-1,...,3}, - ytick={-8,-6,...,8}, - width=\textwidth, - grid=both] - \addplot expression[domain=-3.25842:2.25842,samples=50]{-x*(x-2)*(x+3)*(x+1)}; - \addplot[soldot]coordinates{(1,8)}node[axisnode,inner sep=.35cm,anchor=west]{$(1,8)$}; - \addplot[soldot]coordinates{(-3,0)(-1,0)(0,0)(2,0)}; - \end{axis} - \end{tikzpicture} - \caption{$p$} - \label{poly:fig:findformulademo} - \end{subfigure} - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - minor xtick={-3,-1,...,3}, - ytick={-8,-6,...,8}, - width=\textwidth, - grid=both] - \addplot expression[domain=-4.33:4.08152]{-.25*(x+2)^2*(x-3)}; - \addplot[soldot]coordinates{(2,4)}node[axisnode,anchor=south west]{$(2,4)$}; - \addplot[soldot]coordinates{(-2,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$q$} - \label{poly:fig:findformulademo1} - \end{subfigure} - \caption{} - \label{poly:fig:findformulademoboth} - \end{figure} - \begin{pccsolution} - \begin{enumerate} - \item We begin by noting that the horizontal intercepts of $p$ are $(-3,0)$, $(-1,0)$, $(0,0)$ and $(2,0)$. - We also note that each zero is simple (multiplicity $1$). - If we assume that $p$ has no other zeros, then we can start by writing - \begin{align*} - p(x) & =(x+3)(x+1)(x-0)(x-2) \\ - & =x(x+3)(x+1)(x-2) \\ - \end{align*} - According to \cref{poly:fig:findformulademo}, the point $(1,8)$ lies - on the curve $y=p(x)$. - Let's check if the formula we have written satisfies this requirement - \begin{align*} - p(1) & = (1)(4)(2)(-1) \\ - & = -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 - \[ - p(x)=kx(x+3)(x+1)(x-2) - \] - Then $p(1)=-8k$, and if this is to equal $8$, then $k=-1$. Therefore - the formula for $p(x)$ is - \[ - p(x)=-x(x+3)(x+1)(x-2) - \] - \item The function $q$ has a zero at $-2$ of multiplicity $2$, and zero of - multiplicity $1$ at $3$ (so $3$ is a simple zero of $q$); we can therefore assume that $q$ has the form - \[ - q(x)=k(x+2)^2(x-3) - \] - where $k$ is some real number. In order to find $k$, we use the given ordered pair, $(2,4)$, and - evaluate $p(2)$ - \begin{align*} - p(2) & =k(4)^2(-1) \\ - & =-16k - \end{align*} - We solve the equation $4=-8k$ and obtain $k=-\frac{1}{4}$ and conclude that the - formula for $q(x)$ is - \[ - q(x)=-\frac{1}{4}(x+2)^2(x-3) - \] - \end{enumerate} - \end{pccsolution} - \end{pccexample} - - - \fixthis{Chris: need sketching polynomial problems} - \begin{pccspecialcomment}[Steps to follow when sketching polynomial functions] - \begin{steps} - \item \label{poly:step:first} Determine the degree of the polynomial, - its leading term and leading coefficient, and hence determine - the long-run behavior of the polynomial| does it behave like $\pm x^2$ or $\pm x^3$ - as $x\rightarrow\pm\infty$? - \item Determine the zeros and their multiplicity. Mark all zeros - and the vertical intercept on the graph using solid circles $\bullet$. - \item \label{poly:step:last} Deduce the overall shape of the curve, and sketch it. If there isn't - enough information from the previous steps, then construct a table of values. - \end{steps} - Remember that until we have the tools of calculus, we won't be able to - find the exact coordinates of local minimums, local maximums, and points - of inflection. - \end{pccspecialcomment} - Before we demonstrate some examples, it is important to remember the following: - \begin{itemize} - \item our sketches will give a good representation of the overall - shape of the graph, but until we have the tools of calculus (from MTH 251) - we can not find local minimums, local maximums, and inflection points algebraically. This - means that we will make our best guess as to where these points are. - \item we will not concern ourselves too much with the vertical scale (because of - our previous point)| we will, however, mark the vertical intercept (assuming there is one), - and any horizontal asymptotes. - \end{itemize} - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{poly:ex:simplecubic} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $p$ - that has formula - \[ - p(x)=\frac{1}{2}(x-4)(x-1)(x+3) - \] - \begin{pccsolution} - \begin{steps} - \item $p$ has degree $3$. The leading term of $p$ is $\frac{1}{2}x^3$, so the leading coefficient of $p$ - is $\frac{1}{2}$. The long-run behavior of $p$ is therefore similar to that of $x^3$. - \item The zeros of $p$ are $-3$, $1$, and $4$; each zero is simple (i.e, it has multiplicity $1$). - This means that the curve of $p$ cuts the horizontal axis at each zero. The vertical - intercept of $p$ is $(0,6)$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=15, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(1,0)(4,0)(0,6)}node[axisnode,anchor=south west]{$(0,6)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:simplecubicp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=15, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(1,0)(4,0)(0,6)}node[axisnode,anchor=south west]{$(0,6)$}; - \addplot[pccplot] expression[domain=-3.57675:4.95392,samples=100]{.5*(x-4)*(x-1)*(x+3)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:simplecubicp2} - \end{subfigure}% - \caption{$y=\dfrac{1}{2}(x-4)(x-1)(x+3)$} - \label{poly:fig:simplecubic} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{poly:ex:degree5} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $q$ - that has formula - \[ - q(x)=\frac{1}{200}(x+7)^2(2-x)(x-6)^2 - \] - \begin{pccsolution} - \begin{steps} - \item $q$ has degree $4$. The leading term of $q$ is - \[ - -\frac{1}{200}x^5 - \] - so the leading coefficient of $q$ is $-\frac{1}{200}$. The long-run behavior of $q$ - is therefore similar to that of $-x^5$. - \item The zeros of $q$ are $-7$ (multiplicity 2), $2$ (simple), and $6$ (multiplicity $2$). - The curve of $q$ bounces off the horizontal axis at the zeros with multiplicity $2$ and - cuts the horizontal axis at the simple zeros. The vertical intercept of $q$ is $\left( 0,\frac{441}{25} \right)$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=40, - xtick={-8,-6,...,8}, - ytick={-5,0,...,35}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-7,0)(2,0)(6,0)(0,441/25)}node[axisnode,anchor=south west]{$\left( 0, \frac{441}{25} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree5p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=40, - xtick={-8,-6,...,8}, - ytick={-5,0,...,35}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-7,0)(2,0)(6,0)(0,441/25)}node[axisnode,anchor=south west]{$\left( 0, \frac{441}{25} \right)$}; - \addplot[pccplot] expression[domain=-8.83223:7.34784,samples=50]{1/200*(x+7)^2*(2-x)*(x-6)^2}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree5p2} - \end{subfigure}% - \caption{$y=\dfrac{1}{200}(x+7)^2(2-x)(x-6)^2$} - \label{poly:fig:degree5} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample} - Use \crefrange{poly:step:first}{poly:step:last} to sketch a graph of the function $r$ - that has formula - \[ - r(x)=\frac{1}{100}x^3(x+4)(x-4)(x-6) - \] - \begin{pccsolution} - \begin{steps} - \item $r$ has degree $6$. The leading term of $r$ is - \[ - \frac{1}{100}x^6 - \] - so the leading coefficient of $r$ is $\frac{1}{100}$. The long-run behavior of $r$ - is therefore similar to that of $x^6$. - \item The zeros of $r$ are $-4$ (simple), $0$ (multiplicity $3$), $4$ (simple), - and $6$ (simple). The vertical intercept of $r$ is $(0,0)$. The curve of $r$ - cuts the horizontal axis at the simple zeros, and goes through the axis - at $(0,0)$, but does so in a flattened way. - \item We mark the zeros and vertical intercept on \cref{poly:fig:degree6p1}. Given that - 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} - \begin{axis}[ - xmin=-5,xmax=10, - ymin=-20,ymax=10, - xtick={-4,-2,...,8}, - ytick={-15,-10,...,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,0)(4,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree6p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=10, - ymin=-20,ymax=10, - xtick={-4,-2,...,8}, - ytick={-15,-10,...,5}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,0)(4,0)(6,0)}; - \addplot[pccplot] expression[domain=-4.16652:6.18911,samples=100]{1/100*(x+4)*x^3*(x-4)*(x-6)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:degree6p2} - \end{subfigure}% - \caption{$y=\dfrac{1}{100}(x+4)x^3(x-4)(x-6)$} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[An open-topped box] - A cardboard company makes open-topped boxes for their clients. The specifications - dictate that the box must have a square base, and that it must be open-topped. - The company uses sheets of cardboard that are $\unit[1200]{cm^2}$. Assuming that - the base of each box has side $x$ (measured in cm), it can be shown that the volume of each box, $V(x)$, - has formula - \[ - V(x)=\frac{x}{4}(1200-x^2) - \] - Find the dimensions of the box that maximize the volume. - \begin{pccsolution} - We graph $y=V(x)$ in \cref{poly:fig:opentoppedbox}. Note that because - $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} - \begin{axis}[framed, - xmin=-50,xmax=50, - ymin=-5000,ymax=5000, - xtick={-40,-30,...,40}, - minor xtick={-45,-35,...,45}, - minor ytick={-3000,-1000,1000,3000}, - width=.75\textwidth, - height=.5\textwidth, - grid=both] - \addplot[pccplot,dashed,<-] expression[domain=-40:0,samples=50]{x/4*(1200-x^2)}; - \addplot[pccplot,-] expression[domain=0:34.64,samples=50]{x/4*(1200-x^2)}; - \addplot[pccplot,dashed,->] expression[domain=34.64:40,samples=50]{x/4*(1200-x^2)}; - \addplot[soldot] coordinates{(20,4000)}; - \end{axis} - \end{tikzpicture} - \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. - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample}\label{poly:ex:complx} - Consider the polynomial function $c$ that has formula - \[ - c(x)=x(x^2+1) - \] - It is clear that $c$ has degree $3$, and that $c$ has a (simple) zero at $0$. Does - $c$ have any other zeros, i.e, can we find any values of $x$ that satisfy the equation - \begin{equation}\label{poly:eq:complx} - 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} - \Cref{poly:ex:complx} shows that not every degree-$3$ polynomial has $3$ - \emph{real} zeros; however, if we are prepared to venture into the complex numbers, - then we can state the following theorem. - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccspecialcomment}[The fundamental theorem of algebra] - Every polynomial function of degree $n$ has $n$ roots, some of which may - be complex, and some may be repeated. - \end{pccspecialcomment} - \fixthis{Fundamental theorem of algebra: is this wording ok? do we want - it as a theorem?} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample} - Find all the zeros of the polynomial function $p$ that has formula - \[ - p(x)=x^4-2x^3+5x^2 - \] - \begin{pccsolution} - We begin by factoring $p$ - \begin{align*} - p(x) & =x^4-2x^3+5x^2 \\ - & =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 - \[ - x^2-2x+5=0 - \] - This equation can not be factored, so we use the quadratic formula - \begin{align*} - x & =\frac{2\pm\sqrt{(-2)^2}-20}{2(1)} \\ - & =\frac{2\pm\sqrt{-16}}{2} \\ - & =1\pm 2i - \end{align*} - We conclude that $p$ has $4$ zeros: $0$ (multiplicity $2$), and $1\pm 2i$ (simple). - \end{pccsolution} - \end{pccexample} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{pccexample} - Find a polynomial that has zeros at $2\pm i\sqrt{2}$. - \begin{pccsolution} - 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 - \end{align*} - We conclude that a possible formula for a polynomial function, $p$, - that has zeros at $2\pm i\sqrt{2}$ is - \[ - p(x)=x^2-4x+6 - \] - Note that we could multiply $p$ by any real number and still ensure - that $p$ has the same zeros. - \end{pccsolution} - \end{pccexample} - \investigation*{} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a graph] - For each of the polynomials in \cref{poly:fig:findformula} - \begin{enumerate} - \item count the number of times the curve turns round, and cuts/bounces off the $x$ axis; - \item approximate the degree of the polynomial; - \item use your information to find the linear factors of each polynomial, and therefore write a possible formula for each; - \item make sure your polynomial goes through the given ordered pair. - \end{enumerate} - \begin{shortsolution} - \Vref{poly:fig:findformdeg2}: - \begin{enumerate} - \item the curve turns round once; - \item the degree could be 2; - \item based on the zeros, the linear factors are $(x+5)$ and $(x-3)$; since the - graph opens downwards, we will assume the leading coefficient is negative: $p(x)=-k(x+5)(x-3)$; - \item $p$ goes through $(2,2)$, so we need to solve $2=-k(7)(-1)$ and therefore $k=\nicefrac{2}{7}$, so - \[ - p(x)=-\frac{2}{7}(x+5)(x-3) - \] - \end{enumerate} - \Vref{poly:fig:findformdeg3}: - \begin{enumerate} - \item the curve turns around twice; - \item the degree could be 3; - \item based on the zeros, the linear factors are $(x+2)^2$, and $(x-1)$; - based on the behavior of $p$, we assume that the leading coefficient is positive, and try $p(x)=k(x+2)^2(x-1)$; - \item $p$ goes through $(0,-2)$, so we need to solve $-2=k(4)(-1)$ and therefore $k=\nicefrac{1}{2}$, so - \[ - p(x)=\frac{1}{2}(x+2)^2(x-1) - \] - \end{enumerate} - \Vref{poly:fig:findformdeg5}: - \begin{enumerate} - \item the curve turns around 4 times; - \item the degree could be 5; - \item based on the zeros, the linear factors are $(x+5)^2$, $(x+1)$, $(x-2)$, $(x-3)$; - based on the behavior of $p$, we assume that the leading coefficient is positive, and try $p(x)=k(x+5)^2(x+1)(x-2)(x-3)$; - \item $p$ goes through $(-3,-50)$, so we need to solve $-50=k(64)(-2)(-5)(-6)$ and therefore $k=\nicefrac{5}{384}$, so - \[ - p(x)=\frac{5}{384}(x+5)^2(x+1)(x-2)(x-3) - \] - \end{enumerate} - \end{shortsolution} - \end{problem} - - - \begin{figure}[!htb] - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-2,ymax=5, - width=\textwidth, - ] - \addplot expression[domain=-4.5:3.75]{-1/3*(x+4)*(x-3)}; - \addplot[soldot] coordinates{(-4,0)(3,0)(2,2)} node[axisnode,above right]{$(2,2)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-3,xmax=2, - ymin=-2,ymax=4, - xtick={-2,...,1}, - width=\textwidth, - ] - \addplot expression[domain=-2.95:1.75]{1/3*(x+2)^2*(x-1)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(0,-1.33)}node[axisnode,anchor=north west]{$(0,-2)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-100,ymax=150, - width=\textwidth, - ] - \addplot expression[domain=-4.5:3.4,samples=50]{(x+4)^2*(x+1)*(x-2)*(x-3)}; - \addplot[soldot]coordinates{(-4,0)(-1,0)(2,0)(3,0)(-3,-60)}node[axisnode,anchor=north]{$(-3,-50)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:findformdeg5} - \end{subfigure} - \caption{} - \label{poly:fig:findformula} - \end{figure} - - - - - \begin{exercises} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Prerequisite classifacation skills] - Decide if each of the following functions are linear or quadratic. - \begin{multicols}{3} - \begin{subproblem} - $f(x)=2x+3$ - \begin{shortsolution} - $f$ is linear. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x)=10-7x$ - \begin{shortsolution} - $g$ is linear - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x)=-x^2+3x-9$ - \begin{shortsolution} - $h$ is quadratic. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x)=-17$ - \begin{shortsolution} - $k$ is linear. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(x)=-82x^2-4$ - \begin{shortsolution} - $l$ is quadratic - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(x)=6^2x-8$ - \begin{shortsolution} - $m$ is linear. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Prerequisite slope identification] - State the slope of each of the following linear functions, and - hence decide if each function is increasing or decreasing. - \begin{multicols}{4} - \begin{subproblem} - $\alpha(x)=4x+1$ - \begin{shortsolution} - $m=4$; $\alpha$ is increasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\beta(x)=-9x$ - \begin{shortsolution} - $m=-9$; $\beta$ is decreasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\gamma(t)=18t+100$ - \begin{shortsolution} - $m=18$; $\gamma$ is increasing. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\delta(y)=23-y$ - \begin{shortsolution} - $m=-1$; $\delta$ is decreasing. - \end{shortsolution} - \end{subproblem} - \end{multicols} - Now let's generalize our findings for the most general linear function $f$ - that has formula $f(x)=mx+b$. Complete the following sentences. - \begin{subproblem} - When $m>0$, the function $f$ is $\ldots$ - \begin{shortsolution} - When $m>0$, the function $f$ is $\ldots$ \emph{increasing}. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - When $m<0$, the function $f$ is $\ldots$ - \begin{shortsolution} - When $m<0$, the function $f$ is $\ldots$ \emph{decreasing}. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Polynomial or not?] - Identify whether each of the following functions is a polynomial or not. - If the function is a polynomial, state its degree. - \begin{multicols}{3} - \begin{subproblem} - $p(x)=2x+1$ - \begin{shortsolution} - $p$ is a polynomial (you might also describe $p$ as linear). The degree of $p$ is 1. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=7x^2+4x$ - \begin{shortsolution} - $p$ is a polynomial (you might also describe $p$ as quadratic). The degree of $p$ is 2. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=\sqrt{x}+2x+1$ - \begin{shortsolution} - $p$ is not a polynomial; we require the powers of $x$ to be integer values. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=2^x-45$ - \begin{shortsolution} - $p$ is not a polynomial; the $2^x$ term is exponential. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=6x^4-5x^3+9$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $6$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=-5x^{17}+9x+2$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is 17. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=4x(x+7)^2(x-3)^3$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $6$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=4x^{-5}-x^2+x$ - \begin{shortsolution} - $p$ is not a polynomial because $-5$ is not a positive integer. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=-x^6(x^2+1)(x^3-2)$ - \begin{shortsolution} - $p$ is a polynomial, and the degree of $p$ is $11$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Polynomial graphs] - Three polynomial functions $p$, $m$, and $n$ are shown in \crefrange{poly:fig:functionp}{poly:fig:functionn}. - The functions have the following formulas - \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) - \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, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{(x-1)*(x+2)*(x-3)}; - \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, - ymin=-10,ymax=10, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{-1*(x-1)*(x+2)*(x-3)}; - \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, - ymin=-90,ymax=70, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-4.15:3.15,samples=50]{(x-1)*(x+2)*(x-3)*(x+1)*(x+4)}; - \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} - \end{subproblem} - \begin{subproblem} - Write down the degree, how many times the curve of each function `turns around', - and how many zeros it has - \begin{shortsolution} - \begin{itemize} - \item The degree of $p$ is 3, and the curve $y=p(x)$ turns around twice. - \item The degree of $q$ is also 3, and the curve $y=q(x)$ turns around twice. - \item The degree of $n$ is $5$, and the curve $y=n(x)$ turns around 4 times. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-10,ymax=10, - ytick={-5,5}, - width=\textwidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{(x-1)*(x+2)*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=p(x)$} - \label{poly:fig:functionp} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-10,ymax=10, - ytick={-5,5}, - width=\textwidth, - ] - \addplot expression[domain=-2.5:3.5,samples=50]{-1*(x-1)*(x+2)*(x-3)}; - \addplot[soldot]coordinates{(-2,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=m(x)$} - \label{poly:fig:functionm} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-90,ymax=70, - width=\textwidth, - ] - \addplot expression[domain=-4.15:3.15,samples=100]{(x-1)*(x+2)*(x-3)*(x+1)*(x+4)}; - \addplot[soldot]coordinates{(-4,0)(-2,0)(-1,0)(1,0)(3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=n(x)$} - \label{poly:fig:functionn} - \end{subfigure} - \caption{} - \end{widepage} - \end{figure} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Horizontal intercepts]\label{poly:prob:matchpolys}% - State the horizontal intercepts (as ordered pairs) of the following polynomials. - \begin{multicols}{2} - \begin{subproblem}\label{poly:prob:degree5} - $p(x)=(x-1)(x+2)(x-3)(x+1)(x+4)$ - \begin{shortsolution} - $(-4,0)$, $(-2,0)$, $(-1,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(x)=-(x-1)(x+2)(x-3)$ - \begin{shortsolution} - $(-2,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(x)=(x-1)(x+2)(x-3)$ - \begin{shortsolution} - $(-2,0)$, $(1,0)$, $(3,0)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{poly:prob:degree2} - $s(x)=(x-2)(x+2)$ - \begin{shortsolution} - $(-2,0)$, $(2,0)$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Minimums, maximums, and concavity]\label{poly:prob:incdec} - Four polynomial functions are graphed in \cref{poly:fig:incdec}. The formulas - for these functions are (not respectively) - \begin{gather*} - p(x)=\frac{x^3}{6}-\frac{x^2}{4}-3x, \qquad q(x)=\frac{x^4}{20}+\frac{x^3}{15}-\frac{6}{5}x^2+1\\ - r(x)=-\frac{x^5}{50}-\frac{x^4}{40}+\frac{2x^3}{5}+6, \qquad s(x)=-\frac{x^6}{6000}-\frac{x^5}{2500}+\frac{67x^4}{4000}+\frac{17x^3}{750}-\frac{42x^2}{125} - \end{gather*} - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{.23\textwidth} - \centering - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=major, - ] - \addplot expression[domain=-5.28:4.68,samples=50]{-x^5/50-x^4/40+2*x^3/5+6}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec3} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10,ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=major, - ] - \addplot expression[domain=-6.08:4.967,samples=50]{x^4/20+x^3/15-6/5*x^2+1}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-6,xmax=8,ymin=-10,ymax=10, - xtick={-4,-2,...,6}, - ytick={-8,-4,4,8}, - minor ytick={-6,-2,...,6}, - grid=both, - ] - \addplot expression[domain=-4.818:6.081,samples=50]{x^3/6-x^2/4-3*x}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - width=\textwidth, - xmin=-10,xmax=10,ymin=-10,ymax=10, - xtick={-8,-4,4,8}, - ytick={-8,-4,4,8}, - minor xtick={-6,-2,...,6}, - minor ytick={-6,-2,...,6}, - grid=both, - ] - \addplot expression[domain=-9.77:8.866,samples=50]{-x^6/6000-x^5/2500+67*x^4/4000+17/750*x^3-42/125*x^2}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:incdec4} - \end{subfigure} - \caption{Graphs for \cref{poly:prob:incdec}.} - \label{poly:fig:incdec} - \end{widepage} - \end{figure} - \begin{subproblem} - Match each of the formulas with one of the given graphs. - \begin{shortsolution} - \begin{itemize} - \item $p$ is graphed in \vref{poly:fig:incdec1}; - \item $q$ is graphed in \vref{poly:fig:incdec2}; - \item $r$ is graphed in \vref{poly:fig:incdec3}; - \item $s$ is graphed in \vref{poly:fig:incdec4}. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the zeros of each function using the appropriate graph. - \begin{shortsolution} - \begin{itemize} - \item $p$ has simple zeros at about $-3.8$, $0$, and $5$. - \item $q$ has simple zeros at about $-5.9$, $-1$, $1$, and $4$. - \item $r$ has simple zeros at about $-5$, $-2.9$, and $4.1$. - \item $s$ has simple zeros at about $-9$, $-6$, $4.2$, $8.1$, and a zero of multiplicity $2$ at $0$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the local maximums and minimums of each of the functions. - \begin{shortsolution} - \begin{itemize} - \item $p$ has a local maximum of approximately $3.9$ at $-2$, and a local minimum of approximately $-6.5$ at $3$. - \item $q$ has a local minimum of approximately $-10$ at $-4$, and $-4$ at $3$; $q$ has a local maximum of approximately $1$ at $0$. - \item $r$ has a local minimum of approximately $-5.5$ at $-4$, and a local maximum of approximately $10$ at $3$. - \item $s$ has a local maximum of approximately $5$ at $-8$, $0$ at $0$, and $5$ at $7$; $s$ has local minimums - of approximately $-3$ at $-4$, and $-1$ at $3$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the global maximums and minimums of each of the functions. - \begin{shortsolution} - \begin{itemize} - \item $p$ does not have a global maximum, nor a global minimum. - \item $q$ has a global minimum of approximately $-10$; it does not have a global maximum. - \item $r$ does not have a global maximum, nor a global minimum. - \item $s$ has a global maximum of approximately $5$; it does not have a global minimum. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the intervals on which each function is increasing and decreasing. - \begin{shortsolution} - \begin{itemize} - \item $p$ is increasing on $(-\infty,-2)\cup (3,\infty)$, and decreasing on $(-2,3)$. - \item $q$ is increasing on $(-4,0)\cup (3,\infty)$, and decreasing on $(-\infty,-4)\cup (0,3)$. - \item $r$ is increasing on $(-4,3)$, and decreasing on $(-\infty,-4)\cup (3,\infty)$. - \item $s$ is increasing on $(-\infty,-8)\cup (-4,0)\cup (3,5)$, and decreasing on $(-8,-4)\cup (0,3)\cup (5,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Approximate the intervals on which each function is concave up and concave down. - \begin{shortsolution} - \begin{itemize} - \item $p$ is concave up on $(1,\infty)$, and concave down on $(-\infty,1)$. - \item $q$ is concave up on $(-\infty,-1)\cup (1,\infty)$, and concave down on $(-1,1)$. - \item $r$ is concave up on $(-\infty,-3)\cup (0,2)$, and concave down on $(-3,0)\cup (2,\infty)$. - \item $s$ is concave up on $(-6,-2)\cup (2,5)$, and concave down on $(-\infty,-6)\cup (-2,2)\cup (5,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - The degree of $q$ is $5$. Assuming that all of the real zeros of $q$ are - shown in its graph, how many complex zeros does $q$ have? - \begin{shortsolution} - \Vref{poly:fig:incdec2} shows that $q$ has $3$ real zeros - since the curve of $q$ cuts the horizontal axis $3$ times. - Since $q$ has degree $5$, $q$ must have $2$ complex zeros. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Long-run behaviour of polynomials] - Describe the long-run behavior of each of polynomial functions in - \crefrange{poly:prob:degree5}{poly:prob:degree2}. - \begin{shortsolution} - $\dd\lim_{x\rightarrow-\infty}p(x)=-\infty$, - $\dd\lim_{x\rightarrow\infty}p(x)=\infty$, - $\dd\lim_{x\rightarrow-\infty}q(x)=\infty$, - $\dd\lim_{x\rightarrow\infty}q(x)=-\infty$, - $\dd\lim_{x\rightarrow-\infty}r(x)=-\infty$, - $\dd\lim_{x\rightarrow\infty}r(x)=\infty$, - $\dd\lim_{x\rightarrow-\infty}s(x)=\infty$, - $\dd\lim_{x\rightarrow\infty}s(x)=\infty$, - \end{shortsolution} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[True of false?] - Let $p$ be a polynomial function. - Label each of the following statements as true (T) or false (F); if they are false, - provide an example that supports your answer. - \begin{subproblem} - If $p$ has degree $3$, then $p$ has $3$ distinct zeros. - \begin{shortsolution} - False. Consider $p(x)=x^2(x+1)$ which has only 2 distinct zeros. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has degree $4$, then $\dd\lim_{x\rightarrow-\infty}p(x)=\infty$ and $\dd\lim_{x\rightarrow\infty}p(x)=\infty$. - \begin{shortsolution} - False. Consider $p(x)=-x^4$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has even degree, then it is possible that $p$ can have no real zeros. - \begin{shortsolution} - True. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - If $p$ has odd degree, then it is possible that $p$ can have no real zeros. - \begin{shortsolution} - False. All odd degree polynomials will cut the horizontal axis at least once. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a possible formula for a polynomial - function that has the specified properties. - \begin{subproblem} - Degree 2 and has zeros at $4$ and $5$. - \begin{shortsolution} - Possible option: $p(x)=(x-4)(x-5)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 3 and has zeros at $4$,$5$ and $-3$. - \begin{shortsolution} - Possible option: $p(x)=(x-4)(x-5)(x+3)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 4 and has zeros at $0$, $4$, $5$, $-3$. - \begin{shortsolution} - Possible option: $p(x)=x(x-4)(x-5)(x+3)$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 4, with zeros that make the graph cut at $2$, $-5$, and a zero that makes the graph touch at $-2$; - \begin{shortsolution} - Possible option: $p(x)=(x-2)(x+5)(x+2)^2$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Degree 3, with only one zero at $-1$. - \begin{shortsolution} - Possible option: $p(x)=(x+1)^3$. Note we could multiply $p$ by any real number, and still meet the requirements. - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{poly:step:last}] - \pccname{Saheed} is graphing a polynomial function, $p$. - He is following \crefrange{poly:step:first}{poly:step:last} and has so far - marked the zeros of $p$ on \cref{poly:fig:optionsp1}. Saheed tells you that - $p$ has degree $3$, but does \emph{not} say if the leading coefficient - of $p$ is positive or negative. - \begin{figure}[!htbp] - \begin{widepage} - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\textwidth, - height=.5\textwidth, - ] - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:optionsp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\textwidth, - height=.5\textwidth, - ] - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{poly:fig:optionsp2} - \end{subfigure}% - \caption{} - \end{widepage} - \end{figure} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp1} to help sketch $p$, assuming that the leading coefficient - is positive. - \begin{shortsolution} - Assuming that $a_3>0$: - - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-6.78179:8.35598,samples=50]{1/20*(x+5)*(x-2)*(x-6)}; - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp1} to help sketch $p$, assuming that the leading coefficient - is negative. - \begin{shortsolution} - Assuming that $a_3<0$: - - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-6.78179:8.35598,samples=50]{-1/20*(x+5)*(x-2)*(x-6)}; - \addplot[soldot] coordinates{(-5,0)(2,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - Saheed now turns his attention to another polynomial function, $q$. He finds - the zeros of $q$ (there are only $2$) and marks them on \cref{poly:fig:optionsp2}. - Saheed knows that $q$ has degree $3$, but doesn't know if the leading - coefficient is positive or negative. - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp2} to help sketch $q$, assuming that the leading - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-8.68983:7.31809,samples=50]{1/20*(x+5)^2*(x-6)}; - \addplot expression[domain=-6.31809:9.68893,samples=50]{1/20*(x+5)*(x-6)^2}; - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use the information in \cref{poly:fig:optionsp2} to help sketch $q$, assuming that the leading - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-15}, - width=\solutionfigurewidth, - ] - \addplot expression[domain=-8.68983:7.31809,samples=50]{-1/20*(x+5)^2*(x-6)}; - \addplot expression[domain=-6.31809:9.68893,samples=50]{-1/20*(x+5)*(x-6)^2}; - \addplot[soldot] coordinates{(-5,0)(6,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Zeros] - Find all zeros of each of the following polynomial functions, making - sure to detail their multiplicity. Note that - you may need to use factoring, or the quadratic formula, or both! Also note - that some zeros may be repeated, and some may be complex. - \begin{multicols}{3} - \begin{subproblem} - $p(x)=x^2+1$ - \begin{shortsolution} - $\pm i$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(y)=(y^2-9)(y^2-7)$ - \begin{shortsolution} - $\pm 3$, $\pm \sqrt{7}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(z)=-4z^3(z^2+3)(z^2+64)$ - \begin{shortsolution} - $0$ (multiplicity $3$), $\pm\sqrt{3}$ (simple), $\pm\sqrt{8}$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $a(x)=x^4-81$ - \begin{shortsolution} - $\pm 3$, $\pm 3i$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $b(y)=y^3-8$ - \begin{shortsolution} - $2$, $-1\pm i\sqrt{3}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $c(m)=m^3-m^2$ - \begin{shortsolution} - $0$ (multiplicity $2$), $1$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(n)=(n+1)(n^2+4)$ - \begin{shortsolution} - $-1$, $\pm 2i$ (all are simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $f(\alpha)=(\alpha^2-16)(\alpha^2-5\alpha+4)$ - \begin{shortsolution} - $-4$ (simple), $4$ (multiplicity $2$), $1$ (simple). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(\beta)=(\beta^2-25)(\beta^2-5\beta-4)$ - \begin{shortsolution} - $\pm 5$, $\dfrac{5\pm\sqrt{41}}{2}$ (all are simple). - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Given zeros, find a formula] - In each of the following problems you are given the zeros of a polynomial. - Write a possible formula for each polynomial| you may leave your - answer in factored form, but it may not contain complex numbers. Unless - otherwise stated, assume that the zeros are simple. - \begin{multicols}{3} - \begin{subproblem} - $1$, $2$ - \begin{shortsolution} - $p(x)=(x-1)(x-2)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $0$, $5$, $13$ - \begin{shortsolution} - $p(x)=x(x-5)(x-13)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $-7$, $2$ (multiplicity $3$), $5$ - \begin{shortsolution} - $p(x)=(x+7)(x-2)^3(x-5)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $0$, $\pm i$ - \begin{shortsolution} - $p(x)=x(x^2+1)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\pm 2i$, $\pm 7$ - \begin{shortsolution} - $p(x)=(x^2+4)(x^2-49)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $-2\pm i\sqrt{6}$ - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Composition of polynomials] - Let $p$ and $q$ be polynomial functions that have formulas - \[ - p(x)=(x+1)(x+2)(x+5), \qquad q(x)=3-x^4 - \] - Evaluate each of the following. - \begin{multicols}{4} - \begin{subproblem} - $(p\circ q)(0)$ - \begin{shortsolution} - $160$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(q\circ p)(0)$ - \begin{shortsolution} - $-9997$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(p\circ q)(1)$ - \begin{shortsolution} - $84$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(p\circ p)(0)$ - \begin{shortsolution} - $1980$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[Piecewise polynomial functions] - Let $P$ be the piecewise-defined function with formula - \[ - P(x)=\begin{cases} - (1-x)(2x+5)(x^2+1), & x\leq -3\\ - 4-x^2, & -3m$ then $r$ will have an oblique asymptote as $x\rightarrow\pm\infty$ (more on this in \cref{rat:sec:oblique}) - \end{itemize} - \end{pccdefinition} - We will concentrate on functions that have horizontal asymptotes until - we reach \cref{rat:sec:oblique}. - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}[Long-run behavior graphically]\label{rat:ex:horizasymp} - \pccname{Kebede} has graphed the following functions in his graphing calculator - \[ - r(x)=\frac{x+1}{x-3}, \qquad s(x)=\frac{2(x+1)}{x-3}, \qquad t(x)=\frac{3(x+1)}{x-3} - \] - 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} - \begin{tikzpicture}[/pgf/declare function={f=2*(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:2]{f}; - \addplot[pccplot] expression[domain=5:15]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:2.42857,samples=50]{f}; - \addplot[pccplot] expression[domain=3.8:15,samples=50]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{1}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=3*(x+1)/(x-3);}] - \begin{axis}[ - framed, - xmin=-15,xmax=15, - ymin=-6,ymax=6, - xtick={-12,-8,...,12}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-15:1.6666,samples=50]{f}; - \addplot[pccplot] expression[domain=7:15]{f}; - \addplot[soldot] coordinates{(-1,0)}; - \addplot[asymptote,domain=-6:6]({3},{x}); - \addplot[asymptote,domain=-15:15]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:horizasymp3} - \end{subfigure} - \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. - In particular, Oscar notes that - \begin{itemize} - \item the curve shown in \cref{rat:fig:horizasymp1} has a horizontal asymptote with equation $y=2$; - \item the curve shown in \cref{rat:fig:horizasymp2} has a horizontal asymptote with equation $y=1$; - \item the curve shown in \cref{rat:fig:horizasymp3} has a horizontal asymptote with equation $y=3$. - \end{itemize} - Oscar is able to tie it all together for Kebede by referencing \cref{rat:def:longrun}. He says - 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 - %=================================== - \begin{pccexample}[Long-run behavior numerically] - \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 - \[ - R(x)=\frac{-5(x+1)}{x-3}, \qquad S(x)=\frac{7(x-5)}{2(x+1)} - \] - In \cref{rat:tab:plusinfty} they model the behavior of $R$ and $S$ as $x\rightarrow\infty$, - and in \cref{rat:tab:minusinfty} they model the behavior of $R$ and $S$ as $x\rightarrow-\infty$ - by substituting very large values of $|x|$ into each function. - \begin{table}[!htb] - \begin{minipage}{.5\textwidth} - \centering - \caption{$R$ and $S$ as $x\rightarrow\infty$} - \label{rat:tab:plusinfty} - \begin{tabular}{crr} - \beforeheading - $x$ & $R(x)$ & $S(x)$ \\ \afterheading - $1\times 10^2$ & $-5.20619$ & $3.29208$ \\\normalline - $1\times 10^3$ & $-5.02006$ & $3.47902$ \\\normalline - $1\times 10^4$ & $-5.00200$ & $3.49790$ \\\normalline - $1\times 10^5$ & $-5.00020$ & $3.49979$ \\\normalline - $1\times 10^6$ & $-5.00002$ & $3.49998$ \\\lastline - \end{tabular} - \end{minipage}% - \begin{minipage}{.5\textwidth} - \centering - \caption{$R$ and $S$ as $x\rightarrow-\infty$} - \label{rat:tab:minusinfty} - \begin{tabular}{crr} - \beforeheading - $x$ & $R(x)$ & $S(x)$ \\ \afterheading - $-1\times 10^2$ & $-4.80583$ & $3.71212$ \\\normalline - $-1\times 10^3$ & $-4.98006$ & $3.52102$ \\\normalline - $-1\times 10^4$ & $-4.99800$ & $3.50210$ \\\normalline - $-1\times 10^5$ & $-4.99980$ & $3.50021$ \\\normalline - $-1\times 10^6$ & $-4.99998$ & $3.50002$ \\\lastline - \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 - %=================================== - \begin{pccexample}[Repeated factors in the numerator] - Consider the functions $f$, $g$, and $h$ that have formulas - \[ - f(x)=\frac{(x-2)^2}{(x-3)(x+1)}, \qquad g(x)=\frac{x-2}{(x-3)(x+1)}, \qquad h(x)=\frac{(x-2)^3}{(x-3)(x+1)} - \] - which are graphed in \cref{rat:fig:repfactn}. We note that each function has vertical - asymptotes at $-1$ and $3$, and so the domain of each function is - \[ - (-\infty,-1)\cup(-1,3)\cup(3,\infty) - \] - 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 - $f$ does not cut the horizontal axis| it bounces off it; - \item $g$ also has a horizontal intercept $(2,0)$, and the curve - of $g$ \emph{does} cut the horizontal axis; - \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} - \item $f$ has a horizontal asymptote with equation $y=1$; - \item $g$ has a horizontal asymptote with equation $y=0$; - \item $h$ does \emph{not} have a horizontal asymptote| it has an oblique asymptote (we'll - study this more in \cref{rat:sec:oblique}). - \end{itemize} - \end{pccexample} - - \begin{figure}[!htb] - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)^2/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - ytick={-8,-4,...,8}, - % grid=both, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.248,samples=50]{f}; - \addplot[pccplot] expression[domain=-0.794:2.976,samples=50]{f}; - \addplot[pccplot] expression[domain=3.026:5,samples=50]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-6:6]({-1},{x}); - % \addplot[asymptote,domain=-6:6]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{(x-2)^2}{(x+1)(x-3)}$} - \label{rat:fig:repfactn1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - ymin=-10,ymax=10, - xtick={-4,-2,...,4}, - ytick={-8,-4,...,8}, - % grid=both, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.075]{f}; - \addplot[pccplot] expression[domain=-0.925:2.975]{f}; - \addplot[pccplot] expression[domain=3.025:5]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-6:6]({-1},{x}); - % \addplot[asymptote,domain=-6:6]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{x-2}{(x+1)(x-3)}$} - \label{rat:fig:repfactn2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-2)^3/((x+1)*(x-3));}] - \begin{axis}[ - % framed, - xmin=-5,xmax=5, - xtick={-8,-6,...,8}, - % grid=both, - ymin=-30,ymax=30, - width=\figurewidth, - ] - \addplot[pccplot] expression[domain=-5:-1.27]{f}; - \addplot[pccplot] expression[domain=-0.806:2.99185]{f}; - \addplot[pccplot] expression[domain=3.0085:5]{f}; - \addplot[soldot] coordinates{(2,0)}; - % \addplot[asymptote,domain=-30:30]({-1},{x}); - % \addplot[asymptote,domain=-30:30]({3},{x}); - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{(x-2)^3}{(x+1)(x-3)}$} - \label{rat:fig:repfactn3} - \end{subfigure} - \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 - function has a \emph{hole} at $a$. - \begin{pccdefinition}[Holes] - The rational function - \[ - r(x)=\frac{p(x)}{q(x)} - \] - has a hole at $a$ if $p(a)=q(a)=0$. Note that holes are different from - a vertical asymptotes. We represent that $r$ has a hole at the point - $(a,r(a))$ on the curve $y=r(x)$ by - using a hollow circle, $\circ$. - \end{pccdefinition} - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample} - \pccname{Mohammed} and \pccname{Sue} have graphed the function $r$ that has formula - \[ - r(x)=\frac{x^2+x-6}{(x-2)} - \] - 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 - \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 - \[ - (-\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] - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-4,...,8}, - ytick={-8,-4,...,8}, - grid=both, - width=\textwidth, - ] - \addplot expression[domain=-10:7]{x+3}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:hole} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-4,...,8}, - ytick={-8,-4,...,8}, - grid=both, - width=\textwidth, - ] - \addplot expression[domain=-10:7]{x+3}; - \addplot[holdot] coordinates{(2,5)}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:hole1} - \end{minipage}% - \end{figure} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{pccexample} - Consider the function $f$ that has formula - \[ - f(x)=\frac{x(x+3)}{x^2-4x} - \] - The domain of $f$ is $(-\infty,0)\cup(0,4)\cup(4,\infty)$ because both $0$ and $4$ - make the denominator equal to $0$. Notice that - \begin{align*} - f(x) & = \frac{x(x+3)}{x(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 - \begin{tikzpicture}[/pgf/declare function={f=(x+3)/(x-4);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - ] - \addplot[pccplot] expression[domain=-10:3.36364,samples=50]{f}; - \addplot[pccplot] expression[domain=4.77:10]{f}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[holdot]coordinates{(0,-0.75)}; - \addplot[soldot] coordinates{(-3,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=\dfrac{x(x+3)}{x^2-4x}$} - \label{rat:fig:holeex} - \end{figure} - \end{pccexample} - - - - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{pccexample}[Minimums and maximums] - \pccname{Seamus} and \pccname{Trang} are discussing rational functions. Seamus says that - 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 - \[ - f(x)=-\frac{32(x-1)(x+1)}{(x-2)^2(x+2)^2}, \qquad g(x)=\frac{32(x-1)(x+1)}{(x-2)^2(x+2)^2} - \] - 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);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.01]{f}; - \addplot[pccplot] expression[domain=-1.45:1.45]{f}; - \addplot[pccplot] expression[domain=3.01:10]{f}; - \addplot[soldot] coordinates{(-1,0)(1,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=f(x)$} - \label{rat:fig:minmax1} - \end{minipage}% - \hfill - \begin{minipage}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=32*(x-1)*(x+1)/(( x-2)^2*(x+2)^2);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.01]{f}; - \addplot[pccplot] expression[domain=-1.45:1.45]{f}; - \addplot[pccplot] expression[domain=3.01:10]{f}; - \addplot[soldot] coordinates{(-1,0)(1,0)}; - \end{axis} - \end{tikzpicture} - \caption{$y=g(x)$} - \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 - % Date: March 2012 - %=================================== - \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} - \centering - \captionof{table}{} - \label{rat:tab:spaghetti} - \begin{tabular}{cc} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - $1$ & \\\normalline - $2$ & \\\normalline - $3$ & \\\normalline - $4$ & \\\normalline - $5$ & \\\normalline - $6$ & \\\normalline - $7$ & \\\normalline - $8$ & \\\normalline - $9$ & \\\normalline - $10$ & \\\lastline - \end{tabular} - \end{margintable} - \begin{subproblem}\label{rat:prob:spaggt1} - Help the Queen complete \cref{rat:tab:spaghetti}, and use $2$ digits after the decimal - where appropriate. - \begin{shortsolution} - \begin{tabular}[t]{ld{2}} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - $1$ & 100 \\\normalline - $2$ & 50 \\\normalline - $3$ & 33.33 \\\normalline - $4$ & 25 \\\normalline - $5$ & 20 \\\normalline - $6$ & 16.67 \\\normalline - $7$ & 14.29 \\\normalline - $8$ & 12.50 \\\normalline - $9$ & 11.11 \\\normalline - $10$ & 10 \\\lastline - \end{tabular} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What do you notice about the number of $\unit{mg}$ that it takes to break - the spaghetti as $x$ increases? - \begin{shortsolution} - It seems that the number of $\unit{mg}$ that it takes to break the spaghetti decreases - as $x$ increases. - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:spaglt1} - The Queen wonders what happens when $x$ gets very small| help the Queen construct - a table of values for $x$ and $y$ when $x=0.0001, 0.001, 0.01, 0.1, 0.5, 1$. - \begin{shortsolution} - \begin{tabular}[t]{d{2}l} - \beforeheading - \heading{$x$} & \heading{$y$} \\ - \afterheading - 0.0001 & $1000000$ \\\normalline - 0.001 & $100000$ \\\normalline - 0.01 & $10000$ \\\normalline - 0.1 & $1000$ \\\normalline - 0.5 & $200$ \\\normalline - 1 & $100$ \\\lastline - \end{tabular} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What do you notice about the number of $\unit{mg}$ that it takes to break the spaghetti - as $x\rightarrow 0$? Would it ever make sense to let $x=0$? - \begin{shortsolution} - The number of $\unit{mg}$ required to break the spaghetti increases as $x\rightarrow 0$. - We can not allow $x$ to be $0$, as we can not divide by $0$, and we can not - be $0$ inches from the edge of the table. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Plot your results from \cref{rat:prob:spaggt1,rat:prob:spaglt1} on the same graph, - and join the points using a smooth curve| set the maximum value of $y$ as $200$, and - 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, - xmin=-2,xmax=11, - ymin=-20,ymax=200, - xtick={2,4,...,10}, - ytick={20,40,...,180}, - grid=major, - width=\solutionfigurewidth, - ] - \addplot+[-] expression[domain=0.5:10]{100/x}; - \addplot[soldot] coordinates{(0.5,200)(1,100)(2,50)(3,33.33) - (4,25)(5,20)(16.67)(7,14.29)(8,12.50)(9,11.11)(10,10)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Using your graph, observe what happens to $y$ as $x$ increases. If we could somehow - construct a piece of uncooked spaghetti that was $\unit[101]{inches}$ long, how many - $\unit{mg}$ would it take to break the spaghetti? - \begin{shortsolution} - As $x$ increases, $y\rightarrow 0$. If we could construct a piece of spaghetti - $\unit[101]{inches}$ long, it would only take $\unit[1]{mg}$ to break it $\left(\frac{100}{100}=1\right)$. Of course, - the weight of spaghetti would probably cause it to break without the weight. - \end{shortsolution} - \end{subproblem} - The Queen looks forward to more food-related investigations from her jester. - \end{problem} - - - - %=================================== - % Author: Adams (Hughes) - % Date: March 2012 - %=================================== - \begin{problem}[Debt Amortization] - To amortize a debt means to pay it off in a given length of time using - equal periodic payments. The payments include interest on the unpaid - balance. The following formula gives the monthly payment, $M$, in dollars - that is necessary to amortize a debt of $P$ dollars in $n$ months - at a monthly interest rate of $i$ - \[ - M=\frac{P\cdot i}{1-(1+i)^{-n}} - \] - Use this formula in each of the following problems. - \begin{subproblem} - What monthly payments are necessary on a credit card debt of \$2000 at - $\unit[1.5]{\%}$ monthly if you want to pay off the debt in $2$ years? - In one year? How much money will you save by paying off the debt in the - shorter amount of time? - \begin{shortsolution} - 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 - \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 - \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. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - To purchase a home, a family needs a loan of \$300,000 at $\unit[5.2]{\%}$ - annual interest. Compare a $20$ year loan to a $30$ year loan and make - a recommendation for the family. - (Note: when given an annual interest rate, it is a common business practice to divide by - $12$ to get a monthly rate.) - \begin{shortsolution} - 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 - \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 - \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} - \begin{subproblem} - \pccname{Ellen} wants to make monthly payments of \$100 to pay off a debt of \$3000 - at \unit[12]{\%} annual interest. How long will it take her to pay off the - debt? - \begin{shortsolution} - We are given $M=100$, $P=3000$, $i=0.01$, and we need to find $n$ - in the equation - \[ - 100 = \frac{3000\cdot 0.01}{1-(1+0.01)^{-n}} - \] - Using logarithms, we find that $n\approx 36$. It will take - Ellen about $3$ years to pay off the debt. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - \pccname{Jake} is going to buy a new car. He puts \$2000 down and wants to finance the - remaining \$14,000. The dealer will offer him \unit[4]{\%} annual interest for - $5$ years, or a \$2000 - rebate which he can use to reduce the amount of the loan and \unit[8]{\%} - annual interest for 5 years. Which should he choose? - \begin{shortsolution} - \begin{description} - \item[Option 1:] $\unit[4]{\%}$ annual interest for $5$ years on \$14,000. - 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 - \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. - \item[Option 2:] $\unit[8]{\%}$ annual interest for $5$ years on \$12,000. - 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 - \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 - interest. - \end{description} - Jake should choose option 1 to minimize the amount of interest - he has to pay. - \end{shortsolution} - \end{subproblem} - \end{problem} - - \begin{exercises} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Rational or not] - Decide if each of the following functions are rational or not. If - they are rational, state their domain. - \begin{multicols}{3} - \begin{subproblem} - $r(x)=\dfrac{3}{x}$ - \begin{shortsolution} - $r$ is rational; the domain of $r$ is $(-\infty,0)\cup (0,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $s(y)=\dfrac{y}{6}$ - \begin{shortsolution} - $s$ is not rational ($s$ is linear). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $t(z)=\dfrac{4-x}{7-8z}$ - \begin{shortsolution} - $t$ is rational; the domain of $t$ is $\left( -\infty,\dfrac{7}{8} \right)\cup \left( \dfrac{7}{8},\infty \right)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $u(w)=\dfrac{w^2}{(w-3)(w+4)}$ - \begin{shortsolution} - $u$ is rational; the domain of $w$ is $(-\infty,-4)\cup(-4,3)\cup(3,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $v(x)=\dfrac{4}{(x-2)^2}$ - \begin{shortsolution} - $v$ is rational; the domain of $v$ is $(-\infty,2)\cup(2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $w(x)=\dfrac{9-x}{x+17}$ - \begin{shortsolution} - $w$ is rational; the domain of $w$ is $(-\infty,-17)\cup(-17,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $a(x)=x^2+4$ - \begin{shortsolution} - $a$ is not rational ($a$ is quadratic, or a polynomial of degree $2$). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $b(y)=3^y$ - \begin{shortsolution} - $b$ is not rational ($b$ is exponential). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $c(z)=\dfrac{z^2}{z^3}$ - \begin{shortsolution} - $c$ is rational; the domain of $c$ is $(-\infty,0)\cup (0,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $d(x)=x^2(x+3)(5x-7)$ - \begin{shortsolution} - $d$ is not rational ($d$ is a polynomial). - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $e(\alpha)=\dfrac{\alpha^2}{\alpha^2-1}$ - \begin{shortsolution} - $e$ is rational; the domain of $e$ is $(-\infty,-1)\cup(-1,1)\cup(1,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $f(\beta)=\dfrac{3}{4}$ - \begin{shortsolution} - $f$ is not rational ($f$ is constant). - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Function evaluation] - Let $r$ be the function that has formula - \[ - r(x)=\frac{(x-2)(x+3)}{(x+5)(x-7)} - \] - Evaluate each of the following (if possible); if the value is undefined, - then state so. - \begin{multicols}{4} - \begin{subproblem} - $r(0)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(0) & =\frac{(0-2)(0+3)}{(0+5)(0-7)} \\ - & =\frac{-6}{-35} \\ - & =\frac{6}{35} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(1)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(1) & =\frac{(1-2)(1+3)}{(1+5)(1-7)} \\ - & =\frac{-4}{-36} \\ - & =\frac{1}{9} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(2)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(2) & =\frac{(2-2)(2+3)}{(2+5)(2-7)} \\ - & = \frac{0}{-50} \\ - & =0 - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(4)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(4) & =\frac{(4-2)(4+3)}{(4+5)(4-7)} \\ - & =\frac{14}{-27} \\ - & =-\frac{14}{27} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(7)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(7) & =\frac{(7-2)(7+3)}{(7+5)(7-7)} \\ - & =\frac{50}{0} - \end{aligned}$ - - $r(7)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(-3)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(-3) & =\frac{(-3-2)(-3+3)}{(-3+5)(-3-7)} \\ - & =\frac{0}{-20} \\ - & =0 - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(-5)$ - \begin{shortsolution} - $\begin{aligned}[t] - r(-5) & =\frac{(-5-2)(-5+3)}{(-5+5)(-5-7)} \\ - & =\frac{14}{0} - \end{aligned}$ - - $r(-5)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r\left( \frac{1}{2} \right)$ - \begin{shortsolution} - $\begin{aligned}[t] - 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} - \end{aligned}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Holes or asymptotes?] - State the domain of each of the following rational functions. Identify - any holes or asymptotes. - \begin{multicols}{3} - \begin{subproblem} - $f(x)=\dfrac{12}{x-2}$ - \begin{shortsolution} - $f$ has a vertical asymptote at $2$; the domain of $f$ is $(-\infty,2)\cup (2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x)=\dfrac{x^2+x}{(x+1)(x-2)}$ - \begin{shortsolution} - $g$ has a vertical asymptote at $2$, and a hole at $-1$; the domain of $g$ is $(-\infty,-1)\cup(-1,2)\cup(2,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x)=\dfrac{x^2+5x+4}{x^2+x-12}$ - \begin{shortsolution} - $h$ has a vertical asymptote at $3$, and a whole at $-4$; the domain of $h$ is $(-\infty,-4)\cup(-4,3)\cup(3,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(z)=\dfrac{z+2}{2z-3}$ - \begin{shortsolution} - $k$ has a vertical asymptote at $\dfrac{3}{2}$; the domain of $k$ is $\left( -\infty,\dfrac{3}{2} \right)\cup\left( \dfrac{3}{2},\infty \right)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(w)=\dfrac{w}{w^2+1}$ - \begin{shortsolution} - $l$ does not have any vertical asymptotes nor holes; the domain of $w$ is $(-\infty,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(t)=\dfrac{14}{13-t^2}$ - \begin{shortsolution} - $m$ has vertical asymptotes at $\pm\sqrt{13}$; the domain of $m$ is $(-\infty,\sqrt{13})\cup(-\sqrt{13},\sqrt{13})\cup(\sqrt{13},\infty)$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a graph] - Consider the rational functions graphed in \cref{rat:fig:findformula}. Find - the vertical asymptotes for each function, together with any zeros, and - give a possible formula for each. - \begin{shortsolution} - \begin{itemize} - \item \Vref{rat:fig:formula1}: possible formula is $r(x)=\dfrac{1}{x+5}$ - \item \Vref{rat:fig:formula2}: possible formula is $r(x)=\dfrac{(x+3)}{(x-5)}$ - \item \Vref{rat:fig:formula3}: possible formula is $r(x)=\dfrac{1}{(x-4)(x+3)}$. - \end{itemize} - \end{shortsolution} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=1/(x+4);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-6,ymax=6, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-4.16667,samples=50]{f}; - \addplot[pccplot] expression[domain=-3.83333:10,samples=50]{f}; - \addplot[asymptote,domain=-6:6]({-4},{x}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula1} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=(x+3)/(x-5);}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-6,ymax=6, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:3.85714]{f}; - \addplot[pccplot] expression[domain=6.6:10]{f}; - \addplot[soldot] coordinates{(-3,0)}; - \addplot[asymptote,domain=-6:6]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula2} - \end{subfigure} - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture}[/pgf/declare function={f=1/((x-4)*(x+3));}] - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-3,ymax=3, - xtick={-8,-6,...,8}, - minor ytick={-4,-3,...,4}, - grid=both, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-3.0473]{f}; - \addplot[pccplot] expression[domain=-2.95205:3.95205]{f}; - \addplot[pccplot] expression[domain=4.0473:10]{f}; - \addplot[asymptote,domain=-3:3]({-3},{x}); - \addplot[asymptote,domain=-3:3]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:formula3} - \end{subfigure} - \caption{} - \label{rat:fig:findformula} - \end{widepage} - \end{figure} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a formula of a rational - function that has the listed properties. - \begin{subproblem} - Vertical asymptote at $2$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{1}{x-2}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Vertical asymptote at $5$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{1}{x-5}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Vertical asymptote at $-2$, and zero at $6$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{x-6}{x+2}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Zeros at $2$ and $-5$ and vertical asymptotes at $1$ and $-7$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{(x-2)(x+5)}{(x-1)(x+7)}$. Note that we could multiply the - numerator or denominator by any real number and still have the desired properties. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Given formula, find horizontal asymptotes] - Each of the following functions has a horizontal asymptote. Write the equation - of the horizontal asymptote for each function. - \begin{multicols}{3} - \begin{subproblem} - $f(x) = \dfrac{1}{x}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $g(x) = \dfrac{2x+3}{x}$ - \begin{shortsolution} - $y=2$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $h(x) = \dfrac{x^2+2x}{x^2+3}$ - \begin{shortsolution} - $y=1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x) = \dfrac{x^2+7}{x}$ - \begin{shortsolution} - $y=1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $l(x)=\dfrac{3x-2}{5x+8}$ - \begin{shortsolution} - $y=\dfrac{3}{5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $m(x)=\dfrac{3x-2}{5x^2+8}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $n(x)=\dfrac{(6x+1)(x-7)}{(11x-8)(x-5)}$ - \begin{shortsolution} - $y=\dfrac{6}{11}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $p(x)=\dfrac{19x^3}{5-x^4}$ - \begin{shortsolution} - $y=0$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $q(x)=\dfrac{14x^2+x}{1-7x^2}$ - \begin{shortsolution} - $y=-2$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{problem}[Given horizontal asymptotes, find formula] - In each of the following problems, give a formula for a function that - has the given horizontal asymptote. Note that there may be more than one option. - \begin{multicols}{4} - \begin{subproblem} - $y=7$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{7(x-2)}{x+1}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $7$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-1$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{5-x^2}{x^2+10}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $10$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=53$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{53x^3}{x^3+4x^2-7}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $53$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-17$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{34(x+2)}{7-2x}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $-17$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{3}{2}$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{3x+4}{2(x+1)}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $\dfrac{3}{2}$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=0$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{4}{x}$. Note that there - are other options, provided that the degree of the numerator is less than the degree - of the denominator. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=-1$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{10x}{5-10x}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $-1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=2$ - \begin{shortsolution} - Possible option: $f(x)=\dfrac{8x-3}{4x+1}$. Note that there - are other options, provided that the degree of the numerator is the same as the degree - of the denominator, and that the ratio of the leading - coefficients is $2$. - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Find a formula from a description] - In each of the following problems, give a formula for a function that - has the prescribed properties. Note that there may be more than one option. - \begin{subproblem} - $f(x)\rightarrow 3$ as $x\rightarrow\pm\infty$. - \begin{shortsolution} - Possible option: $f(x)=\dfrac{3(x-2)}{x+7}$. Note that - the zero and asymptote of $f$ could be changed, and $f$ would still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $r(x)\rightarrow -4$ as $x\rightarrow\pm\infty$. - \begin{shortsolution} - Possible option: $r(x)=\dfrac{-4(x-2)}{x+7}$. Note that - the zero and asymptote of $r$ could be changed, and $r$ would still have the desired properties. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $k(x)\rightarrow 2$ as $x\rightarrow\pm\infty$, and $k$ has vertical asymptotes at $-3$ and $5$. - \begin{shortsolution} - Possible option: $k(x)=\dfrac{2x^2}{(x+3)(x-5)}$. Note that the denominator - must have the given factors; the numerator could be any degree $2$ polynomial, provided the - leading coefficient is $2$. - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: Feb 2011 - %=================================== - \begin{problem} - Let $r$ be the rational function that has - \[ - r(x) = \frac{(x+2)(x-1)}{(x+3)(x-4)} - \] - Each of the following questions are in relation to this function. - \begin{subproblem} - What is the vertical intercept of this function? State your answer as an - ordered pair. \index{rational functions!vertical intercept} - \begin{shortsolution} - $\left(0,\frac{1}{6}\right)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:rational} - What values of $x$ make the denominator equal to $0$? - \begin{shortsolution} - $-3,4$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use your answer to \cref{rat:prob:rational} to write the domain of the function in - both interval, and set builder notation. %\index{rational functions!domain}\index{domain!rational functions} - \begin{shortsolution} - Interval notation: $(-\infty,-3)\cup (-3,4)\cup (4,\infty)$. - Set builder: $\{x|x\ne -3, \mathrm{and}\, x\ne 4\}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - What are the vertical asymptotes of the function? State your answers in - the form $x=$ - \begin{shortsolution} - $x=-3$ and $x=4$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem}\label{rat:prob:zeroes} - What values of $x$ make the numerator equal to $0$? - \begin{shortsolution} - $-2,1$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Use your answer to \cref{rat:prob:zeroes} to write the horizontal intercepts of - $r$ as ordered pairs. - \begin{shortsolution} - $(-2,0)$ and $(1,0)$ - \end{shortsolution} - \end{subproblem} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \begin{problem}[Holes] - \pccname{Josh} and \pccname{Pedro} are discussing the function - \[ - r(x)=\frac{x^2-1}{(x+3)(x-1)} - \] - \begin{subproblem} - What is the domain of $r$? - \begin{shortsolution} - The domain of $r$ is $(-\infty,-3)\cup(-3,1)\cup(1,\infty)$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Josh notices that the numerator can be factored- can you see how? - \begin{shortsolution} - $(x^2-1)=(x-1)(x+1)$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Pedro asks, `Doesn't that just mean that - \[ - r(x)=\frac{x+1}{x+3} - \] - for all values of $x$?' Josh says, `Nearly\ldots but not for all values of $x$'. - What does Josh mean? - \begin{shortsolution} - $r(x)=\dfrac{x+1}{x+3}$ provided that $x\ne -1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Where does $r$ have vertical asymptotes, and where does it have holes? - \begin{shortsolution} - The function $r$ has a vertical asymptote at $-3$, and a hole at $1$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Sketch a graph of $r$. - \begin{shortsolution} - A graph of $r$ is shown below. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-8,-6,...,8}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:-3.25]{(x+1)/(x+3)}; - \addplot[pccplot] expression[domain=-2.75:10]{(x+1)/(x+3)}; - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[holdot]coordinates{(1,0.5)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{problem} - - %=================================== - % Author: Hughes - % Date: July 2012 - %=================================== - \begin{problem}[Function algebra] - Let $r$ and $s$ be the rational functions that have formulas - \[ - r(x)=\frac{2-x}{x+3}, \qquad s(x)=\frac{x^2}{x-4} - \] - Evaluate each of the following (if possible). - \begin{multicols}{4} - \begin{subproblem} - $(r+s)(5)$ - \begin{shortsolution} - $\frac{197}{8}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r-s)(3)$ - \begin{shortsolution} - $\frac{53}{6}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r\cdot s)(4)$ - \begin{shortsolution} - Undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $\left( \frac{r}{s} \right)(1)$ - \begin{shortsolution} - $-\frac{3}{4}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: July 2012 - %=================================== - \begin{problem}[Transformations: given the transformation, find the formula] - Let $r$ be the rational function that has formula. - \[ - r(x)=\frac{x+5}{2x-3} - \] - In each of the following problems apply the given transformation to the function $r$ and - write a formula for the transformed version of $r$. - \begin{multicols}{2} - \begin{subproblem} - Shift $r$ to the right by $3$ units. - \begin{shortsolution} - $r(x-3)=\frac{x+2}{2x-9}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ to the left by $4$ units. - \begin{shortsolution} - $r(x+4)=\frac{x+9}{2x+5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ up by $\pi$ units. - \begin{shortsolution} - $r(x)+\pi=\frac{x+5}{2x-3}+\pi$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Shift $r$ down by $17$ units. - \begin{shortsolution} - $r(x)-17=\frac{x+5}{2x-3}-17$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Reflect $r$ over the horizontal axis. - \begin{shortsolution} - $-r(x)=-\frac{x+5}{2x-3}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Reflect $r$ over the vertical axis. - \begin{shortsolution} - $r(-x)=\frac{x-5}{2x+3}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - - - %=================================== - % Author: Hughes - % Date: May 2011 - %=================================== - \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 - \caption{Tables for \cref{rat:prob:findformula}} - \label{rat:tab:findformula} - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=r(x)$} - \label{rat:tab:findformular} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{7}{2}$ \\\normalline - $-3$ & $-18$ \\\normalline - $-2$ & X \\\normalline - $-1$ & $-4$ \\\normalline - $0$ & $\nicefrac{-3}{2}$ \\\normalline - $1$ & $\nicefrac{-2}{3}$ \\\normalline - $2$ & $\nicefrac{-1}{4}$ \\\normalline - $3$ & $0$ \\\normalline - $4$ & $\nicefrac{1}{6}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=s(x)$} - \label{rat:tab:findformulas} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{-2}{21}$ \\\normalline - $-3$ & $\nicefrac{-1}{12}$ \\\normalline - $-2$ & $0$ \\\normalline - $-1$ & X \\\normalline - $0$ & $\nicefrac{-2}{3}$ \\\normalline - $1$ & $\nicefrac{-3}{4}$ \\\normalline - $2$ & $\nicefrac{-4}{3}$ \\\normalline - $3$ & X \\\normalline - $4$ & $\nicefrac{6}{5}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=t(x)$} - \label{rat:tab:findformulat} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{3}{5}$ \\\normalline - $-3$ & $0$ \\\normalline - $-2$ & X \\\normalline - $-1$ & $3$ \\\normalline - $0$ & $3$ \\\normalline - $1$ & X \\\normalline - $2$ & $0$ \\\normalline - $3$ & $\nicefrac{3}{5}$ \\\normalline - $4$ & $\nicefrac{7}{9}$ \\\lastline - \end{tabular} - \end{subtable} - \hfill - \begin{subtable}{.2\textwidth} - \centering - \caption{$y=u(x)$} - \label{rat:tab:findformulau} - \begin{tabular}{rr} - \beforeheading - $x$ & $y$ \\ \afterheading - $-4$ & $\nicefrac{16}{7}$ \\\normalline - $-3$ & X \\\normalline - $-2$ & $-\nicefrac{4}{5}$ \\\normalline - $-1$ & $-\nicefrac{1}{8}$ \\\normalline - $0$ & $0$ \\\normalline - $1$ & $-\nicefrac{1}{8}$ \\\normalline - $2$ & $-\nicefrac{4}{5}$ \\\normalline - $3$ & X \\\normalline - $4$ & $\nicefrac{16}{7}$ \\\lastline - \end{tabular} - \end{subtable} - \end{widepage} - \end{table} - \begin{subproblem} - Given that the formula for $r(x)$ has the form $r(x)=\dfrac{x-A}{x-B}$, use \cref{rat:tab:findformular} - to find values of $A$ and $B$. - \begin{shortsolution} - $A=3$ and $B=-2$, so $r(x)=\dfrac{x-3}{x+2}$. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Check your formula by computing $r(x)$ at the values specified in the table. - \begin{shortsolution} - $\begin{aligned}[t] - r(-4) & = \frac{-4-3}{-4+2} \\ - & = \frac{7}{2} \\ - \end{aligned}$ - - $r(-3)=\ldots$ etc - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - The function $s$ in \cref{rat:tab:findformulas} has two vertical asymptotes and one zero. - Can you find a formula for $s(x)$? - \begin{shortsolution} - $s(x)=\dfrac{x+2}{(x-3)(x+1)}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Check your formula by computing $s(x)$ at the values specified in the table. - \begin{shortsolution} - $\begin{aligned}[t] - s(-4) & =\frac{-4+2}{(-4-3)(-4+1)} \\ - & =-\frac{2}{21} - \end{aligned}$ - - $s(-3)=\ldots$ etc - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Given that the formula for $t(x)$ has the form $t(x)=\dfrac{(x-A)(x-B)}{(x-C)(x-D)}$, use \cref{rat:tab:findformulat} to find the - values of $A$, $B$, $C$, and $D$; hence write a formula for $t(x)$. - \begin{shortsolution} - $t(x)=\dfrac{(x+3)(x-2)}{(x+2)(x+1)}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Given that the formula for $u(x)$ has the form $u(x)=\dfrac{(x-A)^2}{(x-B)(x-C)}$, use \cref{rat:tab:findformulau} to find the - values of $A$, $B$, and $C$; hence write a formula for $u(x)$. - \begin{shortsolution} - $u(x)=\dfrac{x^2}{(x+3)(x-3)}$ - \end{shortsolution} - \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 - \[ - r(x)=\frac{p(x)}{q(x)} - \] - In this section we will restrict attention to the case when - \[ - \text{degree of }p\leq \text{degree of }q - \] - Note that this necessarily means that each function that we consider - 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 - shape of the graph, but until we have the tools of calculus (from MTH 251) - we can not find local minimums, local maximums, and inflection points algebraically. This - means that we will make our best guess as to where these points are. - \item We will not concern ourselves too much with the vertical scale (because of - our previous point)| we will, however, mark the vertical intercept (assuming there is one), - and any horizontal asymptotes. - \end{itemize} - \begin{pccspecialcomment}[Steps to follow when sketching rational functions]\label{rat:def:stepsforsketch} - \begin{steps} - \item \label{rat:step:first} Find all vertical asymptotes and holes, and mark them on the - graph using dashed vertical lines and open circles $\circ$ respectively. - \item Find any intercepts, and mark them using solid circles $\bullet$; - determine if the curve cuts the axis, or bounces off it at each zero. - \item Determine the behavior of the function around each asymptote| does - it behave like $\frac{1}{x}$ or $\frac{1}{x^2}$? - \item \label{rat:step:penultimate} Determine the long-run behavior of the function, and mark the horizontal - asymptote using a dashed horizontal line. - \item \label{rat:step:last} Deduce the overall shape of the curve, and sketch it. If there isn't - enough information from the previous steps, then construct a table of values - including sample points from each branch. - \end{steps} - Remember that until we have the tools of calculus, we won't be able to - 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 - %=================================== - \begin{pccexample}\label{rat:ex:1overxminus2p2} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $r$ - that has formula - \[ - r(x)=\frac{1}{x-2} - \] - \begin{pccsolution} - \begin{steps} - \item $r$ has a vertical asymptote at $2$; $r$ does not have any holes. The curve of - $r$ will have $2$ branches. - \item $r$ does not have any zeros since the numerator is never equal to $0$. The - vertical intercept of $r$ is $\left( 0,-\frac{1}{2} \right)$. - \item $r$ behaves like $\frac{1}{x}$ around its vertical asymptote since $(x-2)$ - is raised to the power $1$. - \item Since the degree of the numerator is less than the degree of the denominator, - according to \vref{rat:def:longrun} the horizontal asymptote of $r$ has equation $y=0$. - \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} - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htbp] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-5,ymax=5, - width=\textwidth, - ] - \addplot[asymptote,domain=-5:5]({2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \addplot[soldot] coordinates{(0,-0.5)}node[axisnode,anchor=north east]{$\left( 0,-\frac{1}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxminus2p1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=1/(x-2);}] - \begin{axis}[ - xmin=-5,xmax=5, - ymin=-5,ymax=5, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-5:1.8,samples=50]{f}; - \addplot[pccplot] expression[domain=2.2:5]{f}; - \addplot[asymptote,domain=-5:5]({2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \addplot[soldot] coordinates{(0,-0.5)}node[axisnode,anchor=north east]{$\left( 0,-\frac{1}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxminus2p2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:1overxp1} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $v$ - that has formula - \[ - v(x)=\frac{10}{x} - \] - \begin{pccsolution} - \begin{steps} - \item $v$ has a vertical asymptote at $0$. $v$ does not have - any holes. The curve of $v$ will have $2$ branches. - \item $v$ does not have any zeros (since $10\ne 0$). Furthermore, $v$ - does not have a vertical intercept since $v(0)$ is undefined. - \item $v$ behaves like $\frac{1}{x}$ around its vertical asymptote. - \item $v$ has a horizontal asymptote with equation $y=0$. - \item We put the details we have obtained so far in \cref{rat:fig:1overxp1}. - We do not have enough information to sketch $v$ yet (because $v$ does - not have any intercepts), so let's pick a sample - point in either of the $2$ branches| it doesn't matter where our sample point - is, because we know what the overall shape will be. Let's compute $v(2)$ - \begin{align*} - v(2) & =\dfrac{10}{2} \\ - & = 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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-5,5}, - ytick={-5,5}, - axis line style={color=white}, - width=\textwidth, - ] - \addplot[asymptote,<->,domain=-10:10]({0},{x}); - \addplot[asymptote,<->,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=10/x;}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-5,5}, - ytick={-5,5}, - axis line style={color=white}, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:-1]{f}; - \addplot[pccplot] expression[domain=1:10]{f}; - \addplot[soldot] coordinates{(2,5)}node[axisnode,anchor=south west]{$(2,5)$}; - \addplot[asymptote,<->,domain=-10:10]({0},{x}); - \addplot[asymptote,<->,domain=-10:10]({x},{0}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:1overxp2} - \end{subfigure}% - \caption{$y=\dfrac{10}{x}$} - \end{figure} - \end{pccsolution} - \end{pccexample} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{rat:ex:asympandholep1} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $u$ - that has formula - \[ - u(x)=\frac{-4(x^2-9)}{x^2-8x+15} - \] - \begin{pccsolution} - \begin{steps} - \item We begin by factoring both the numerator and denominator of $u$ to help - us find any vertical asymptotes or holes - \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} - \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. - \item $u$ has a simple zero at $-3$. The vertical intercept of $u$ is $\left( 0,\frac{12}{5} \right)$. - \item $u$ behaves like $\frac{1}{x}$ around its vertical asymptote at $4$. - \item Using \vref{rat:def:longrun} the equation of the horizontal asymptote of $u$ is $y=-4$. - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,10}, - width=\textwidth, - ] - \addplot[asymptote,domain=-20:20]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-4}); - \addplot[soldot] coordinates{(-3,0)(0,2.4)}node[axisnode,anchor=south east]{$\left( 0,\frac{12}{5} \right)$}; - \addplot[holdot] coordinates{(3,12)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:asympandholep1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=-4*(x+3)/(x-5);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,10}, - width=\textwidth, - ] - \addplot[pccplot] expression[domain=-10:3.6666,samples=50]{f}; - \addplot[pccplot] expression[domain=7:10]{f}; - \addplot[asymptote,domain=-20:20]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{-4}); - \addplot[soldot] coordinates{(-3,0)(0,2.4)}node[axisnode,anchor=south east]{$\left( 0,\frac{12}{5} \right)$}; - \addplot[holdot] coordinates{(3,12)}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:asympandholep2} - \end{subfigure}% - \caption{$y=\dfrac{-4(x+3)}{x-5}$} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:sketchtwoasymp} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $w$ - that has formula - \[ - w(x)=\frac{2(x+3)(x-5)}{(x+5)(x-4)} - \] - \begin{pccsolution} - \begin{steps} - \item $w$ has vertical asymptotes at $-5$ and $4$. $w$ does not have - any holes. The curve of $w$ will have $3$ branches. - \item $w$ has simple zeros at $-3$ and $5$. The vertical intercept of $w$ - is $\left( 0,\frac{3}{2} \right)$. - \item $w$ behaves like $\frac{1}{x}$ around both of its vertical - asymptotes. - \item The degree of the numerator of $w$ is $2$ and the degree of the - denominator of $w$ is also $2$. Using the ratio of the leading coefficients - 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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[soldot] coordinates{(-3,0)(5,0)}; - \addplot[soldot] coordinates{(0,1.5)}node[axisnode,anchor=north west]{$\left( 0,\frac{3}{2} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:sketchtwoasymptp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=2*(x+3)*(x-5)/( (x+5)*(x-4));}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[soldot] coordinates{(-3,0)(5,0)}; - \addplot[soldot] coordinates{(0,1.5)}node[axisnode,anchor=north west]{$\left( 0,\frac{3}{2} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.56708]{f}; - \addplot[pccplot] expression[domain=-4.63511:3.81708]{f}; - \addplot[pccplot] expression[domain=4.13511:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:sketchtwoasymptp2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:2asympnozeros} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $f$ - that has formula - \[ - f(x)=\frac{100}{(x+5)(x-4)^2} - \] - \begin{pccsolution} - \begin{steps} - \item $f$ has vertical asymptotes at $-5$ and $4$. $f$ does not have - any holes. The curve of $f$ will have $3$ branches. - \item $f$ does not have any zeros (since $100\ne 0$). The vertical intercept of $f$ - is $\left( 0,\frac{5}{4} \right)$. - \item $f$ behaves like $\frac{1}{x}$ around $-5$ and behaves like $\frac{1}{x^2}$ - around $4$. - \item The degree of the numerator of $f$ is $0$ and the degree of the - 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 - be able to find local minimums more precisely. - \end{steps} - \end{pccsolution} - \end{pccexample} - - \begin{figure}[!htbp] - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(0,1.25)}node[axisnode,anchor=south east]{$\left( 0,\frac{5}{4} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2asympnozerosp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=100/( (x+5)*(x-4)^2);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(0,1.25)}node[axisnode,anchor=south east]{$\left( 0,\frac{5}{4} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.12022]{f}; - \addplot[pccplot] expression[domain=-4.87298:2.87298,samples=50]{f}; - \addplot[pccplot] expression[domain=5:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2asympnozerosp2} - \end{subfigure}% - \caption{$y=\dfrac{100}{(x+5)(x-4)^2}$} - \end{figure} - - %=================================== - % Author: Hughes - % Date: May 2012 - %=================================== - \begin{pccexample}\label{rat:ex:2squaredasymp} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $g$ - that has formula - \[ - g(x)=\frac{50(2-x)}{(x+3)^2(x-5)^2} - \] - \begin{pccsolution} - \begin{steps} - \item $g$ has vertical asymptotes at $-3$ and $5$. $g$ does - not have any holes. The curve of $g$ will have $3$ branches. - \item $g$ has a simple zero at $2$. The vertical intercept of $g$ is - $\left( 0,\frac{4}{9} \right)$. - \item $g$ behaves like $\frac{1}{x^2}$ around both of its - vertical asymptotes. - \item The degree of the numerator of $g$ is $1$ and the degree of the denominator - of $g$ is $4$. Using \vref{rat:def:longrun}, we calculate that - the horizontal asymptote of $g$ has equation $y=0$. - \item The details that we have found so far have been drawn in - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(2,0)(0,4/9)}node[axisnode,anchor=south west]{$\left( 0,\frac{4}{9} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2squaredasymp1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=50*(2-x)/( (x+3)^2*(x-5)^2);}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - ytick={-5,5}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-3},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{0}); - \addplot[soldot] coordinates{(2,0)(0,4/9)}node[axisnode,anchor=south west]{$\left( 0,\frac{4}{9} \right)$}; - \addplot[pccplot] expression[domain=-10:-3.61504]{f}; - \addplot[pccplot] expression[domain=-2.3657:4.52773]{f}; - \addplot[pccplot] expression[domain=5.49205:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:2squaredasymp2} - \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 - %=================================== - \begin{pccexample}\label{rat:ex:doublezero} - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of the function $g$ - that has formula - \[ - h(x)=\frac{(x-3)^2}{(x+4)(x-6)} - \] - \begin{pccsolution} - \begin{steps} - \item $h$ has vertical asymptotes at $-4$ and $6$. $h$ does - not have any holes. The curve of $h$ will have $3$ branches. - \item $h$ has a zero at $3$ that has \emph{multiplicity $2$}. - The vertical intercept of $h$ is - $\left( 0,-\frac{3}{8} \right)$. - \item $h$ behaves like $\frac{1}{x}$ around both of its - vertical asymptotes. - \item The degree of the numerator of $h$ is $2$ and the degree of the denominator - of $h$ is $2$. Using \vref{rat:def:longrun}, we calculate that - the horizontal asymptote of $h$ has equation $y=1$. - \item The details that we have found so far have been drawn in - \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} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - ytick={-3,3}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-4},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot] coordinates{(3,0)(0,-3/8)}node[axisnode,anchor=north west]{$\left( 0,-\frac{3}{8} \right)$}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:doublezerop1} - \end{subfigure}% - \hfill - \begin{subfigure}{.45\textwidth} - \begin{tikzpicture}[/pgf/declare function={f=(x-3)^2/((x+4)*(x-6));}] - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - ytick={-3,3}, - width=\textwidth, - ] - \addplot[asymptote,domain=-10:10]({-4},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot] coordinates{(3,0)(0,-3/8)}node[axisnode,anchor=north west]{$\left( 0,-\frac{3}{8} \right)$}; - \addplot[pccplot] expression[domain=-10:-5.20088]{f}; - \addplot[pccplot] expression[domain=-3.16975:5.83642,samples=50]{f}; - \addplot[pccplot] expression[domain=6.20088:10]{f}; - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:doublezerop2} - \end{subfigure}% - \caption{$y=\dfrac{(x-3)^2}{(x+4)(x-6)}$} - \end{figure} - \begin{exercises} - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{rat:step:last}]\label{rat:prob:deduce} - \pccname{Katie} is working on graphing rational functions. She - has been concentrating on functions that have the form - \begin{equation}\label{rat:eq:deducecurve} - f(x)=\frac{a(x-b)}{x-c} - \end{equation} - Katie notes that functions with this type of formula have a zero - 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 - more thing to do to complete the graphs| follow \cref{rat:step:last}. - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,12/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \addplot[pccplot] expression[domain=-10:-5.42857]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(2,0)(0,-3/2)}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-3}); - \addplot[pccplot] expression[domain=-10:3.53846,samples=50]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(6,0)(0,3)}; - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[pccplot] expression[domain=-10:3.5,samples=50]{f}; - \addplot[pccplot] expression[domain=4.3333:10]{f}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{problem} - - \begin{figure}[!htb] - \begin{widepage} - \setlength{\figurewidth}{0.3\textwidth} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-4,0)(0,12/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve1} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(2,0)(0,-3/2)}; - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{-3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve2} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(6,0)(0,3)}; - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducecurve4} - \end{subfigure} - \caption{Graphs for \cref{rat:prob:deduce}} - \label{rat:fig:deducecurve} - \end{widepage} - \end{figure} - - %=================================== - % Author: Hughes - % Date: June 2012 - %=================================== - \begin{problem}[\Cref{rat:step:last} for more complicated rational functions]\label{rat:prob:deducehard} - \pccname{David} is also working on graphing rational functions, and - has been concentrating on functions that have the form - \[ - r(x)=\frac{a(x-b)(x-c)}{(x-d)(x-e)} - \] - David notices that functions with this type of formula have simple zeros - 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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(6,0)(0,9/2)}; - \addplot[asymptote,domain=-10:10]({-1},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[pccplot] expression[domain=-10:-1.24276]{f}; - \addplot[pccplot] expression[domain=-0.6666:3.66667]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(2,0)(0,3/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \addplot[pccplot] expression[domain=-10:-5.4861]{f}; - \addplot[pccplot] expression[domain=-4.68395:5.22241]{f}; - \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, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\solutionfigurewidth, - ] - \addplot[soldot] coordinates{(-3,0)(7,0)(0,1.4)}; - \addplot[asymptote,domain=-10:10]({-6},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \addplot[pccplot] expression[domain=-10:-6.91427]{f}; - \addplot[pccplot] expression[domain=-5.42252:4.66427]{f}; - \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} - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(6,0)(0,9/2)}; - \addplot[asymptote,domain=-10:10]({-1},{x}); - \addplot[asymptote,domain=-10:10]({4},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard1} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(2,0)(0,3/5)}; - \addplot[asymptote,domain=-10:10]({-5},{x}); - \addplot[asymptote,domain=-10:10]({6},{x}); - \addplot[asymptote,domain=-10:10]({x},{3}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard2} - \end{subfigure}% - \hfill - \begin{subfigure}{\figurewidth} - \begin{tikzpicture} - \begin{axis}[ - xmin=-10,xmax=10, - ymin=-10,ymax=10, - xtick={-8,-6,...,8}, - width=\textwidth, - ] - \addplot[soldot] coordinates{(-3,0)(7,0)(0,1.4)}; - \addplot[asymptote,domain=-10:10]({-6},{x}); - \addplot[asymptote,domain=-10:10]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{2}); - \end{axis} - \end{tikzpicture} - \caption{} - \label{rat:fig:deducehard3} - \end{subfigure}% - \hfill - \caption{Graphs for \cref{rat:prob:deducehard}} - \label{rat:fig:deducehard} - \end{widepage} - \end{figure} - %=================================== - % Author: Adams (Hughes) - % Date: March 2012 - %=================================== - \begin{problem}[\Crefrange{rat:step:first}{rat:step:last}] - Use \crefrange{rat:step:first}{rat:step:last} to sketch a graph of - each of the following functions - \fixthis{need 2 more subproblems here} - \begin{multicols}{4} - \begin{subproblem} - $y=\dfrac{4}{x+2}$ - \begin{shortsolution} - Vertical intercept: $(0,2)$; vertical asymptote: $x=-2$, horizontal asymptote: $y=0$. - - \begin{tikzpicture} - \begin{axis}[ - framed, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-2.8]{4/(x+2)}; - \addplot[pccplot] expression[domain=-1.2:5]{4/(x+2)}; - \addplot[soldot]coordinates{(0,2)}; - \addplot[asymptote,domain=-5:5]({-2},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{2x-1}{x^2-9}$ - \begin{shortsolution} - 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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-3.23974]{(2*x-1)/(x^2-9)}; - \addplot[pccplot,samples=50] expression[domain=-2.77321:2.83974]{(2*x-1)/(x^2-9)}; - \addplot[pccplot] expression[domain=3.17321:5]{(2*x-1)/(x^2-9)}; - \addplot[soldot]coordinates{(0,1/9)(1/2,0)}; - \addplot[asymptote,domain=-5:5]({-3},{x}); - \addplot[asymptote,domain=-5:5]({3},{x}); - \addplot[asymptote,domain=-5:5]({x},{0}); - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{x+3}{x-5}$ - \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, - xmin=-10,xmax=10, - ymin=-5,ymax=5, - xtick={-8,-6,...,8}, - minor ytick={-3,-1,...,3}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:3.666]{(x+3)/(x-5)}; - \addplot[pccplot] expression[domain=7:10]{(x+3)/(x-5)}; - \addplot[asymptote,domain=-5:5]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{1}); - \addplot[soldot]coordinates{(0,-3/5)(-3,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{2x+3}{3x-1}$ - \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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:0.1176]{f}; - \addplot[pccplot] expression[domain=0.6153:5]{f}; - \addplot[asymptote,domain=-5:5]({1/3},{x}); - \addplot[asymptote,domain=-5:5]({x},{2/3}); - \addplot[soldot]coordinates{(0,-3)(-3/2,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{4-x^2}{x^2-9}$ - \begin{shortsolution} - 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, - xmin=-5,xmax=5, - ymin=-5,ymax=5, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-5:-3.20156]{f}; - \addplot[pccplot,samples=50] expression[domain=-2.85774:2.85774]{f}; - \addplot[pccplot] expression[domain=3.20156:5]{f}; - \addplot[asymptote,domain=-5:5]({-3},{x}); - \addplot[asymptote,domain=-5:5]({3},{x}); - \addplot[asymptote,domain=-5:5]({x},{-1}); - \addplot[soldot] coordinates{(-2,0)(2,0)(0,-4/9)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{(4x+5)(3x-4)}{(2x+5)(x-5)}$ - \begin{shortsolution} - 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, - xmin=-10,xmax=10, - ymin=-20,ymax=20, - xtick={-8,-6,...,8}, - ytick={-10,0,...,10}, - minor ytick={-15,-5,...,15}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot] expression[domain=-10:-2.73416]{f}; - \addplot[pccplot] expression[domain=-2.33689:4.2792]{f}; - \addplot[pccplot] expression[domain=6.26988:10]{f}; - \addplot[asymptote,domain=-20:20]({-5/2},{x}); - \addplot[asymptote,domain=-20:20]({5},{x}); - \addplot[asymptote,domain=-10:10]({x},{6}); - \addplot[soldot]coordinates{(0,4/5)(-5/4,0)(4/3,0)}; - \end{axis} - \end{tikzpicture} - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Inverse functions] - Each of the following rational functions are invertible - \[ - F(x)=\frac{2x+1}{x-3}, \qquad G(x)= \frac{1-4x}{x+3} - \] - \begin{subproblem} - State the domain of each function. - \begin{shortsolution} - \begin{itemize} - \item The domain of $F$ is $(-\infty,3)\cup(3,\infty)$. - \item The domain of $G$ is $(-\infty,-3)\cup(-3,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Find the inverse of each function, and state its domain. - \begin{shortsolution} - \begin{itemize} - \item $F^{-1}(x)=\frac{3x+1}{x-2}$; the domain of $F^{-1}$ is $(-\infty,2)\cup(2,\infty)$. - \item $G^{-1}(x)=\frac{3x+1}{x+4}$; the domain of $G^{-1}$ is $(-\infty,-4)\cup(-4,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - Hence state the range of the original functions. - \begin{shortsolution} - \begin{itemize} - \item The range of $F$ is the domain of $F^{-1}$, which is $(-\infty,2)\cup(2,\infty)$. - \item The range of $G$ is the domain of $G^{-1}$, which is $(-\infty,-4)\cup(-4,\infty)$. - \end{itemize} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - State the range of each inverse function. - \begin{shortsolution} - \begin{itemize} - \item The range of $F^{-1}$ is the domain of $F$, which is $(-\infty,3)\cup(3,\infty)$. - \item The range of $G^{-1}$ is the domain of $G$, which is $(-\infty,-3)\cup(-3,\infty)$. - \end{itemize}<++> - \end{shortsolution} - \end{subproblem} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Composition] - Let $r$ and $s$ be the rational functions that have formulas - \[ - r(x)=\frac{3}{x^2},\qquad s(x)=\frac{4-x}{x+5} - \] - Evaluate each of the following. - \begin{multicols}{3} - \begin{subproblem} - $(r\circ s)(0)$ - \begin{shortsolution} - $\frac{75}{16}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(0)$ - \begin{shortsolution} - $(s\circ r)(0)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(r\circ s)(2)$ - \begin{shortsolution} - $\frac{147}{4}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(3)$ - \begin{shortsolution} - $192$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(4)$ - \begin{shortsolution} - $(s\circ r)(4)$ is undefined. - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $(s\circ r)(x)$ - \begin{shortsolution} - $\dfrac{4x^2-3}{1+5x^2}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \end{problem} - %=================================== - % Author: Hughes - % Date: March 2012 - %=================================== - \begin{problem}[Piecewise rational functions] - The function $R$ has formula - \[ - R(x)= - \begin{dcases} - \frac{2}{x+3}, & x<-5 \\ - \frac{x-4}{x-10}, & x\geq -5 - \end{dcases} - \] - Evaluate each of the following. - \begin{multicols}{4} - \begin{subproblem} - $R(-6)$ - \begin{shortsolution} - $-\frac{2}{3}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(-5)$ - \begin{shortsolution} - $\frac{3}{5}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(-3)$ - \begin{shortsolution} - $\frac{7}{13}$ - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $R(5)$ - \begin{shortsolution} - $-\frac{1}{5}$ - \end{shortsolution} - \end{subproblem} - \end{multicols} - \begin{subproblem} - What is the domain of $R$? - \begin{shortsolution} - $(-\infty,10)\cup(10,\infty)$ - \end{shortsolution} - \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}$ - \begin{shortsolution} - \begin{enumerate} - \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, - xmin=-20,xmax=20, - ymin=-30,ymax=30, - xtick={-10,10}, - minor xtick={-15,-5,...,15}, - minor ytick={-10,10}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot,samples=50] expression[domain=-20:3.54724]{f}; - \addplot[pccplot,samples=50] expression[domain=4.80196:20]{f}; - \addplot[asymptote,domain=-30:30]({4},{x}); - \end{axis} - \end{tikzpicture} - \end{enumerate} - \end{shortsolution} - \end{subproblem} - \begin{subproblem} - $y=\dfrac{x^3(x+3)}{x-5}$ - \begin{shortsolution} - \begin{enumerate} - \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, - xmin=-10,xmax=10, - ymin=-500,ymax=2500, - xtick={-8,-6,...,8}, - ytick={500,1000,1500,2000}, - grid=both, - width=\solutionfigurewidth, - ] - \addplot[pccplot,samples=50] expression[domain=-10:4]{f}; - \addplot[pccplot] expression[domain=5.6068:9.777]{f}; - \addplot[asymptote,domain=-500:2500]({5},{x}); - \end{axis} - \end{tikzpicture} - \end{enumerate} - \end{shortsolution} - \end{subproblem} diff --git a/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex b/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex deleted file mode 100644 index c7e3cce3730..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/stylefile.tex +++ /dev/null @@ -1,135 +0,0 @@ -% arara: indent: {overwrite: yes} -% http://tex.stackexchange.com/questions/106244/using-a-lot-of-marginpars -\ProvidesPackage{tabto}[2013/03/25 \space v 1.3 \space -Another tabbing mechanism]\relax - -\newdimen\CurrentLineWidth -\let\TabPrevPos\z@ - -\newcommand\tabto[1]{% - \leavevmode - \begingroup - \def\@tempa{*}\def\@tempb{#1}% - \ifx\@tempa\@tempb % \tab* - \endgroup - \TTo@overlaptrue % ... set a flag and re-issue \tabto to get argument - \expandafter\tabto - \else - \ifinner % in a \hbox, so ignore - \else % unrestricted horizontal mode - \null% \predisplaysize will tell the position of this box (must be box) - \parfillskip\fill - \everydisplay{}\everymath{}% - \predisplaypenalty\@M \postdisplaypenalty\@M - $$% math display so we can test \predisplaysize - \lineskiplimit=-999pt % so we get pure \baselineskip - \abovedisplayskip=-\baselineskip \abovedisplayshortskip=-\baselineskip - \belowdisplayskip\z@skip \belowdisplayshortskip\z@skip - \halign{##\cr\noalign{% - % get the width of the line above - %\message{>>> Line \the\inputlineno\space -- \predisplaydirection\the\predisplaydirection, \predisplaysize\the\predisplaysize, \displayindent\the\displayindent, \leftskip\the\leftskip, \linewidth\the\linewidth. }% - \ifdim\predisplaysize=\maxdimen % mixed R and L; call the line full - \message{Mixed R and L, so line is full. }% - \CurrentLineWidth\linewidth - \else - \ifdim\predisplaysize=-\maxdimen % impossible, in vmode; call the line empty - \message{Not in paragraph, so line is empty. }% - \CurrentLineWidth\z@ - \else - \ifnum\TTo@Direction<\z@ - \CurrentLineWidth\linewidth \advance\CurrentLineWidth\predisplaysize - \else - \CurrentLineWidth\predisplaysize - \fi - % Correct the 2em offset - \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 -} - -% \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 - -\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>{} - -\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}% -} - -% default setting of tab positions: -\TabPositions{\parindent,.5\linewidth} - -\newif\ifTTo@overlap \TTo@overlapfalse - -\@ifundefined{predisplaydirection}{ - \let\TTo@Direction\predisplaysize - \let\predisplaydirection\@undefined -} -{ - \let\TTo@Direction\predisplaydirection -} diff --git a/Master/texmf-dist/doc/support/latexindent/success/table1.tex b/Master/texmf-dist/doc/support/latexindent/success/table1.tex deleted file mode 100644 index 5002f8b81a6..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/table1.tex +++ /dev/null @@ -1,22 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -\documentclass{article} -\usepackage{multirow} -\usepackage{booktabs} -\begin{document} -\begin{table}[h!] - \centering - \caption{mycaption} - \label{tab:test} - \begin{tabular}{llll} - \toprule - \textbf{headerone} & \textbf{headertwo} & \textbf{headerthree} & \textbf{headerfour} \\\midrule - r1c1 & r1c2 & r1c3 & \multirow{4}{*}{norowlinesinthefirstfourrows} \\\cmidrule{1-3} - r2c1 & r2c2 & r2c3 & \\\cmidrule{1-3} - r3c1 & r3c2 & r3c3 & \\\cmidrule{1-3} - r4c1 & r4c2 & r4c3 & \\\midrule - r5c1 & r5c2 & r5c3 & \\\midrule - r6c1 & r6c2 & r6c3 & \\\midrule - r7c1 & r7c2 & r7c3 & \\\bottomrule - \end{tabular} -\end{table} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/table2.tex b/Master/texmf-dist/doc/support/latexindent/success/table2.tex deleted file mode 100644 index cc0c12cc763..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/table2.tex +++ /dev/null @@ -1,26 +0,0 @@ -% arara: indent: {overwrite: true, silent: yes} -\documentclass{article} -\usepackage{array} % Thanks to Heiko for catching the redundant package loading -\newcolumntype{M}{>{$}c<{$}} - -\begin{document} - -\begin{table}% - \centering - \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} - \caption{Some caption} - \label{table:mytable} -\end{table} -\end{document} - diff --git a/Master/texmf-dist/doc/support/latexindent/success/table3.tex b/Master/texmf-dist/doc/support/latexindent/success/table3.tex deleted file mode 100644 index 19007908e01..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/table3.tex +++ /dev/null @@ -1,26 +0,0 @@ -% !arara: pdflatex -% arara: indent: {overwrite: yes, trace: on} -\documentclass{article} -\usepackage{multirow} - -\begin{document} -\begin{figure*} - \centering - \begin{tabular}{|c|c|c c c c|c|} - \hline - \multicolumn{2}{|c|}{\multirow{2}{*}{$V_{\rm rot}/{\sigma}$}}&\multicolumn{4}{c|}{W1}\\ - \cline{3-6} - \multicolumn{2}{|c|}{}&3&6&9&12\\ - \hline - \multirow{6}{*}{W2} & \multirow{3}{*}{3} & $0.090475\pm 0.011115$ & \multirow{3}{*}{21} & \multirow{3}{*}{6} & \multirow{3}{*}{3} \\ - & & $0.14861\pm 0.03562$ & & & \\ - & & $0.1861 \pm 0.01728$ & & & \\ - & 6 & 8 & 14 & 5 & 2 \\ - & 9 & 8 & 14 & 5 & 2 \\ - & 12 & 8 & 14 & 5 & 2 \\ - \hline - \end{tabular} - \caption{Multirow in multirow} - \label{ta.Multirow} -\end{figure*} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/table4.tex b/Master/texmf-dist/doc/support/latexindent/success/table4.tex deleted file mode 100644 index 6f6e71323ce..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/table4.tex +++ /dev/null @@ -1,22 +0,0 @@ -% 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 deleted file mode 100644 index e2750f40d78..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/table5.tex +++ /dev/null @@ -1,35 +0,0 @@ -\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 deleted file mode 100644 index 565157dcaca..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/testHeadings-simple.tex +++ /dev/null @@ -1,56 +0,0 @@ -% 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/testHeadings.tex b/Master/texmf-dist/doc/support/latexindent/success/testHeadings.tex deleted file mode 100644 index 2a8fa072e4e..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/testHeadings.tex +++ /dev/null @@ -1,59 +0,0 @@ -% 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 - \[ - f(x)=x^2 - \] - \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/testHeadings1.tex b/Master/texmf-dist/doc/support/latexindent/success/testHeadings1.tex deleted file mode 100644 index 164fcbe1057..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/testHeadings1.tex +++ /dev/null @@ -1,25 +0,0 @@ -% arara: indent: {overwrite: yes, localSettings: yes, trace: on} -\documentclass[a4paper]{article} -\usepackage{filecontents} -\begin{filecontents} - \begin{document} - hello world - \end{document} -\end{filecontents} -\begin{document} -\section{} -\subsection{} - \subsubsection{} - some text goes here - some text goes here - some text goes here - \begin{verbatim} - \documentclass[<+options+>]{<+class+>} - - \begin{document} - <++> - \end{document} - \end{document} - more text here - \end{verbatim} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/testItems.tex b/Master/texmf-dist/doc/support/latexindent/success/testItems.tex deleted file mode 100644 index fba97784548..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/testItems.tex +++ /dev/null @@ -1,94 +0,0 @@ -% arara: indent: {overwrite: yes, silent: off, trace: yes, localSettings: yes} - -\begin{itemize} - \item some text here - some more text here - some more text here - \item another item more text - more text more text more text - more text more text more text - \item - more text more text more text - more text more text more text -\end{itemize} - -regular text -regular text -regular text -\begin{itemize} - \item some other stuff - \item[1] some other stuff - \myitem another item - \myitem[2] another item - \item some other stuff - \item some other stuff - \item some other stuff - \item some text some text - some text some text - some text some text - % here's a comment - \item some text some text - some text some text - some text some text - \[ - x^2 - \] - \item some text some text - some text some text - some text some text - \begin{list} - \item some other stuff - some other stuff - some other stuff - % here's a comment - \end{list} - \item some text some text - some text some text - some text some text - \begin{myenv} - some other stuff - some other stuff - some other stuff - \end{myenv} - \begin{itemize} - \item some text some text - some text some text - some text some text - % here's a comment - \item some text some text - some text some text - some text some text - \[ - x^2 - \] - \item some text some text - some text some text - some text some text - \begin{list} - \item some other stuff - some other stuff - some other stuff - % here's a comment - \end{list} - - \item some text some text - some text some text - some text some text - \begin{myenv} - some other stuff - some other stuff - some other stuff - \end{myenv} - \item just one line - some more text - \item something here - \end{itemize} - \item this one belongs here - more text more text more text -\end{itemize} - -\begin{myenv} - some other stuff - some other stuff - some other stuff -\end{myenv} diff --git a/Master/texmf-dist/doc/support/latexindent/success/testcls.cls b/Master/texmf-dist/doc/support/latexindent/success/testcls.cls deleted file mode 100644 index d4c23660c5a..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/testcls.cls +++ /dev/null @@ -1,375 +0,0 @@ -% arara: indent: {overwrite: yes} -\NeedsTeXFormat{LaTeX2e} -\ProvidesClass{rpisudiss}[2014/07/06 Ryan Pavlik's ISU Thesis] - -\newcommand{\@isu@classname}{rpisudiss} -\RequirePackage{setspace} - -% option doublespacing: Double-space where we would have 1.5 spaced. -\newcommand\isu@spacing{\onehalfspacing} -\newcommand\isu@space{onehalfspace} -\DeclareOption{doublespacing}{% - \renewcommand\isu@spacing{\doublespacing} - \renewcommand\isu@space{doublespace} -} - -% option capstoc: Capitalize chapters in the table of contents -% Technically required if you go by the text of the grad college site, -% but rule inconsistently applied and results painful to read. -\newif\if@isu@capstoc \@isu@capstocfalse -\DeclareOption{capstoc}{\@isu@capstoctrue} - -% option capschap: Capitalize chapters everywhere else -% Technically required if you go by the text of the grad college site, -% but rule inconsistently applied and results painful to read. -\newif\if@isu@capschap \@isu@capschapfalse -\DeclareOption{capschap}{\@isu@capschaptrue} - -% option print: Optimize for print rather than on-screen (hide links, etc.) -% Apparently doesn't work right now. Sad. -\newif\if@isu@print \@isu@printfalse -\DeclareOption{print}{\@isu@printtrue} - -% option tocnumbersections: Number sections in the ToC. -\newif\if@isu@tocnumbersections@ \@isu@tocnumbersections@false -\DeclareOption{tocnumbersections}{\@isu@tocnumbersections@true} - -% option tocnumbersubsections: Number subsections in the ToC. Implies tocnumbersections. -\newif\if@isu@tocnumbersubsections@ \@isu@tocnumbersubsections@false -\DeclareOption{tocnumbersubsections}{ \@isu@tocnumbersubsections@true\@isu@tocnumbersections@true} - -% option ignoremissingmainmatter: Don't error if we've seen a titlepage but no \mainmatter by the end of the document. -\newif\if@isu@errormissingmainmatter@ \@isu@errormissingmainmatter@true -\DeclareOption{ignoremissingmainmatter}{\@isu@errormissingmainmatter@false} - -% option draftcls: adds "DRAFT" and a date/time stamp on the footer. -\newif\if@isu@draftcls@ \@isu@draftcls@false -\DeclareOption{draftcls}{\@isu@draftcls@true} - -% option draft: draftcls plus whatever anyone else thinks about draft. -\DeclareOption{draft}{ - \@isu@draftcls@true - \PassOptionsToClass{draft}{report} -} - -% Forward everything not recognized -\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}} - -% Process options -\ProcessOptions\relax - -% Based on report -\LoadClass[12pt]{report} - -% had to choose to put this here for tocloft -\RequirePackage{subfig} - -% Put lot, lof, and bibliography (but not the contents itself) in the ToC -\RequirePackage[nottoc]{tocbibind} - -% Basic hyperref - note that backreferences are incompatible with bibtopic (for per-chapter bibliographies) -\RequirePackage[pdftex,pdfusetitle,hypertexnames=false,linktocpage=true]{hyperref} -\hypersetup{bookmarksnumbered=true,bookmarksopen=true,pdfpagemode=UseOutlines,pdfview=FitB} - -\if@isu@print -% Hide links for print -% Apparently doesn't work right now. Sad. -\hypersetup{hidelinks} -\else -% Nice blue links. -\hypersetup{colorlinks=true,linkcolor=blue,anchorcolor=blue,citecolor=blue,filecolor=blue,urlcolor=blue} -\fi - -% Indent first paragraph after sectioning things. -\RequirePackage{indentfirst} - -% Setup page layout -\RequirePackage{geometry} -\geometry{left=1in, top=1in, headheight=0.25in, headsep=0.5in, right=1in, bottom=1in, includehead=false} - -% Handle draftcls option placing timestamp in footer and watermarking first page. -\if@isu@draftcls@ - \RequirePackage[firstpage]{draftwatermark} - \RequirePackage{datetime} - \newcommand{\isu@draftfooter}{DRAFT --- rendered \today\ at \currenttime} -\else - \newcommand{\isu@draftfooter}{} -\fi - -% Setup headers/footers - override the plain page style. -\RequirePackage{fancyhdr} -\fancypagestyle{plain}{% - \fancyhf{} % clear all header and footer fields - \fancyhead[C]{\thepage} % Always put the page in the center header - \fancyfoot[C]{\isu@draftfooter} % In draft mode, put stuff in the center footer. - \renewcommand{\headrulewidth}{0pt} - \renewcommand{\footrulewidth}{0pt}} - -\AtBeginDocument{\pagestyle{plain}} - -% Set up a bool for mainmatter or not. -\newif\if@mainmatter \@mainmatterfalse - -% Title page: -% - empty style (no numbering shown) -% - starts the preface/roman numerals -% - gets a PDF bookmark, just because we can. -\renewcommand{\titlepage}{ - \thispagestyle{empty} - \pagenumbering{roman} - \pdfbookmark[0]{\@title}{toc} - % backup and set secnumdepth - \newcounter{isu@secnumdepth} - \setcounter{isu@secnumdepth}{\value{secnumdepth}} - \setcounter{secnumdepth}{-1} - \@mainmatterfalse -} -\renewcommand{\endtitlepage}{\newpage\pagestyle{plain}} - -%%% -% Set up sectioning -\RequirePackage{titlesec} -% \titleformat{command}[shape]{format}{label}{sep}{before}[after] - -% Chapter titles: -% - Caps (optional) -% - large -% - bold -% - center -\titleformat{\chapter}[block] -{\normalfont\large\bfseries\centering} -{\if@mainmatter% - \if@isu@capschap\MakeUppercase{\chaptertitlename}% - \else\chaptertitlename\fi - \thechapter.\quad\fi} -{0pt} -{\if@isu@capschap\MakeUppercase\fi}{} - -% Section: -% - bold -% - center -\titleformat{\section}[block] -{\normalfont\normalsize\bfseries\centering} -{\thesection.}{1em}{}{} - -% Subsection: -% - bold -% - left-justified -\titleformat{\subsection}[block] -{\normalfont\normalsize\bfseries} -{\thesubsection.}{1em}{}{} - -% Subsubsection: -% - bold -% - left-justified with indent -\titleformat{\subsubsection}[block] -{\normalfont\normalsize\bfseries} -{\quad\thesubsubsection.}{1em}{}{} - -% Apply default spacing -\isu@spacing - - -% Needed for toc/lof/lot spacing and headfoot tweaking -\RequirePackage{xpatch} - -%%% -% ToC: - -% Rename the ToC -\RequirePackage[subfigure,titles]{tocloft} -\renewcommand{\contentsname}{Table of Contents} - -% - Remove parskips from toc (and lof/lot) -\setlength{\cftparskip}{0pt} - -% - Single space -% - 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}{}{} -%\end{noindent} - -% - Add dot leader for chapter levels -\renewcommand\cftchapdotsep{\cftdotsep} - -% - Prefix "Chapter " to chapter number -% - 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} -\else - \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}} -\fi - -\if@isu@tocnumbersubsections@\else -\renewcommand{\cftsubsecpresnum}{\begin{lrbox}{\@tempboxa}} -\renewcommand{\cftsubsecaftersnum}{\end{lrbox}} -\fi - -%%% -% List of Figures: -% - Single space -% - Page break after -%\begin{noindent} -\xpretocmd{\listoffigures}{% -\begin{singlespace}}{}{} -\xapptocmd{\listoffigures}{% -\end{singlespace}\clearpage}{}{} -%\end{noindent} - -% - Prepend the word "Figure" to the number -\renewcommand\cftfigpresnum{Figure } -\cftsetindents{figure}{0em}{6em} - -%%% -% List of Tables: -% - Single space -% - Page break after -%\begin{noindent} -\xpretocmd{\listoftables}{% - \begin{singlespace}}{}{} -\xapptocmd{\listoftables}{% - \end{singlespace}\clearpage}{}{} -%\end{noindent} - -% - Prepend the word "Table" to the number -\renewcommand\cfttabpresnum{Table } -\cftsetindents{table}{0em}{6em} - -%%% -% Document division commands - -% Command to indicate when we're done -% with preface content - must be called! -% (If we're actually typesetting a full thesis...) -\newcommand{\mainmatter}{% - \clearpage - \pagenumbering{arabic} - \pagestyle{plain} - \@mainmattertrue - \newcommand{\@isu@gotmainmatter@}{} - \setcounter{chapter}{0} - % restore secnumdepth - \setcounter{secnumdepth}{\value{isu@secnumdepth}} -} - -% Command to indicate we're done with main content -\newcommand{\backmatter}{ - \setcounter{isu@secnumdepth}{\value{secnumdepth}} - \setcounter{secnumdepth}{-1} - \@mainmatterfalse -} - -\RequirePackage{etoolbox} -% 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.} - \fi - \fi - \fi -} - -%%% -% Title Page - -% Temporary: hardcode these values in. -\newcommand\isu@degree{Doctor of Philosophy} -\newcommand\isu@gradyear{2014} -\newcommand\isu@submissiontype{dissertation} -\newcommand\isu@majorline{Co-majors: Human-Computer Interaction; Computer Science} -\newcommand\isu@committee{% - Judy M. Vance, Co-major Professor\\% - Leslie Miller, Co-major Professor\\% - Debra Satterfield \\ Jonathan Kelly \\ David Weiss \\ Horea Ilies} -\newcommand\isu@copyrightnotice{\\ % Unclear what the spacing between notice and the text above should be. - Copyright \copyright\ \@author, \isu@gradyear. -All rights reserved.} - -% Spacing tools -% - used for what the thesis office calls "two blank lines" -\newcommand{\@isu@twoblanklines}{20pt} -\newcommand{\@isu@maketwoblanklines}{\vspace{\@isu@twoblanklines}} - -% The actual title page layout. -% Note that portions that appear double-spaced in the sample/annotated PDF -% are given the same spacing as the body of the document (1.5 or 2) -\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" - by\\ % the word 'by', not in bold - \@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} -} - -\endinput - diff --git a/Master/texmf-dist/doc/support/latexindent/success/theorem.tex b/Master/texmf-dist/doc/support/latexindent/success/theorem.tex deleted file mode 100644 index 6541ed31ceb..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/theorem.tex +++ /dev/null @@ -1,47 +0,0 @@ -% arara: indent: {overwrite: on} -\documentclass[12pt,twoside]{report} -\usepackage[margin=2cm]{geometry} -\usepackage{amsmath,amsthm,amssymb} -\usepackage{thmtools} -\usepackage{tikz} -\usepackage[framemethod=TikZ]{mdframed} - -\declaretheoremstyle -[ - spaceabove=0pt, spacebelow=0pt, headfont=\normalfont\bfseries, - notefont=\mdseries, notebraces={(}{)}, headpunct={\newline}, headindent={}, - postheadspace={ }, postheadspace=4pt, bodyfont=\normalfont, qed=$\blacktriangle$, - preheadhook={\begin{mdframed}[style=myframedstyle]}, - postfoothook=\end{mdframed}, -]{mystyle} - -\declaretheorem[style=mystyle,numberwithin=chapter,title=Exemplo]{example} -\mdfdefinestyle{myframedstyle}{% - outermargin = 1.3cm , % - leftmargin = 0pt , rightmargin = 0pt , % - innerleftmargin = 5pt , innerrightmargin = 5pt , % - innertopmargin = 5pt, innerbottommargin = 5pt , % - backgroundcolor = blue!10 , % - align = center , % align the environment itself (left, center, rigth) - nobreak = true, % prevent a frame from splitting - hidealllines = true , % - topline = true , bottomline = true , % - splittopskip = \topskip , splitbottomskip = 0pt , % - skipabove = 0.5\baselineskip , skipbelow = 0.3\baselineskip} - -\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 - \textbf{Solução:} - \newline - $PV = 800 \times \left[ \dfrac{1,012^{48}-1}{1,012^{48}\times 0,012} \right] \newline - 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/tikz1.tex b/Master/texmf-dist/doc/support/latexindent/success/tikz1.tex deleted file mode 100644 index ccef3d047f2..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/tikz1.tex +++ /dev/null @@ -1,88 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -\documentclass[png,border=10pt,tikz]{standalone} -\usepackage{xstring} -\usepackage{tikz} -\usetikzlibrary{calc} - -\pgfkeys{/tikz/.cd, - vertical factor/.initial=0.5, - vertical factor/.get=\vertfactor, - vertical factor/.store in=\vertfactor, - start coordinate/.initial={0,\vertfactor}, - start coordinate/.get=\startcoord, - start coordinate/.store in=\startcoord, - sample color/.initial=black, - sample color/.get=\samplecol, - sample color/.store in=\samplecol, - sample size/.initial=1pt, - sample size/.get=\samplesize, - sample size/.store in=\samplesize, - sample line width/.initial=very thick, - sample line width/.get=\samplelinewidth, - sample line width/.store in=\samplelinewidth, -} - - -\newcommand{\samplepath}[1]{% - \coordinate (start) at (\startcoord) ; - \foreach \samples[count=\xi from 1] in {#1}{% - \StrCut{\samples}{|}{\vertdir}{\hordir} - \ifnum\xi=1 - \draw[\samplelinewidth,\samplecol](start) - --++(\hordir,0) coordinate (start); - \else - \IfStrEq{\vertdir}{+}{%true - \draw[\samplelinewidth,\samplecol]($(start)+(0,\vertfactor)$) - --++(\hordir,0)coordinate(start); - }{%false - \relax - } - \IfStrEq{\vertdir}{-}{%true - \draw[\samplelinewidth,\samplecol]($(start)+(0,-\vertfactor)$) - --++(\hordir,0)coordinate(start); - }{%false - \relax - } - \fi - } -} - -\tikzset{sample/.style={ - circle, - inner sep=\samplesize, - fill=\samplecol, - } -} - -\newcommand{\discretesamplepath}[1]{% - \coordinate (start) at (\startcoord) ; - \foreach \samples[count=\xi from 1] in {#1}{% - \StrCut{\samples}{|}{\vertdir}{\hordir} - \ifnum\xi=1 - \path(start)node[sample]{} - --++(\hordir,0) coordinate (start); - \else - \IfStrEq{\vertdir}{+}{%true - \path($(start)+(0,\vertfactor)$)node[sample]{} - --++(\hordir,0)coordinate(start); - }{%false - \relax - } - \IfStrEq{\vertdir}{-}{%true - \path($(start)+(0,-\vertfactor)$)node[sample]{} - --++(\hordir,0)coordinate(start); - }{%false - \relax - } - \fi - } -} - -\begin{document} -\begin{tikzpicture} - % axis - \draw[-stealth] (0,-1)--(0,4) node[left]{$X(t)$}; - \draw[-stealth] (-1,0)--(5,0) node[below]{$t$}; - \samplepath{+|0.5,+|0.25,-|1.5,+|1,+|0.5,+|0.75} -\end{tikzpicture} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/tikz2.tex b/Master/texmf-dist/doc/support/latexindent/success/tikz2.tex deleted file mode 100644 index 5ba03622079..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/tikz2.tex +++ /dev/null @@ -1,61 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -% http://tex.stackexchange.com/questions/104528/tikz-shade-also-the-border-of-a-node -\documentclass[tikz,border=10pt,png]{standalone} -\usepackage{tikz} -\usetikzlibrary{calc} -\begin{document} -\tikzset{ - shrink inner sep/.code={ - \pgfkeysgetvalue{/pgf/inner xsep}{\currentinnerxsep} - \pgfkeysgetvalue{/pgf/inner ysep}{\currentinnerysep} - \pgfkeyssetvalue{/pgf/inner xsep}{\currentinnerxsep - 0.5\pgflinewidth} - \pgfkeyssetvalue{/pgf/inner ysep}{\currentinnerysep - 0.5\pgflinewidth} - } -} - -\tikzset{horizontal shaded border/.style args={#1 and #2}{ - append after command={ - \pgfextra{% - \begin{pgfinterruptpath} - \path[rounded corners,left color=#1,right color=#2] - ($(\tikzlastnode.south west)+(-\pgflinewidth,-\pgflinewidth)$) - rectangle - ($(\tikzlastnode.north east)+(\pgflinewidth,\pgflinewidth)$); - \end{pgfinterruptpath} - } - } - }, - vertical shaded border/.style args={#1 and #2}{ - append after command={ - \pgfextra{% - \begin{pgfinterruptpath} - \path[rounded corners,top color=#1,bottom color=#2] - ($(\tikzlastnode.south west)+(-\pgflinewidth,-\pgflinewidth)$) - rectangle - ($(\tikzlastnode.north east)+(\pgflinewidth,\pgflinewidth)$); - \end{pgfinterruptpath} - } - } - } -} -\begin{tikzpicture} - \draw (0,0) node[rectangle, - rounded corners, - thick, - outer sep=0pt, - shrink inner sep, - left color=red!50!white, - right color=green!50!white, - horizontal shaded border=red and green - ](A){abcabc abc}; - \draw (2.5,0) node[rectangle, - rounded corners, - thick, - outer sep=0pt, - shrink inner sep, - top color=cyan!50, - bottom color=orange!50, - vertical shaded border=blue and orange - ](A){abcabc abc}; -\end{tikzpicture} -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/tikz3.tex b/Master/texmf-dist/doc/support/latexindent/success/tikz3.tex deleted file mode 100644 index f50646ac5c8..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/tikz3.tex +++ /dev/null @@ -1,53 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -\documentclass[11pt]{article} -\usepackage{tikz} -\usetikzlibrary{trees} -\usetikzlibrary{decorations.pathmorphing} -\usetikzlibrary{decorations.markings} - -\begin{document} - -\tikzset{ - photon/.style={decorate, decoration={snake}, draw=red}, - particle/.style={draw=blue, postaction={decorate}, - decoration={markings,mark=at position .5 with {\arrow[draw=blue]{>}}}}, - antiparticle/.style={draw=blue, postaction={decorate}, - decoration={markings,mark=at position .5 with {\arrow[draw=blue]{<}}}}, - gluon/.style={decorate, draw=black, - decoration={coil,amplitude=4pt, segment length=5pt}} -} - -\begin{tikzpicture}[ - thick, - % Set the overall layout of the tree - level/.style={level distance=1.5cm}, - level 2/.style={sibling distance=3.5cm}, - ] - \coordinate - child[grow=down]{ - edge from parent [antiparticle] - child { - node{$E$} - edge from parent [particle] - } - child { - node{$D$} - edge from parent [gluon] - } - node [above=3pt] {$C$} - } - % I have to insert a dummy child to get the tree to grow - % correctly to the right. - child[grow=right, level distance=0pt] { - child { - node{$A$} - edge from parent [gluon] - } - child { - node{$B$} - edge from parent [particle] - } - }; -\end{tikzpicture} - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/tikz4.tex b/Master/texmf-dist/doc/support/latexindent/success/tikz4.tex deleted file mode 100644 index 97830271b3f..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/tikz4.tex +++ /dev/null @@ -1,27 +0,0 @@ -% arara: indent: {overwrite: true, silent: on} -\documentclass{article} - -% in the preamble -% nothing -% should happend -\foreach \x in {0,1,2,3,4}{ - \foreach \y in {0,1,2,3,4}{ - \foreach \z in {0,1,2,3,4}{ - \fill[black] (\x, \y, \z) circle (0.1); - } - } -}; -\usepackage{tikz} - -\begin{document} -\begin{tikzpicture} - \foreach \x in {0,1,2,3,4}{ - \foreach \y in {0,1,2,3,4}{ - \foreach \z in {0,1,2,3,4}{ - \fill[black] (\x, \y, \z) circle (0.1); - } - } - }; -\end{tikzpicture} -\end{document} - diff --git a/Master/texmf-dist/doc/support/latexindent/success/tikz5.tex b/Master/texmf-dist/doc/support/latexindent/success/tikz5.tex deleted file mode 100644 index b24b429e318..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/tikz5.tex +++ /dev/null @@ -1,34 +0,0 @@ -% arara: indent: {overwrite: yes} -\documentclass[professionalfont, fleqn]{beamer} -\mode -\usetheme{Warsaw} -\usetheme{CambridgeUS} - -\usepackage{pgfplots} -\usetikzlibrary{arrows,shapes,positioning} -\graphicspath{{graphics/}} - -\begin{document} -\frame -{ - \frametitle{Frame Title} - \begin{tikzpicture} - \begin{axis} - [ - axis x line = bottom, - axis y line = left, - width = 1.01\textwidth, - height = .63\textwidth, % Adjusted - ymax = 93, - ymin = 27, - ytick = {30,40,...,90}, - xmax = 1993, - xmin = 1967, - xtick = {1970, 1980, ..., 1990}, - ] - \node[anchor=west] at (axis cs:1968.5,89.5){% - \textbullet\ Comment here about data - }; - \end{axis} - \end{tikzpicture} -} diff --git a/Master/texmf-dist/doc/support/latexindent/success/torusPGF.tex b/Master/texmf-dist/doc/support/latexindent/success/torusPGF.tex deleted file mode 100644 index 0edf21a5e29..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/torusPGF.tex +++ /dev/null @@ -1,20 +0,0 @@ -% arara: indent: {overwrite: yes} -\documentclass{article} -\usepackage{pgfplots} - -\begin{document} - -\begin{tikzpicture} - \begin{axis} - \addplot3[surf, - colormap/cool, - samples=20, - domain=0:2*pi,y domain=0:2*pi, - z buffer=sort] - ({(2+cos(deg(x)))*cos(deg(y+pi/2))}, - {(2+cos(deg(x)))*sin(deg(y+pi/2))}, - {sin(deg(x))}); - \end{axis} -\end{tikzpicture} - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/torusPSTricks.tex b/Master/texmf-dist/doc/support/latexindent/success/torusPSTricks.tex deleted file mode 100644 index cd8cc0db4ad..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/torusPSTricks.tex +++ /dev/null @@ -1,18 +0,0 @@ -% arara: indent: {overwrite: on, silent: yes} -\documentclass{article} -\usepackage{pst-solides3d} -\begin{document} - -\begin{pspicture}(-3,-4)(3,6) - \psset{viewpoint=20 40 40 rtp2xyz,Decran=30,lightsrc=20 10 10} - \defFunction[algebraic]{torus}(u,v) - {(2+cos(u))*cos(v+\Pi)} - {(2+cos(u))*sin(v+\Pi)} - {sin(u)} - \psSolid[object=surfaceparametree, - base=-10 10 0 6.28,fillcolor=black!70,incolor=orange, - function=torus,ngrid=60 0.4, - opacity=0.25] -\end{pspicture} - -\end{document} diff --git a/Master/texmf-dist/doc/support/latexindent/success/trailingComments.tex b/Master/texmf-dist/doc/support/latexindent/success/trailingComments.tex deleted file mode 100644 index 060e1888df7..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/trailingComments.tex +++ /dev/null @@ -1,7 +0,0 @@ -% arara: indent: {overwrite: yes, trace: true} -\parbox{% more comments here - some stuff% comments go here }}}} - some \% stuff this is not a comment -} -some stuff -some stuff diff --git a/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex b/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex deleted file mode 100644 index 635192051f2..00000000000 --- a/Master/texmf-dist/doc/support/latexindent/success/verbatim1.tex +++ /dev/null @@ -1,21 +0,0 @@ -% 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/LatexIndent/AlignmentAtAmpersand.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm new file mode 100644 index 00000000000..3f86cffd10f --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm @@ -0,0 +1,255 @@ +package LatexIndent::AlignmentAtAmpersand; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Tokens qw/%tokens/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/align_at_ampersand find_aligned_block/; +our $alignmentBlockCounter; + +sub find_aligned_block{ + my $self = shift; + + return unless (${$self}{body} =~ m/(?!<\\)%\*\h*\\begin\{/s); + + # aligned block + # %* \begin{tabular} + # 1 & 2 & 3 & 4 \\ + # 5 & & 6 & \\ + # %* \end{tabular} + $self->logger('looking for ALIGNED blocks marked by comments','heading')if($is_t_switch_active); + $self->logger(Dumper(\%{$masterSettings{lookForAlignDelims}})) if($is_t_switch_active); + while( my ($alignmentBlock,$yesno)= each %{$masterSettings{lookForAlignDelims}}){ + if(ref $yesno eq "HASH"){ + $yesno = (defined ${$yesno}{delims} ) ? ${$yesno}{delims} : 1; + } + if($yesno){ + $self->logger("looking for $alignmentBlock:$yesno environments"); + + my $noIndentRegExp = qr/ + ( + (?!<\\) + % + \* + \h* # possible horizontal spaces + \\begin\{ + $alignmentBlock # environment name captured into $2 + \} # %* \begin{alignmentBlock} statement + ) + ( + .*? + ) + \R + \h* + ( + (?!<\\) + %\* # % + \h* # possible horizontal spaces + \\end\{$alignmentBlock\} # \end{alignmentBlock} + ) # %* \end{} statement + #\R + /sx; + + while( ${$self}{body} =~ m/$noIndentRegExp/sx){ + + ${$self}{body} =~ s/ + $noIndentRegExp + / + # create a new Environment object + my $alignmentBlock = LatexIndent::AlignmentAtAmpersand->new( begin=>$1, + body=>$2, + end=>$3, + name=>$alignmentBlock, + modifyLineBreaksYamlName=>"environments", + linebreaksAtEnd=>{ + begin=>1, + body=>1, + end=>0, + }, + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($alignmentBlock); + ${@{${$self}{children}}[-1]}{replacementText}; + /xseg; + } + } else { + $self->logger("*not* looking for $alignmentBlock as $alignmentBlock:$yesno"); + } + } + return; +} + +sub modify_line_breaks_settings{ + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; +# $self->remove_leading_space; +} + +sub create_unique_id{ + my $self = shift; + + $alignmentBlockCounter++; + ${$self}{id} = "$tokens{alignmentBlock}$alignmentBlockCounter"; + return; +} + +sub align_at_ampersand{ + my $self = shift; + return if(${$self}{bodyLineBreaks}==0); + + # calculate the maximum number of ampersands in a row in the body + my $maximumNumberOfAmpersands = 0; + foreach(split("\n",${$self}{body})){ + my $numberOfAmpersands = () = $_ =~ /(?$maximumNumberOfAmpersands); + } + + # create an array of zeros + my @columnSizes = (0) x ($maximumNumberOfAmpersands+1); + + # array for the new body + my @formattedBody; + + # now loop back through the body, and store the maximum column size + foreach(split("\n",${$self}{body})){ + # remove \\ and anything following it + my $endPiece; + if($_ =~ m/(\\\\.*)/){ + $_ =~ s/(\\\\.*)//; + $endPiece = $1; + } + + my $numberOfAmpersands = () = $_ =~ /(?$columnSizes[$columnCount]); + + # put the row back together, using " " if the column is empty + $strippedRow .= ($columnCount>0 ? "&" : q() ).(length($column)>0 ? $column: " "); + + # move on to the next column + $columnCount++; + } + + # store the information + push(@formattedBody,{ + row=>$strippedRow, + format=>1, + endPiece=>($endPiece ? $endPiece :q() ), + trailingComment=>($trailingComments ? $trailingComments :q() )}); + } else { + # otherwise simply store the row + push(@formattedBody,{ + row=>$_.($endPiece ? $endPiece : q() ), + format=>0}); + } + } + + # output some of the info so far to the log file + $self->logger("Column sizes of horizontally stripped formatted block (${$self}{name}): @columnSizes") if $is_t_switch_active; + + # README: printf( formatting, expression) + # + # formatting has the form %-50s & %-20s & %-19s + # (the numbers have been made up for example) + # the - symbols mean that each column should be left-aligned + # the numbers represent how wide each column is + # the s represents string + # the & needs to be inserted + + # join up the maximum string lengths using "s %-" + my $fmtstring = join("s & %-",@columnSizes); + + # add %- to the beginning and an s to the end + $fmtstring = "%-".$fmtstring."s "; + + # log file info + $self->logger("Formatting string is: $fmtstring",'heading') if $is_t_switch_active; + + # finally, reformat the body + foreach(@formattedBody){ + if(${$_}{format} and ${$_}{row} !~ m/^\h*$/){ + # format the row, and put the trailing \\ and trailing comments back into the row + ${$_}{row} = sprintf($fmtstring,split(/(?=0 and !${$self}{alignDoubleBackSlash}){ + my $horizontalSpaceToInsert = " "x (${$self}{spacesBeforeDoubleBackSlash}); + ${$_}{row} =~ s/\h*\\\\/$horizontalSpaceToInsert\\\\/; + } + } + + # if we have an empty row, it's possible that it originally had an end piece (e.g \\) and/or trailing comments + if(${$_}{row} =~ m/^\h*$/){ + ${$_}{row} .= (${$_}{endPiece} ? ${$_}{endPiece} :q() ).(${$_}{trailingComment}? ${$_}{trailingComment} : q() ); + } + } + + # to the log file + if($is_tt_switch_active){ + $self->logger(${$_}{row},'ttrace') for @formattedBody; + } + + # delete the original body + ${$self}{body} = q(); + + # update the body + ${$self}{body} .= ${$_}{row}."\n" for @formattedBody; + + # if the \end{} statement didn't originally have a line break before it, we need to remove the final + # line break added by the above + ${$self}{body} =~ s/\h*\R$//s if !${$self}{linebreaksAtEnd}{body}; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm new file mode 100644 index 00000000000..569cead9584 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm @@ -0,0 +1,380 @@ +package LatexIndent::Arguments; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/get_arguments_regexp find_opt_mand_arguments get_numbered_arg_regexp construct_arguments_regexp $optAndMandRegExp/; +our $ArgumentCounter; +our $optAndMandRegExp; +our $optAndMandRegExpWithLineBreaks; + +sub construct_arguments_regexp{ + my $self = shift; + + $optAndMandRegExp = $self->get_arguments_regexp; + + $optAndMandRegExpWithLineBreaks = $self->get_arguments_regexp(mode=>"lineBreaksAtEnd"); +} + +sub indent{ + my $self = shift; + $self->logger("Arguments object doesn't receive any direct indentation, but its children will...",'heading') if $is_t_switch_active; + return; +} + +sub find_opt_mand_arguments{ + my $self = shift; + + $self->logger("Searching ${$self}{name} for optional and mandatory arguments",'heading') if $is_t_switch_active; + + # blank line token + my $blankLineToken = $tokens{blanklines}; + + # the command object allows () + my $objectDependentOptAndMandRegExp = (defined ${$self}{optAndMandArgsRegExp} ? ${$self}{optAndMandArgsRegExp} : $optAndMandRegExpWithLineBreaks); + + if(${$self}{body} =~ m/^$objectDependentOptAndMandRegExp\h*($trailingCommentRegExp)?/){ + $self->logger("Optional/Mandatory arguments found in ${$self}{name}: $1",'heading') if $is_t_switch_active; + + # create a new Arguments object + # The arguments object is a little different to most + # other objects, as it is created purely for its children, + # so some of the properties common to other objects, such + # as environment, ifelsefi, etc do not exist for Arguments; + # they will, however, exist for its children: OptionalArgument, MandatoryArgument + my $arguments = LatexIndent::Arguments->new(begin=>"", + name=>${$self}{name}.":arguments", + parent=>${$self}{name}, + body=>$1, + linebreaksAtEnd=>{ + end=>$2?1:0, + }, + end=>"", + regexp=>$objectDependentOptAndMandRegExp, + endImmediatelyFollowedByComment=>$2?0:($3?1:0), + ); + + # give unique id + $arguments->create_unique_id; + + # determine which comes first, optional or mandatory + if(${$arguments}{body} =~ m/.*?((?logger("Searching for optional arguments, and then mandatory (optional found first)") if $is_t_switch_active; + # look for optional arguments + $arguments->find_optional_arguments; + + # look for mandatory arguments + $arguments->find_mandatory_arguments; + } else { + $self->logger("Searching for mandatory arguments, and then optional (mandatory found first)") if $is_t_switch_active; + # look for mandatory arguments + $arguments->find_mandatory_arguments; + + # look for optional arguments + $arguments->find_optional_arguments; + } + + } else { + $self->logger("Searching for round brackets ONLY") if $is_t_switch_active; + # look for round brackets + $arguments->find_round_brackets; + } + + # examine *first* child + # situation: parent BodyStartsOnOwnLine >= 1, but first child has BeginStartsOnOwnLine == 0 || BeginStartsOnOwnLine == undef + # problem: the *body* of parent actually starts after the arguments + # solution: remove the linebreak at the end of the begin statement of the parent + if(defined ${$self}{BodyStartsOnOwnLine} and ${$self}{BodyStartsOnOwnLine}>=1){ + if( !(defined ${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine} and ${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine}>=1) + and ${$self}{body} !~ m/^$blankLineToken/){ + my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; + my $BeginStringLogFile = ${${${$arguments}{children}}[0]}{aliases}{BeginStartsOnOwnLine}||"BeginStartsOnOwnLine"; + $self->logger("$BodyStringLogFile = 1 (in ${$self}{name}), but first argument should not begin on its own line (see $BeginStringLogFile)") if $is_t_switch_active; + $self->logger("Removing line breaks at the end of ${$self}{begin}") if $is_t_switch_active; + ${$self}{begin} =~ s/\R*$//s; + ${$self}{linebreaksAtEnd}{begin} = 0; + } + } + + # situation: preserveBlankLines is active, so the body may well begin with a blank line token + # which means that ${$self}{linebreaksAtEnd}{begin} *should be* 1 + if(${${${$arguments}{children}}[0]}{body} =~ m/^($blankLineToken)/){ + $self->logger("Updating {linebreaksAtEnd}{begin} for ${$self}{name} as $blankLineToken or blank line found at beginning of argument child") if $is_t_switch_active; + ${$self}{linebreaksAtEnd}{begin} = 1 + } + + # examine *first* child + # situation: parent BodyStartsOnOwnLine == -1, but first child has BeginStartsOnOwnLine == 1 + # problem: the *body* of parent actually starts after the arguments + # solution: add a linebreak at the end of the begin statement of the parent so that + # the child settings are obeyed. + # BodyStartsOnOwnLine == 0 will actually be controlled by the last arguments' + # settings of EndFinishesWithLineBreak + if( ${$self}{linebreaksAtEnd}{begin} == 0 + and ((defined ${$self}{BodyStartsOnOwnLine} and ${$self}{BodyStartsOnOwnLine}==-1) + or !(defined ${$self}{BodyStartsOnOwnLine})) + ){ + if(defined ${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine} and ${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine}>=1){ + my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; + my $BeginStringLogFile = ${${${$arguments}{children}}[0]}{aliases}{BeginStartsOnOwnLine}||"BeginStartsOnOwnLine"; + my $BodyValue = (defined ${$self}{BodyStartsOnOwnLine}) ? ${$self}{BodyStartsOnOwnLine} : "0"; + $self->logger("$BodyStringLogFile = $BodyValue (in ${$self}{name}), but first argument *should* begin on its own line (see $BeginStringLogFile)") if $is_t_switch_active; + + # possibly add a comment at the end of the begin statement + my $trailingCommentToken = q(); + if(${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine}==1){ + $self->logger("Adding line breaks at the end of ${$self}{begin} (first argument, see $BeginStringLogFile == ${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine})") if $is_t_switch_active; + } elsif(${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine}==2){ + $self->logger("Adding a % at the end of begin, ${$self}{begin} followed by a linebreak ($BeginStringLogFile == 2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + $self->logger("Removing trailing space on ${$self}{begin}") if $is_t_switch_active; + ${$self}{begin} =~ s/\h*$//s; + } + + # modification + ${$self}{begin} .= "$trailingCommentToken\n"; + ${$self}{linebreaksAtEnd}{begin} = 1; + } + } + + # the replacement text can be just the ID, but the ID might have a line break at the end of it + ${$arguments}{replacementText} = ${$arguments}{id}; + + # children need to receive ancestor information, see test-cases/commands/commands-triple-nested.tex + foreach (@{${$arguments}{children}}){ + $self->logger("Updating argument children of ${$self}{name} to include ${$self}{id} in ancestors") if $is_t_switch_active; + push(@{${$_}{ancestors}},{ancestorID=>${$self}{id},ancestorIndentation=>${$self}{indentation},type=>"natural"}); + } + + # the argument object only needs a trailing line break if the *last* child + # did not add one at the end, and if BodyStartsOnOwnLine >= 1 + if( (defined ${${${$arguments}{children}}[-1]}{EndFinishesWithLineBreak} and ${${${$arguments}{children}}[-1]}{EndFinishesWithLineBreak}<1) + and (defined ${$self}{BodyStartsOnOwnLine} and ${$self}{BodyStartsOnOwnLine}>=1) ){ + $self->logger("Updating replacementtext to include a linebreak for arguments in ${$self}{name}") if $is_t_switch_active; + ${$arguments}{replacementText} .= "\n" if(${$arguments}{linebreaksAtEnd}{end}); + } + + # store children in special hash + push(@{${$self}{children}},$arguments); + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/${$arguments}{regexp}/${$arguments}{replacementText}/; + + # delete the regexp, as there's no need for it + delete ${${${$self}{children}}[-1]}{regexp}; + + $self->logger(Dumper(\%{$arguments}),'ttrace') if($is_tt_switch_active); + $self->logger("replaced with ID: ${$arguments}{id}") if $is_t_switch_active; + } else { + $self->logger("... no arguments found") if $is_t_switch_active; + } + +} + + +sub create_unique_id{ + my $self = shift; + + $ArgumentCounter++; + ${$self}{id} = "$tokens{arguments}$ArgumentCounter$tokens{endOfToken}"; + return; +} + +sub get_numbered_arg_regexp{ + + # for example #1 #2, etc + my $numberedArgRegExp = qr/(?:#\d\h*;?,?\/?)+/; + return $numberedArgRegExp; +} + +sub get_arguments_regexp{ + + my $self = shift; + my %input = @_; + + # blank line token + my $blankLineToken = $tokens{blanklines}; + + # some calls to this routine need to account for the linebreaks at the end, some do not + my $lineBreaksAtEnd = (defined ${input}{mode} and ${input}{mode} eq 'lineBreaksAtEnd')?'\R*':q(); + + # for example #1 #2, etc + my $numberedArgRegExp = $self->get_numbered_arg_regexp; + + # beamer special + my $beamerRegExp = qr/\<.*?\>/; + + # commands are allowed strings between arguments, e.g node, decoration, etc, specified in stringsAllowedBetweenArguments + my $stringsBetweenArguments = q(); + + if(defined ${input}{stringBetweenArguments} and ${input}{stringBetweenArguments}==1){ + # grab the strings allowed between arguments + my %stringsAllowedBetweenArguments = %{${$masterSettings{commandCodeBlocks}}{stringsAllowedBetweenArguments}}; + + while( my ($allowedStringName,$allowedStringValue)= each %stringsAllowedBetweenArguments){ + # change + and - to escaped characters + $allowedStringName =~ s/\+/\\+/g; + $allowedStringName =~ s/\-/\\-/g; + + # form the regexp + $stringsBetweenArguments .= ($stringsBetweenArguments eq '' ? q() : "|").$allowedStringName if $allowedStringValue; + } + + # report to log file + $self->logger("Strings allowed between arguments $stringsBetweenArguments (see stringsAllowedBetweenArguments)",'heading') if $is_t_switch_active; + } + + if(defined ${input}{roundBrackets} and ${input}{roundBrackets}==1){ + # arguments regexp + return qr/ + ( # capture into $1 + (?: + (?:\h|\R|$blankLineToken|$trailingCommentRegExp|$numberedArgRegExp|$beamerRegExp|_|\^|$stringsBetweenArguments)* + (?: + (?: + \h* # 0 or more spaces + (?logger("Backup procedure (-w flag active):",'heading'); + + my $fileName = ${$self}{fileName}; + + # grab the file extension preferences + my %fileExtensionPreference= %{$masterSettings{fileExtensionPreference}}; + + # sort the file extensions by preference + my @fileExtensions = sort { $fileExtensionPreference{$a} <=> $fileExtensionPreference{$b} } keys(%fileExtensionPreference); + + # backup file name is the base name + my $backupFile = basename(${$self}{fileName},@fileExtensions); + + # add the user's backup directory to the backup path + $backupFile = "${$self}{cruftDirectory}/$backupFile"; + + # local variables, determined from the YAML settings + my $onlyOneBackUp = $masterSettings{onlyOneBackUp}; + my $maxNumberOfBackUps = $masterSettings{maxNumberOfBackUps}; + my $cycleThroughBackUps= $masterSettings{cycleThroughBackUps}; + my $backupExtension= $masterSettings{backupExtension}; + + # 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) { + $self->logger("WARNING: onlyOneBackUp=$onlyOneBackUp and maxNumberOfBackUps: $maxNumberOfBackUps"); + $self->logger("setting onlyOneBackUp=0 which will allow you to reach $maxNumberOfBackUps back ups"); + $onlyOneBackUp = 0; + } + + # if the user has specified that $maxNumberOfBackUps = 1 then + # they only want one backup + if($maxNumberOfBackUps==1) { + $onlyOneBackUp=1 ; + $self->logger("FYI: you set maxNumberOfBackUps=1, so I'm setting onlyOneBackUp: 1 "); + } elsif($maxNumberOfBackUps<=0 and !$onlyOneBackUp) { + $onlyOneBackUp=0 ; + $maxNumberOfBackUps=-1; + } + + # if onlyOneBackUp is set, then the backup file will + # be overwritten each time + if($onlyOneBackUp) { + $backupFile .= $backupExtension; + $self->logger("copying $fileName to $backupFile"); + $self->logger("$backupFile was overwritten (see onlyOneBackUp)") 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) { + $self->logger("maxNumberOfBackUps reached ($maxNumberOfBackUps, see maxNumberOfBackUps)"); + + # some users may wish to cycle through back up files, e.g: + # copy myfile.bak1 to myfile.bak0 + # copy myfile.bak2 to myfile.bak1 + # copy myfile.bak3 to myfile.bak2 + # + # current back up is stored in myfile.bak4 + if($cycleThroughBackUps) { + $self->logger("cycleThroughBackUps detected (see cycleThroughBackUps) "); + for(my $i=1;$i<=$maxNumberOfBackUps;$i++) { + # remove number from backUpFile + my $oldBackupFile = $backupFile; + $oldBackupFile =~ s/$backupExtension.*/$backupExtension/; + my $newBackupFile = $oldBackupFile; + + # add numbers back on + $oldBackupFile .= $i; + $newBackupFile .= $i-1; + + # check that the oldBackupFile exists + if(-e $oldBackupFile){ + $self->logger(" copying $oldBackupFile to $newBackupFile "); + copy($oldBackupFile,$newBackupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting."; + } + } + } + + # rest maxNumberOfBackUps + $maxNumberOfBackUps=1 ; + last; # break out of the loop + } elsif(!(-e $backupFile)) { + $maxNumberOfBackUps=1; + last; # break out of the loop + } + $self->logger(" $backupFile already exists, incrementing by 1... (see maxNumberOfBackUps and onlyOneBackUp)"); + $backupCounter++; + $backupFile =~ s/$backupExtension.*/$backupExtension$backupCounter/; + } + $self->logger("copying $fileName to $backupFile"); + } + + # output these lines to the log file + $self->logger("Backup file: ",$backupFile,""); + $self->logger("Overwriting file: ",$fileName,""); + copy($fileName,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting."; +} +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm new file mode 100644 index 00000000000..f4572dd6797 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm @@ -0,0 +1,108 @@ +package LatexIndent::BlankLines; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @EXPORT_OK = qw/protect_blank_lines unprotect_blank_lines condense_blank_lines/; + +sub protect_blank_lines{ + return unless $is_m_switch_active; + my $self = shift; + + unless(${$masterSettings{modifyLineBreaks}}{preserveBlankLines}){ + $self->logger("Blank lines will not be protected (preserveBlankLines=0)",'heading') if $is_t_switch_active; + return + } + + $self->logger("Protecting blank lines (see preserveBlankLines)",'heading') if $is_t_switch_active; + ${$self}{body} =~ s/^(\h*)?\R/$tokens{blanklines}\n/mg; + return; +} + +sub condense_blank_lines{ + return unless $is_m_switch_active; + + return unless ${$masterSettings{modifyLineBreaks}}{condenseMultipleBlankLinesInto}>0; + + my $self = shift; + + # if preserveBlankLines is set to 0, then the blank-line-token will not be present + # in the document -- we change that here + if(${$masterSettings{modifyLineBreaks}}{preserveBlankLines}==0){ + # turn the switch on + ${$masterSettings{modifyLineBreaks}}{preserveBlankLines}=1; + + # log file information + $self->logger("Updating body to inclued blank line token, this requires preserveBlankLines = 1",'ttrace') if($is_tt_switch_active); + $self->logger("(any blanklines that could have been removed, would have done so by this point)",'ttrace') if($is_tt_switch_active); + + # make the call + $self->protect_blank_lines ; + $self->logger("body now looks like:\n${$self}{body}",'ttrace') if($is_tt_switch_active); + } + + # grab the value from the settings + my $condenseMultipleBlankLinesInto = ${$masterSettings{modifyLineBreaks}}{condenseMultipleBlankLinesInto}; + + # grab the blank-line-token + my $blankLineToken = $tokens{blanklines}; + + # condense! + $self->logger("Condensing multiple blank lines into $condenseMultipleBlankLinesInto (see condenseMultipleBlankLinesInto)",'heading') if $is_t_switch_active; + my $replacementToken = $blankLineToken; + for (my $i=1; $i<$condenseMultipleBlankLinesInto; $i++ ){ + $replacementToken .= "\n$blankLineToken"; + } + + $self->logger("blank line replacement token: $replacementToken",'ttrace') if($is_tt_switch_active); + ${$self}{body} =~ s/($blankLineToken\h*\R*\h*){1,}$blankLineToken/$replacementToken/mgs; + $self->logger("body now looks like:\n${$self}{body}",'ttrace') if($is_tt_switch_active); + return; +} + +sub unprotect_blank_lines{ + return unless $is_m_switch_active; + + return unless ${$masterSettings{modifyLineBreaks}}{preserveBlankLines}; + my $self = shift; + + $self->logger("Unprotecting blank lines (see preserveBlankLines)",'heading') if $is_t_switch_active; + my $blankLineToken = $tokens{blanklines}; + + # loop through the body, looking for the blank line token + while(${$self}{body} =~ m/$blankLineToken/m){ + # when the blank line token occupies the whole line + if(${$self}{body} =~ m/^\h*$blankLineToken$/m){ + $self->logger("Replacing purely blank lines",'heading') if $is_tt_switch_active; + ${$self}{body} =~ s/^\h*$blankLineToken$//mg; + $self->logger("body now looks like:\n${$self}{body}",'ttrace') if($is_tt_switch_active); + } + # otherwise the blank line has been deleted, so we compensate with an extra + if(${$self}{body} =~ m/(^\h*)?$blankLineToken/m){ + $self->logger("Replacing blank line token that doesn't take up whole line",'heading') if $is_tt_switch_active; + ${$self}{body} =~ s/(^\h*)?$blankLineToken/$1?"\n".$1:"\n"/me; + $self->logger("body now looks like:\n${$self}{body}",'ttrace') if($is_tt_switch_active); + } + } + $self->logger("Finished unprotecting lines (see preserveBlankLines)",'heading') if $is_t_switch_active; + $self->logger("body now looks like ${$self}{body}",'ttrace') if($is_tt_switch_active); +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Braces.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Braces.pm new file mode 100644 index 00000000000..c5122fd1275 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Braces.pm @@ -0,0 +1,188 @@ +package LatexIndent::Braces; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Command qw/$commandRegExp $commandRegExpTrailingComment $optAndMandAndRoundBracketsRegExpLineBreaks/; +use LatexIndent::KeyEqualsValuesBraces qw/$key_equals_values_bracesRegExp $key_equals_values_bracesRegExpTrailingComment/; +use LatexIndent::NamedGroupingBracesBrackets qw/$grouping_braces_regexp $grouping_braces_regexpTrailingComment/; +use LatexIndent::UnNamedGroupingBracesBrackets qw/$un_named_grouping_braces_RegExp $un_named_grouping_braces_RegExp_trailing_comment/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_commands_or_key_equals_values_braces/; +our $commandCounter; + +sub find_commands_or_key_equals_values_braces{ + + my $self = shift; + + $self->logger("Searching for commands with optional and/or mandatory arguments AND key = {value}",'heading') if $is_t_switch_active ; + + # match either a \\command or key={value} + while( ${$self}{body} =~ m/$commandRegExpTrailingComment/ + or + ${$self}{body} =~ m/$key_equals_values_bracesRegExpTrailingComment/ + or + ${$self}{body} =~ m/$grouping_braces_regexpTrailingComment/ + or + ${$self}{body} =~ m/$un_named_grouping_braces_RegExp_trailing_comment/ + ){ + if(${$self}{body} =~ m/$commandRegExpTrailingComment/){ + + # global substitution + ${$self}{body} =~ s/ + $commandRegExpTrailingComment + / + # log file output + $self->logger("command found: $2",'heading') if $is_t_switch_active ; + + # create a new command object + my $command = LatexIndent::Command->new(begin=>$1.$2.($3?$3:q()).($4?$4:q()), + name=>$2, + body=>$5.($8?$8:($10?$10:q())), # $8 is linebreak, $10 is trailing comment + end=>q(), + linebreaksAtEnd=>{ + begin=>$4?1:0, + end=>$8?1:0, # $8 is linebreak before comment check, $10 is after + }, + modifyLineBreaksYamlName=>"commands", + endImmediatelyFollowedByComment=>$8?0:($10?1:0), + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"CommandStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"CommandNameFinishesWithLineBreak", + }, + optAndMandArgsRegExp=>$optAndMandAndRoundBracketsRegExpLineBreaks, + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($command); + ${@{${$self}{children}}[-1]}{replacementText}.($8?($10?$10:q()):q()); + /xseg; + + } elsif (${$self}{body} =~ m/$key_equals_values_bracesRegExpTrailingComment/){ + + # global substitution + ${$self}{body} =~ s/ + $key_equals_values_bracesRegExpTrailingComment + / + # log file output + $self->logger("key_equals_values_braces found: $3",'heading') if $is_t_switch_active ; + + # create a new key_equals_values_braces object + my $key_equals_values_braces = LatexIndent::KeyEqualsValuesBraces->new( + begin=>($2?$2:q()).$3.$4.($5?$5:q()), + name=>$3, + body=>$6.($9?$9:($10?$10:q()).($11?$11:q())), # $9 is linebreak before comment check, $11 is trailing comment + end=>q(), + linebreaksAtEnd=>{ + begin=>$5?1:0, + end=>$9?1:0, # $9 is linebreak before comment check + }, + modifyLineBreaksYamlName=>"keyEqualsValuesBracesBrackets", + beginningbit=>$1, + endImmediatelyFollowedByComment=>$9?0:($11?1:0), + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"KeyStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"EqualsFinishesWithLineBreak", + }, + additionalAssignments=>["EqualsStartsOnOwnLine"], + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($key_equals_values_braces); + ${@{${$self}{children}}[-1]}{replacementText}.($9?($11?$11:q()):q()); + /xseg; + + } elsif (${$self}{body} =~ m/$grouping_braces_regexpTrailingComment/){ + + # global substitution + ${$self}{body} =~ s/ + $grouping_braces_regexpTrailingComment + / + # log file output + $self->logger("named grouping braces found: $2",'heading') if $is_t_switch_active ; + + # create a new key_equals_values_braces object + my $grouping_braces = LatexIndent::NamedGroupingBracesBrackets->new( + begin=>$2.($3?$3:q()).($4?$4:q()), + name=>$2, + body=>$5.($8?$8:($9?$9:q())), + end=>q(), + linebreaksAtEnd=>{ + begin=>$4?1:0, + end=>$8?1:0, + }, + modifyLineBreaksYamlName=>"namedGroupingBracesBrackets", + beginningbit=>$1, + endImmediatelyFollowedByComment=>$8?0:($9?1:0), + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"NameStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"NameFinishesWithLineBreak", + }, + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($grouping_braces); + ${@{${$self}{children}}[-1]}{replacementText}.($8?($9?$9:q()):q()); + /xseg; + + } elsif (${$self}{body} =~ m/$un_named_grouping_braces_RegExp_trailing_comment/) { + # global substitution + ${$self}{body} =~ s/ + $un_named_grouping_braces_RegExp_trailing_comment + / + # log file output + $self->logger("UNnamed grouping braces found: (no name, by definition!)",'heading') if $is_t_switch_active ; + + # create a new Un-named-grouping-braces-brackets object + my $un_named_grouping_braces = LatexIndent::UnNamedGroupingBracesBrackets->new( + begin=>q(), + name=>"always-un-named", + body=>$3.($6?$6:($8?$8:q())), + end=>q(), + linebreaksAtEnd=>{ + begin=>$2?1:0, + end=>$6?1:0, + }, + modifyLineBreaksYamlName=>"UnNamedGroupingBracesBrackets", + beginningbit=>$1.($2?$2:q()), + endImmediatelyFollowedByComment=>$6?0:($8?1:0), + # begin statements + BeginStartsOnOwnLine=>0, + # body statements + BodyStartsOnOwnLine=>0, + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($un_named_grouping_braces); + ${@{${$self}{children}}[-1]}{replacementText}.($6?($8?$8:q()):q()); + /xseg; + + } + } + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm new file mode 100755 index 00000000000..022064fd1d7 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm @@ -0,0 +1,178 @@ +package LatexIndent::Command; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/construct_command_regexp $commandRegExp $commandRegExpTrailingComment $optAndMandAndRoundBracketsRegExpLineBreaks/; +our $commandCounter; +our $commandRegExp; +our $commandRegExpTrailingComment; +our $optAndMandAndRoundBracketsRegExp; +our $optAndMandAndRoundBracketsRegExpLineBreaks; + +# store the regular expresssion for matching and replacing +sub construct_command_regexp{ + my $self = shift; + + $optAndMandAndRoundBracketsRegExp = $self->get_arguments_regexp( + roundBrackets=>${$masterSettings{commandCodeBlocks}}{roundParenthesesAllowed}, + stringBetweenArguments=>1); + + $optAndMandAndRoundBracketsRegExpLineBreaks = $self->get_arguments_regexp( + roundBrackets=>${$masterSettings{commandCodeBlocks}}{roundParenthesesAllowed}, + mode=>"lineBreaksAtEnd", + stringBetweenArguments=>1); + + # construct the command regexp + $commandRegExp = qr/ + (\\|@) + ( + [+a-zA-Z@\*0-9_\:]+? # lowercase|uppercase letters, @, *, numbers + ) + (\h*) + (\R*)? + ($optAndMandAndRoundBracketsRegExp) + (\R)? + /sx; + + # command regexp with trailing comment + $commandRegExpTrailingComment = qr/$commandRegExp(\h*)((?:$trailingCommentRegExp\h*)*)/; + +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # check for adding/removing linebreaks before = + $self->check_linebreaks_before_equals; + + # search for arguments + $self->find_opt_mand_arguments; + + # situation: ${${$self}{linebreaksAtEnd}}{end} == 1, and the argument container object + # still contains a linebreak at the end; in this case, we need to remove the linebreak from + # the container object + if(${${$self}{linebreaksAtEnd}}{end} == 1 + and ${${${$self}{children}}[0]}{body} =~ m/\R$/s + and !${$self}{endImmediatelyFollowedByComment}){ + $self->logger("Removing linebreak from argument container of ${$self}{name}") if $is_t_switch_active; + ${${${$self}{children}}[0]}{body} =~ s/\R$//s; + ${${${${$self}{children}}[0]}{linebreaksAtEnd}}{body} = 0; + } + + # situation: ${${$self}{linebreaksAtEnd}}{end} == 1 and the last argument specifies + # EndFinishesWithLineBreaks = 0 (see test-cases/commands/just-one-command-mod10.tex) + if(${${$self}{linebreaksAtEnd}}{end} == 1 + and defined ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} + and ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} == -1 + ){ + $self->logger("Switching linebreaksAtEnd{end} to be 0 in command ${$self}{name} as last argument specifies EndFinishesWithLineBreak == 0") if $is_t_switch_active; + ${${$self}{linebreaksAtEnd}}{end} = 0; + ${$self}{EndFinishesWithLineBreak} = -1; + } + + # if the last argument finishes with a linebreak, it won't get interpreted at + # the right time (see test-cases/commands/commands-one-line-nested-simple-mod1.tex for example) + # so this little bit fixes it + if(${${${${${$self}{children}}[0]}{children}[-1]}{linebreaksAtEnd}}{end} and ${${$self}{linebreaksAtEnd}}{end} == 0 + and defined ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} + and ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} >= 1 + and !${$self}{endImmediatelyFollowedByComment}){ + + # update the Command object + $self->logger("Adjusting linebreaksAtEnd in command ${$self}{name}") if $is_t_switch_active; + ${${$self}{linebreaksAtEnd}}{end} = ${${${${${$self}{children}}[0]}{children}[-1]}{linebreaksAtEnd}}{end}; + ${$self}{replacementText} .= "\n"; + + # update the argument object + $self->logger("Adjusting argument object in command, ${$self}{name}") if $is_t_switch_active; + ${${${${$self}{children}}[0]}{linebreaksAtEnd}}{body} = 0; + ${${${$self}{children}}[0]}{body} =~ s/\R$//s; + + # update the last mandatory/optional argument + $self->logger("Adjusting last argument in command, ${$self}{name}") if $is_t_switch_active; + ${${${${${$self}{children}}[0]}{children}[-1]}{linebreaksAtEnd}}{end} = 0; + ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} = -1; + ${${${${$self}{children}}[0]}{children}[-1]}{replacementText} =~ s/\R$//s; + + # output to log file + $self->logger(Dumper(${${${$self}{children}}[0]}{children}[-1])) if $is_t_switch_active; + } + + # situation: ${${$self}{linebreaksAtEnd}}{end} == 1 and the last argument has added + # a line break, which can result in a bogus blank line (see test-cases/commands/just-one-command.tex with mand-args-mod1.yaml) + if(${${$self}{linebreaksAtEnd}}{end} == 1 + and defined ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} + and ${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} >= 1 + and ${${${${$self}{children}}[0]}{children}[-1]}{replacementText}=~m/\R$/s + and !${$self}{endImmediatelyFollowedByComment}){ + + # last argument adjustment + $self->logger("Adjusting last argument in command, ${$self}{name} to avoid double line break") if $is_t_switch_active; + ${${${${$self}{children}}[0]}{children}[-1]}{replacementText}=~s/\R$//s; + ${${${${${$self}{children}}[0]}{children}[-1]}{linebreaksAtEnd}}{end} = 0; + + # argument object adjustment + $self->logger("Adjusting argument object in command, ${$self}{name} to avoid double line break") if $is_t_switch_active; + ${${${${$self}{children}}[0]}{linebreaksAtEnd}}{body} = 0; + ${${${$self}{children}}[0]}{body}=~s/\R$//s; + } + + # the arguments body might finish with horizontal space, in which case, we need to transfer this + # to the parent object replacement text. + # + # see ../test-cases/texexchange/5461.tex which was the first example to demonstrate the need for this + if(!${${${$self}{children}}[0]}{endImmediatelyFollowedByComment} and ${${${$self}{children}}[0]}{body} =~ m/\h*$/ and ${$self}{replacementText} !~ m/\R$/){ + $self->logger("${$self}{name}: trailling horizontal space found in arguments -- removing it from arguments, adding to replacement text") if $is_t_switch_active; + ${${${$self}{children}}[0]}{body} =~ s/(\h*)$//s; + ${$self}{replacementText} .= "$1"; + } + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for special begin/end + $self->find_special; + +} + +sub check_linebreaks_before_equals{ + # empty routine, which allows the above routine to function (this routine kicks in for KeyEqualsValuesBraces) + return; +} + +sub create_unique_id{ + my $self = shift; + + $commandCounter++; + ${$self}{id} = "$tokens{command}$commandCounter"; + return; +} + +sub align_at_ampersand{ + # need an empty routine here for commands; see + # test-cases/matrix1.tex for example + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm new file mode 100644 index 00000000000..7c951ec7995 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm @@ -0,0 +1,335 @@ +package LatexIndent::Document; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use Data::Dumper; + +# gain access to subroutines in the following modules +use LatexIndent::Switches qw/storeSwitches %switches $is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use LatexIndent::LogFile qw/logger output_logfile processSwitches/; +use LatexIndent::GetYamlSettings qw/readSettings modify_line_breaks_settings get_indentation_settings_for_this_object get_every_or_custom_value get_indentation_information get_object_attribute_for_indentation_settings alignment_at_ampersand_settings/; +use LatexIndent::FileExtension qw/file_extension_check/; +use LatexIndent::BackUpFileProcedure qw/create_back_up_file/; +use LatexIndent::BlankLines qw/protect_blank_lines unprotect_blank_lines condense_blank_lines/; +use LatexIndent::ModifyLineBreaks qw/modify_line_breaks_body modify_line_breaks_end remove_line_breaks_begin adjust_line_breaks_end_parent/; +use LatexIndent::TrailingComments qw/remove_trailing_comments put_trailing_comments_back_in add_comment_symbol construct_trailing_comment_regexp/; +use LatexIndent::HorizontalWhiteSpace qw/remove_trailing_whitespace remove_leading_space/; +use LatexIndent::Indent qw/indent wrap_up_statement determine_total_indentation indent_begin indent_body indent_end_statement final_indentation_check get_surrounding_indentation indent_children_recursively check_for_blank_lines_at_beginning put_blank_lines_back_in_at_beginning add_surrounding_indentation_to_begin_statement/; +use LatexIndent::Tokens qw/token_check %tokens/; +use LatexIndent::HiddenChildren qw/find_surrounding_indentation_for_children update_family_tree get_family_tree check_for_hidden_children/; +use LatexIndent::AlignmentAtAmpersand qw/align_at_ampersand find_aligned_block/; +use LatexIndent::DoubleBackSlash qw/dodge_double_backslash un_dodge_double_backslash/; + +# code blocks +use LatexIndent::Verbatim qw/put_verbatim_back_in find_verbatim_environments find_noindent_block find_verbatim_commands put_verbatim_commands_back_in/; +use LatexIndent::Environment qw/find_environments/; +use LatexIndent::IfElseFi qw/find_ifelsefi/; +use LatexIndent::Arguments qw/get_arguments_regexp find_opt_mand_arguments get_numbered_arg_regexp construct_arguments_regexp/; +use LatexIndent::OptionalArgument qw/find_optional_arguments/; +use LatexIndent::MandatoryArgument qw/find_mandatory_arguments get_mand_arg_reg_exp/; +use LatexIndent::RoundBrackets qw/find_round_brackets/; +use LatexIndent::Item qw/find_items construct_list_of_items/; +use LatexIndent::Braces qw/find_commands_or_key_equals_values_braces/; +use LatexIndent::Command qw/construct_command_regexp/; +use LatexIndent::KeyEqualsValuesBraces qw/construct_key_equals_values_regexp/; +use LatexIndent::NamedGroupingBracesBrackets qw/construct_grouping_braces_brackets_regexp/; +use LatexIndent::UnNamedGroupingBracesBrackets qw/construct_unnamed_grouping_braces_brackets_regexp/; +use LatexIndent::Special qw/find_special construct_special_begin/; +use LatexIndent::Heading qw/find_heading construct_headings_levels/; +use LatexIndent::FileContents qw/find_file_contents_environments_and_preamble/; +use LatexIndent::Preamble; + +sub new{ + # Create new objects, with optional key/value pairs + # passed as initializers. + # + # See Programming Perl, pg 319 + my $invocant = shift; + my $class = ref($invocant) || $invocant; + my $self = {@_}; + bless ($self,$class); + return $self; +} + +sub latexindent{ + my $self = shift; + $self->storeSwitches; + $self->processSwitches; + $self->readSettings; + $self->file_extension_check; + $self->operate_on_file; +} + +sub operate_on_file{ + my $self = shift; + + $self->create_back_up_file; + $self->token_check; + $self->construct_regular_expressions; + $self->find_noindent_block; + $self->find_verbatim_commands; + $self->find_aligned_block; + $self->remove_trailing_comments; + $self->find_verbatim_environments; + $self->protect_blank_lines; + $self->remove_trailing_whitespace(when=>"before"); + $self->find_file_contents_environments_and_preamble; + $self->dodge_double_backslash; + $self->remove_leading_space; + $self->process_body_of_text; + $self->remove_trailing_whitespace(when=>"after"); + $self->condense_blank_lines; + $self->unprotect_blank_lines; + $self->un_dodge_double_backslash; + $self->put_verbatim_back_in; + $self->put_trailing_comments_back_in; + $self->put_verbatim_commands_back_in; + $self->output_indented_text; + $self->output_logfile; + return +} + +sub construct_regular_expressions{ + my $self = shift; + $self->construct_trailing_comment_regexp; + $self->construct_list_of_items; + $self->construct_special_begin; + $self->construct_headings_levels; + $self->construct_arguments_regexp; + $self->construct_command_regexp; + $self->construct_key_equals_values_regexp; + $self->construct_grouping_braces_brackets_regexp; + $self->construct_unnamed_grouping_braces_brackets_regexp; + +} + +sub output_indented_text{ + my $self = shift; + + # output to screen, unless silent mode + print ${$self}{body} unless $switches{silentMode}; + + $self->logger("Output routine",'heading'); + + # if -overwrite is active then output to original fileName + if($switches{overwrite}) { + $self->logger("Overwriting file ${$self}{fileName}"); + open(OUTPUTFILE,">",${$self}{fileName}); + print OUTPUTFILE ${$self}{body}; + close(OUTPUTFILE); + } elsif($switches{outputToFile}) { + $self->logger("Outputting to file $switches{outputToFile}"); + open(OUTPUTFILE,">",$switches{outputToFile}); + print OUTPUTFILE ${$self}{body}; + close(OUTPUTFILE); + } else { + $self->logger("Not outputting to file; see -w and -o switches for more options."); + } + return; +} + +sub process_body_of_text{ + my $self = shift; + + # find objects recursively + $self->logger('Phase 1: searching for objects','heading'); + $self->find_objects; + + # find all hidden child + $self->logger('Phase 2: finding surrounding indentation','heading'); + $self->find_surrounding_indentation_for_children; + + # indentation recursively + $self->logger('Phase 3: indenting objects','heading'); + $self->indent_children_recursively; + + # final indentation check + $self->logger('Phase 4: final indentation check','heading'); + $self->final_indentation_check; + + return; +} + +sub find_objects{ + my $self = shift; + + # search for environments + $self->logger('looking for ENVIRONMENTS'); + $self->find_environments; + + # search for ifElseFi blocks + $self->logger('looking for IFELSEFI'); + $self->find_ifelsefi; + + # search for headings (part, chapter, section, setc) + $self->logger('looking for HEADINGS (chapter, section, part, etc)'); + $self->find_heading; + + # search for commands with arguments + $self->logger('looking for COMMANDS and key = {value}'); + $self->find_commands_or_key_equals_values_braces; + + # search for special begin/end + $self->logger('looking for SPECIAL begin/end'); + $self->find_special; + + # if there are no children, return + if(${$self}{children}){ + $self->logger("Objects have been found.",'heading'); + } else { + $self->logger("No objects found."); + return; + } + + # logfile information + $self->logger(Dumper(\%{$self}),'ttrace') if($is_tt_switch_active); + $self->logger("Operating on: ${$self}{name}",'heading'); + $self->logger("Number of children:",'heading'); + $self->logger(scalar (@{${$self}{children}})); + + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + $self->logger("There are no tasks particular to ${$self}{name}") if $is_t_switch_active; +} + +sub get_settings_and_store_new_object{ + my $self = shift; + + # grab the object to be operated upon + my ($latexIndentObject) = @_; + + # there are a number of tasks common to each object + $latexIndentObject->tasks_common_to_each_object(%{$self}); + + # tasks particular to each object + $latexIndentObject->tasks_particular_to_each_object; + + # store children in special hash + push(@{${$self}{children}},$latexIndentObject); + +} + +sub tasks_common_to_each_object{ + my $self = shift; + + # grab the parent information + my %parent = @_; + + # update/create the ancestor information + if($parent{ancestors}){ + $self->logger("Ancestors *have* been found for ${$self}{name}") if($is_t_switch_active); + push(@{${$self}{ancestors}},@{$parent{ancestors}}); + } else { + $self->logger("No ancestors found for ${$self}{name}") if($is_t_switch_active); + if(defined $parent{id} and $parent{id} ne ''){ + $self->logger("Creating ancestors with $parent{id} as the first one") if($is_t_switch_active); + push(@{${$self}{ancestors}},{ancestorID=>$parent{id},ancestorIndentation=>\$parent{indentation},type=>"natural",name=>${$self}{name}}); + } + } + + # natural ancestors + ${$self}{naturalAncestors} = q(); + if(${$self}{ancestors}){ + ${$self}{naturalAncestors} .= "---".${$_}{ancestorID}."\n" for @{${$self}{ancestors}}; + } + + # in what follows, $self can be an environment, ifElseFi, etc + + # count linebreaks in body + my $bodyLineBreaks = 0; + $bodyLineBreaks++ while(${$self}{body} =~ m/\R/sxg); + ${$self}{bodyLineBreaks} = $bodyLineBreaks; + + # get settings for this object + $self->get_indentation_settings_for_this_object; + + # give unique id + $self->create_unique_id; + + # add trailing text to the id to stop, e.g LATEX-INDENT-ENVIRONMENT1 matching LATEX-INDENT-ENVIRONMENT10 + ${$self}{id} .= $tokens{endOfToken}; + + # the replacement text can be just the ID, but the ID might have a line break at the end of it + $self->get_replacement_text; + + # the above regexp, when used below, will remove the trailing linebreak in ${$self}{linebreaksAtEnd}{end} + # so we compensate for it here + $self->adjust_replacement_text_line_breaks_at_end; + + # modify line breaks on body and end statements + $self->modify_line_breaks_body; + + # modify line breaks end statements + $self->modify_line_breaks_end; + + # check the body for current children + $self->check_for_hidden_children; + + return; +} + +sub get_replacement_text{ + my $self = shift; + + # the replacement text can be just the ID, but the ID might have a line break at the end of it + ${$self}{replacementText} = ${$self}{id}; + return; +} + +sub adjust_replacement_text_line_breaks_at_end{ + my $self = shift; + + # the above regexp, when used below, will remove the trailing linebreak in ${$self}{linebreaksAtEnd}{end} + # so we compensate for it here + $self->logger("Putting linebreak after replacementText for ${$self}{name}") if($is_t_switch_active); + if(defined ${$self}{horizontalTrailingSpace}){ + ${$self}{replacementText} .= ${$self}{horizontalTrailingSpace} unless(!${$self}{endImmediatelyFollowedByComment} and defined ${$self}{EndFinishesWithLineBreak} and ${$self}{EndFinishesWithLineBreak}==2); + } + ${$self}{replacementText} .= "\n" if(${$self}{linebreaksAtEnd}{end}); + +} + +sub count_body_line_breaks{ + my $self = shift; + + my $oldBodyLineBreaks = (defined ${$self}{bodyLineBreaks})? ${$self}{bodyLineBreaks} : 0; + + # count linebreaks in body + my $bodyLineBreaks = 0; + $bodyLineBreaks++ while(${$self}{body} =~ m/\R/sxg); + ${$self}{bodyLineBreaks} = $bodyLineBreaks; + $self->logger("bodyLineBreaks ${$self}{bodyLineBreaks}") if((${$self}{bodyLineBreaks} != $oldBodyLineBreaks) and $is_t_switch_active); +} + +sub wrap_up_tasks{ + my $self = shift; + + # most recent child object + my $child = @{${$self}{children}}[-1]; + + # check if the last object was the last thing in the body, and if it has adjusted linebreaks + $self->adjust_line_breaks_end_parent; + + $self->logger(Dumper(\%{$child})) if($is_tt_switch_active); + $self->logger("replaced with ID: ${$child}{id}") if $is_t_switch_active; + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/DoubleBackSlash.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/DoubleBackSlash.pm new file mode 100644 index 00000000000..8b8be3e25ec --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/DoubleBackSlash.pm @@ -0,0 +1,45 @@ +package LatexIndent::DoubleBackSlash; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use LatexIndent::Tokens qw/%tokens/; +use Exporter qw/import/; +our @EXPORT_OK = qw/dodge_double_backslash un_dodge_double_backslash/; + +# some code can contain, e.g +# cycle list={blue,mark=none\\}, +# see test-cases/texexchange/29293-christian-feuersanger.tex +# +# This is problematic, as the argument regexp won't count the right } because it has a +# backslash immediately infront of it! +sub dodge_double_backslash{ + my $self = shift; + + ${$self}{body} =~ s/(?:\\\\(\{|\}|\]))/$tokens{doubleBackSlash}$1/sg; + return; +} + +# this routine replaces the token with the \\\\ +sub un_dodge_double_backslash{ + my $self = shift; + + ${$self}{body} =~ s/$tokens{doubleBackSlash}/\\\\/sg; + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm new file mode 100755 index 00000000000..1b0ad27d550 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm @@ -0,0 +1,128 @@ +package LatexIndent::Environment; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_environments/; +our $environmentCounter; + +# store the regular expresssion for matching and replacing the \begin{}...\end{} statements +our $environmentRegExp = qr/ + ( + \\begin\{ + ( + [a-zA-Z@\*0-9_\\]+ # lowercase|uppercase letters, @, *, numbers + ) # environment name captured into $2 + \} # \begin{} statement + \h* # horizontal space + (\R*)? # possible line breaks (into $3) + ) # begin statement captured into $1 + ( + (?: # cluster-only (), don't capture + (?! # don't include \begin in the body + (?:\\begin) # cluster-only (), don't capture + ). # any character, but not \\begin + )*? # non-greedy + (\R*)? # possible line breaks (into $5) + ) # environment body captured into $4 + ( + \\end\{\2\} # \end{} statement + ) # captured into $6 + (\h*)? # possibly followed by horizontal space + (\R)? # possibly followed by a line break + /sx; + +sub find_environments{ + my $self = shift; + + + while( ${$self}{body} =~ m/$environmentRegExp\h*($trailingCommentRegExp)?/){ + + # global substitution + ${$self}{body} =~ s/ + $environmentRegExp(\h*)($trailingCommentRegExp)? + / + # log file output + $self->logger("environment found: $2",'heading') if $is_t_switch_active; + + # create a new Environment object + my $env = LatexIndent::Environment->new(begin=>$1, + name=>$2, + body=>$4, + end=>$6, + linebreaksAtEnd=>{ + begin=>$3?1:0, + body=>$5?1:0, + end=>$8?1:0, + }, + modifyLineBreaksYamlName=>"environments", + endImmediatelyFollowedByComment=>$8?0:($10?1:0), + horizontalTrailingSpace=>$7?$7:q(), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($env); + ${@{${$self}{children}}[-1]}{replacementText}.($9?$9:q()).($10?$10:q()); + /xseg; + $self->adjust_line_breaks_end_parent; + } + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # if the environment is empty, we may need to update linebreaksAtEnd{body} + if(${$self}{body} =~ m/^\h*$/s and ${${$self}{linebreaksAtEnd}}{begin}){ + $self->logger("empty environment body (${$self}{name}), updating linebreaksAtEnd{body} to be 1") if($is_t_switch_active); + ${${$self}{linebreaksAtEnd}}{body} = 1; + } + + # search for items as the first order of business + $self->find_items; + + # search for headings (important to do this before looking for commands!) + $self->find_heading; + + # search for commands, keys, named grouping braces + $self->find_commands_or_key_equals_values_braces; + + # search for arguments + $self->find_opt_mand_arguments; + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for special begin/end + $self->find_special; +} + +sub create_unique_id{ + my $self = shift; + + $environmentCounter++; + ${$self}{id} = "$tokens{environment}$environmentCounter"; + return; +} + + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm new file mode 100644 index 00000000000..dc8aa53f206 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm @@ -0,0 +1,230 @@ +package LatexIndent::FileContents; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @EXPORT_OK = qw/find_file_contents_environments_and_preamble/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our $fileContentsCounter; + +sub find_file_contents_environments_and_preamble{ + my $self = shift; + + # store the file contents blocks in an array which, depending on the value + # of indentPreamble, will be put into the verbatim hash, or otherwise + # stored as children to be operated upon + my @fileContentsStorageArray; + + # fileContents environments + $self->logger('looking for FILE CONTENTS environments (see fileContentsEnvironments)','heading'); + $self->logger(Dumper(\%{$masterSettings{fileContentsEnvironments}})) if($is_t_switch_active); + while( my ($fileContentsEnv,$yesno)= each %{$masterSettings{fileContentsEnvironments}}){ + if($yesno){ + $self->logger("looking for $fileContentsEnv:$yesno environments"); + + # the trailing * needs some care + if($fileContentsEnv =~ m/\*$/){ + $fileContentsEnv =~ s/\*$//; + $fileContentsEnv .= '\*'; + } + + my $fileContentsRegExp = qr/ + ( + \\begin\{ + $fileContentsEnv + \} + ) + ( + .*? + ) + ( + \\end\{$fileContentsEnv\} + \h* + ) + (\R)? + /sx; + + while( ${$self}{body} =~ m/$fileContentsRegExp/sx){ + + # create a new Environment object + my $fileContentsBlock = LatexIndent::FileContents->new( begin=>$1, + body=>$2, + end=>$3, + name=>$fileContentsEnv, + linebreaksAtEnd=>{ + begin=>0, + body=>0, + end=>$4?1:0, + }, + modifyLineBreaksYamlName=>"filecontents", + ); + # give unique id + $fileContentsBlock->create_unique_id; + + # the replacement text can be just the ID, but the ID might have a line break at the end of it + $fileContentsBlock->get_replacement_text; + + # count body line breaks + $fileContentsBlock->count_body_line_breaks; + + # the above regexp, when used below, will remove the trailing linebreak in ${$self}{linebreaksAtEnd}{end} + # so we compensate for it here + $fileContentsBlock->adjust_replacement_text_line_breaks_at_end; + + # store the fileContentsBlock, and determine location afterwards + push(@fileContentsStorageArray,$fileContentsBlock); + + # log file output + $self->logger("FILECONTENTS environment found: $fileContentsEnv"); + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/$fileContentsRegExp/${$fileContentsBlock}{replacementText}/sx; + + $self->logger("replaced with ID: ${$fileContentsBlock}{id}"); + } + } else { + $self->logger("*not* looking for $fileContentsEnv as $fileContentsEnv:$yesno"); + } + } + + # determine if body of document contains \begin{document} -- if it does, then assume + # that the body has a preamble + my $preambleRegExp = qr/ + (.*?) + (\R*)? # linebreaks at end of body into $2 + \\begin\{document\} + /sx; + my $preamble = q(); + + my $needToStorePreamble = 0; + + # try and find the preamble + if( ${$self}{body} =~ m/$preambleRegExp/sx and ${$masterSettings{lookForPreamble}}{${$self}{fileExtension}}){ + + $self->logger("\\begin{document} found in body (after searching for filecontents)-- assuming that a preamble exists"); + + # create a preamble object + $preamble = LatexIndent::Preamble->new( begin=>q(), + body=>$1, + end=>q(), + name=>"preamble", + linebreaksAtEnd=>{ + begin=>0, + body=>$2?1:0, + end=>0, + }, + afterbit=>($2?$2:q())."\\begin{document}", + modifyLineBreaksYamlName=>"preamble", + ); + + # give unique id + $preamble->create_unique_id; + + # get the replacement_text + $preamble->get_replacement_text; + + # log file output + $self->logger("preamble found: $preamble"); + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/$preambleRegExp/${$preamble}{replacementText}/sx; + + $self->logger("replaced with ID: ${$preamble}{replacementText}"); + # indentPreamble set to 1 + if($masterSettings{indentPreamble}){ + $self->logger("storing ${$preamble}{id} for indentation (see indentPreamble)"); + $needToStorePreamble = 1; + } else { + # indentPreamble set to 0 + $self->logger("NOT storing ${$preamble}{id} for indentation -- will store as VERBATIM object (see indentPreamble)"); + $preamble->unprotect_blank_lines; + ${$self}{verbatim}{${$preamble}{id}} = $preamble; + } + } + + # loop through the fileContents array, check if it's in the preamble + foreach(@fileContentsStorageArray){ + my $indentThisChild = 0; + # verbatim children go in special hash + if($preamble ne '' and ${$preamble}{body} =~ m/${$_}{id}/){ + $self->logger("filecontents (${$_}{id}) is within preamble"); + # indentPreamble set to 1 + if($masterSettings{indentPreamble}){ + $self->logger("storing ${$_}{id} for indentation (indentPreamble is 1)"); + $indentThisChild = 1; + } else { + # indentPreamble set to 0 + $self->logger("Storing ${$_}{id} as a VERBATIM object (indentPreamble is 0)"); + ${$self}{verbatim}{${$_}{id}}=$_; + } + } else { + $self->logger("storing ${$_}{id} for indentation (${$_}{name} found outside of preamble)"); + $indentThisChild = 1; + } + # store the child, if necessary + if($indentThisChild){ + $_->remove_leading_space; + $_->get_indentation_settings_for_this_object; + $_->tasks_particular_to_each_object; + push(@{${$self}{children}},$_); + } + } + + if($needToStorePreamble){ + $preamble->dodge_double_backslash; + $preamble->remove_leading_space; + $preamble->find_commands_or_key_equals_values_braces if($masterSettings{preambleCommandsBeforeEnvironments}); + $preamble->tasks_particular_to_each_object; + push(@{${$self}{children}},$preamble); + } + return; +} + +sub create_unique_id{ + my $self = shift; + + $fileContentsCounter++; + ${$self}{id} = "$tokens{filecontents}$fileContentsCounter$tokens{endOfToken}"; + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # search for environments + $self->find_environments; + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for headings (part, chapter, section, setc) + $self->find_heading; + + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces; + + # search for special begin/end + $self->find_special; + + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/FileExtension.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileExtension.pm new file mode 100644 index 00000000000..8dcb66dd80c --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileExtension.pm @@ -0,0 +1,99 @@ +package LatexIndent::FileExtension; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use File::Basename; # to get the filename and directory path +use Exporter qw/import/; +our @EXPORT_OK = qw/file_extension_check/; + +sub file_extension_check{ + my $self = shift; + + # grab the filename + my $fileName = ${$self}{fileName}; + + # grab the file extension preferences + my %fileExtensionPreference= %{$masterSettings{fileExtensionPreference}}; + + # 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); + + # check to make sure given file type is supported + if( -e $fileName and !$ext ){ + my $message = "The file $fileName exists , but the extension does not correspond to any given in fileExtensionPreference; consinder updating fileExtensionPreference."; + $self->logger($message,'heading'); + $self->output_logfile; + die($message); + } + + # if no extension, search according to fileExtensionPreference + if (!$ext) { + $self->logger("File extension work:",'heading'); + $self->logger("latexindent called to act upon $fileName with an, as yet, unrecognised file extension;"); + $self->logger("searching for file with an extension in the following order (see fileExtensionPreference):"); + $self->logger(join("\n",@fileExtensions)); + + my $fileFound = 0; + # loop through the known file extensions (see @fileExtensions) + foreach (@fileExtensions ){ + if ( -e $fileName.$_ ) { + $self->logger("$fileName$_ found!"); + $fileName .= $_; + $self->logger("Updated fileName to $fileName"); + ${$self}{fileName} = $fileName ; + $fileFound = 1; + $ext = $_; + last; + } + } + unless($fileFound){ + $self->logger("I couldn't find a match for $fileName in fileExtensionPreference (see defaultSettings.yaml)"); + foreach (@fileExtensions ){ + $self->logger("I searched for $fileName$_"); + } + $self->logger("but couldn't find any of them."); + $self->logger("Consider updating fileExtensionPreference. Error: Exiting, no indendation done."); + $self->output_logfile; + die "I couldn't find a match for $fileName in fileExtensionPreference.\nExiting, no indendation done."; + } + } else { + # if the file has a recognised extension, check that the file exists + unless( -e $fileName ){ + my $message = "Error: I couldn't find $fileName, are you sure it exists?. No indentation done. Exiting."; + $self->logger($message); + $self->output_logfile; + die $message; + } + } + + # store the file extension + ${$self}{fileExtension} = $ext; + + # read the file into the Document body + my @lines; + open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; + push(@lines,$_) while(); + close(MAINFILE); + + # the all-important step: update the body + ${$self}{body} = join("",@lines); +} +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm new file mode 100644 index 00000000000..4c93bc80426 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm @@ -0,0 +1,471 @@ +package LatexIndent::GetYamlSettings; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use strict; +use warnings; +use LatexIndent::Switches qw/%switches $is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use YAML::Tiny; # interpret defaultSettings.yaml and other potential settings files +use File::Basename; # to get the filename and directory path +use File::HomeDir; +use Exporter qw/import/; +our @EXPORT_OK = qw/readSettings modify_line_breaks_settings get_indentation_settings_for_this_object get_every_or_custom_value get_indentation_information get_object_attribute_for_indentation_settings alignment_at_ampersand_settings %masterSettings/; + +# Read in defaultSettings.YAML file +our $defaultSettings; + +# master yaml settings is a hash, global to this module +our %masterSettings; + +# previously found settings is a hash, global to this module +our %previouslyFoundSettings; + +sub readSettings{ + my $self = shift; + + $defaultSettings = YAML::Tiny->new; + $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" ); + $self->logger("YAML settings read",'heading'); + $self->logger("Reading defaultSettings.yaml from $FindBin::RealBin/defaultSettings.yaml"); + + # if latexindent.exe is invoked from TeXLive, then defaultSettings.yaml won't be in + # the same directory as it; we need to navigate to it + if(!$defaultSettings) { + $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml"); + $self->logger("Reading defaultSettings.yaml (2nd attempt, TeXLive, Windows) from $FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml"); + } + + # need to exit if we can't get defaultSettings.yaml + die "Could not open defaultSettings.yaml" if(!$defaultSettings); + + # master yaml settings is a hash, global to this module + our %masterSettings = %{$defaultSettings->[0]}; + + # scalar to read user settings + my $userSettings; + + # array to store the paths to user settings + my @absPaths; + + # we'll need the home directory a lot in what follows + my $homeDir = File::HomeDir->my_home; + + # get information about user settings- first check if indentconfig.yaml exists + my $indentconfig = "$homeDir/indentconfig.yaml"; + + # if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml + $indentconfig = "$homeDir/.indentconfig.yaml" if(! -e $indentconfig); + + # messages for indentconfig.yaml and/or .indentconfig.yaml + if ( -e $indentconfig and !$switches{onlyDefault}) { + $self->logger("Reading path information from $indentconfig"); + # if both indentconfig.yaml and .indentconfig.yaml exist + if ( -e File::HomeDir->my_home . "/indentconfig.yaml" and -e File::HomeDir->my_home . "/.indentconfig.yaml") { + $self->logger("$homeDir/.indentconfig.yaml has been found, but $indentconfig takes priority"); + } elsif ( -e File::HomeDir->my_home . "/indentconfig.yaml" ) { + $self->logger("(Alternatively $homeDir/.indentconfig.yaml can be used)"); + } elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) { + $self->logger("(Alternatively $homeDir/indentconfig.yaml can be used)"); + } + + # read the absolute paths from indentconfig.yaml + $userSettings = YAML::Tiny->read( "$indentconfig" ); + + # output the contents of indentconfig to the log file + $self->logger(Dump \%{$userSettings->[0]}); + + # update the absolute paths + @absPaths = @{$userSettings->[0]->{paths}}; + } else { + if($switches{onlyDefault}) { + $self->logger("Only default settings requested, not reading USER settings from $indentconfig"); + $self->logger("Ignoring $switches{readLocalSettings} (you used the -d switch)") if($switches{readLocalSettings}); + $switches{readLocalSettings}=0; + } else { + # give the user instructions on where to put indentconfig.yaml or .indentconfig.yaml + $self->logger("Home directory is $homeDir (didn't find either indentconfig.yaml or .indentconfig.yaml)"); + $self->logger("To specify user settings you would put indentconfig.yaml here: $homeDir/indentconfig.yaml"); + $self->logger("Alternatively, you can use the hidden file .indentconfig.yaml as: $homeDir/.indentconfig.yaml"); + } + } + + # get information about LOCAL settings, assuming that $readLocalSettings exists + my $directoryName = dirname (${$self}{fileName}); + + # local settings can be separated by , + # e.g + # -l = myyaml1.yaml,myyaml2.yaml + # and in which case, we need to read them all + my @localSettings; + if($switches{readLocalSettings} =~ m/,/){ + $self->logger("Multiple localSettings found, separated by commas:",'heading'); + @localSettings = split(/,/,$switches{readLocalSettings}); + } else { + push(@localSettings,$switches{readLocalSettings}) if($switches{readLocalSettings}); + } + + # add local settings to the paths, if appropriate + foreach (@localSettings) { + if ( (-e "$directoryName/$_") and !(-z "$directoryName/$_")) { + $self->logger("Adding $directoryName/$_ to YAML read paths"); + push(@absPaths,"$directoryName/$_"); + } elsif ( !(-e "$directoryName/$_") ) { + $self->logger("WARNING yaml file not found: $directoryName/$_ not found"); + $self->logger("Proceeding without it."); + } + } + + # read in the settings from each file + foreach my $settings (@absPaths) { + # check that the settings file exists and that it isn't empty + if (-e $settings and !(-z $settings)) { + $self->logger("Reading USER settings from $settings"); + $userSettings = YAML::Tiny->read( "$settings" ); + + # if we can read userSettings + if($userSettings) { + # update the MASTER setttings to include updates from the userSettings + while(my($firstLevelKey, $firstLevelValue) = each %{$userSettings->[0]}) { + # the update approach is slightly different for hashes vs scalars/arrays + if (ref($firstLevelValue) eq "HASH") { + while(my ($secondLevelKey,$secondLevelValue) = each %{$userSettings->[0]{$firstLevelKey}}) { + if (ref $secondLevelValue eq "HASH"){ + # if masterSettings already contains a *scalar* value in secondLevelKey + # then we need to delete it (test-cases/headings-first.tex with indentRules1.yaml first demonstrated this) + if(ref $masterSettings{$firstLevelKey}{$secondLevelKey} ne "HASH"){ + $self->logger("masterSettings{$firstLevelKey}{$secondLevelKey} currently contains a *scalar* value, but it needs to be updated with a hash (see $settings); deleting the scalar") if($is_t_switch_active); + delete $masterSettings{$firstLevelKey}{$secondLevelKey} ; + } + while(my ($thirdLevelKey,$thirdLevelValue) = each %{$secondLevelValue}) { + if (ref $thirdLevelValue eq "HASH"){ + # similarly for third level + if (ref $masterSettings{$firstLevelKey}{$secondLevelKey}{$thirdLevelKey} ne "HASH"){ + $self->logger("masterSettings{$firstLevelKey}{$secondLevelKey}{$thirdLevelKey} currently contains a *scalar* value, but it needs to be updated with a hash (see $settings); deleting the scalar") if($is_t_switch_active); + delete $masterSettings{$firstLevelKey}{$secondLevelKey}{$thirdLevelKey} ; + } + while(my ($fourthLevelKey,$fourthLevelValue) = each %{$thirdLevelValue}) { + $masterSettings{$firstLevelKey}{$secondLevelKey}{$thirdLevelKey}{$fourthLevelKey} = $fourthLevelValue; + } + } else { + $masterSettings{$firstLevelKey}{$secondLevelKey}{$thirdLevelKey} = $thirdLevelValue; + } + } + } else { + $masterSettings{$firstLevelKey}{$secondLevelKey} = $secondLevelValue; + } + } + } else { + $masterSettings{$firstLevelKey} = $firstLevelValue; + } + } + + # output settings to $logfile + if($masterSettings{logFilePreferences}{showEveryYamlRead}){ + $self->logger(Dump \%{$userSettings->[0]}); + } else { + $self->logger("Not showing settings in the log file (see showEveryYamlRead and showAmalgamatedSettings)."); + } + } else { + # otherwise print a warning that we can not read userSettings.yaml + $self->logger("WARNING $settings contains invalid yaml format- not reading from it"); + } + } else { + # otherwise keep going, but put a warning in the log file + $self->logger("WARNING: $homeDir/indentconfig.yaml"); + if (-z $settings) { + $self->logger("specifies $settings but this file is EMPTY -- not reading from it"); + } else { + $self->logger("specifies $settings but this file does not exist - unable to read settings from this file"); + } + } + } + + # some users may wish to see showAmalgamatedSettings + # which details the overall state of the settings modified + # from the default in various user files + if($masterSettings{logFilePreferences}{showAmalgamatedSettings}){ + $self->logger("Amalgamated/overall settings to be used:",'heading'); + $self->logger(Dump \%masterSettings); + } + + return; +} + +sub get_indentation_settings_for_this_object{ + my $self = shift; + + # create a name for previously found settings + my $storageName = ${$self}{name}.${$self}{modifyLineBreaksYamlName}; + + # check for storage of repeated objects + if ($previouslyFoundSettings{$storageName}){ + $self->logger("Using stored settings for $storageName") if($is_t_switch_active); + } else { + my $name = ${$self}{name}; + $self->logger("Storing settings for $storageName") if($is_t_switch_active); + + # check for noAdditionalIndent and indentRules + # otherwise use defaultIndent + my $indentation = $self->get_indentation_information; + + # check for alignment at ampersand settings + $self->alignment_at_ampersand_settings; + + # check for line break settings + $self->modify_line_breaks_settings; + + # store the settings + %{${previouslyFoundSettings}{$storageName}} = ( + indentation=>$indentation, + BeginStartsOnOwnLine=>${$self}{BeginStartsOnOwnLine}, + BodyStartsOnOwnLine=>${$self}{BodyStartsOnOwnLine}, + EndStartsOnOwnLine=>${$self}{EndStartsOnOwnLine}, + EndFinishesWithLineBreak=>${$self}{EndFinishesWithLineBreak}, + ); + + # don't forget alignment settings! + ${${previouslyFoundSettings}{$storageName}}{lookForAlignDelims} = ${$self}{lookForAlignDelims} if(defined ${$self}{lookForAlignDelims}); + ${${previouslyFoundSettings}{$storageName}}{alignDoubleBackSlash} = ${$self}{alignDoubleBackSlash} if(defined ${$self}{alignDoubleBackSlash}); + ${${previouslyFoundSettings}{$storageName}}{spacesBeforeDoubleBackSlash} = ${$self}{spacesBeforeDoubleBackSlash} if(defined ${$self}{spacesBeforeDoubleBackSlash}); + + # some objects, e.g ifElseFi, can have extra assignments, e.g ElseStartsOnOwnLine + # these need to be stored as well! + foreach (@{${$self}{additionalAssignments}}){ + ${${previouslyFoundSettings}{$storageName}}{$_} = ${$self}{$_}; + } + + } + + # append indentation settings to the current object + while( my ($key,$value)= each %{${previouslyFoundSettings}{$storageName}}){ + ${$self}{$key} = $value; + } + + return; +} + +sub alignment_at_ampersand_settings{ + my $self = shift; + + # if the YamlName is, for example, optionalArguments, mandatoryArguments, heading, then we'll be looking for information about the *parent* + my $name = (defined ${$self}{nameForIndentationSettings}) ? ${$self}{nameForIndentationSettings} : ${$self}{name}; + + # check, for example, + # lookForAlignDelims: + # tabular: 1 + # or + # + # lookForAlignDelims: + # tabular: + # delims: 1 + # alignDoubleBackSlash: 1 + # spacesBeforeDoubleBackSlash: 2 + return unless ${$masterSettings{lookForAlignDelims}}{$name}; + + ## check, for example, + ## lookForAlignDelims: + ## tabular: + ## body: 1 + #return unless $self->get_object_attribute_for_indentation_settings; + + if(ref ${$masterSettings{lookForAlignDelims}}{$name} eq "HASH"){ + ${$self}{lookForAlignDelims} = (defined ${${$masterSettings{lookForAlignDelims}}{$name}}{delims} ) ? ${${$masterSettings{lookForAlignDelims}}{$name}}{delims} : 1; + ${$self}{alignDoubleBackSlash} = (defined ${${$masterSettings{lookForAlignDelims}}{$name}}{alignDoubleBackSlash} ) ? ${${$masterSettings{lookForAlignDelims}}{$name}}{alignDoubleBackSlash} : 1; + ${$self}{spacesBeforeDoubleBackSlash} = (defined ${${$masterSettings{lookForAlignDelims}}{$name}}{spacesBeforeDoubleBackSlash} ) ? ${${$masterSettings{lookForAlignDelims}}{$name}}{spacesBeforeDoubleBackSlash} : -1; + } else { + ${$self}{lookForAlignDelims} = 1; + ${$self}{alignDoubleBackSlash} = 1; + ${$self}{spacesBeforeDoubleBackSlash} = -1; + } + return; +} + +sub modify_line_breaks_settings{ + # return with undefined values unless the -m switch is active + return unless $is_m_switch_active; + + my $self = shift; + + # details to the log file + $self->logger("-m modifylinebreaks switch active, looking for settings for ${$self}{name} ",'heading') if $is_t_switch_active; + + # some objects, e.g ifElseFi, can have extra assignments, e.g ElseStartsOnOwnLine + my @toBeAssignedTo = ${$self}{additionalAssignments} ? @{${$self}{additionalAssignments}} : (); + + # the following will *definitley* be in the array, so let's add them + push(@toBeAssignedTo,("BeginStartsOnOwnLine","BodyStartsOnOwnLine","EndStartsOnOwnLine","EndFinishesWithLineBreak")); + + # we can effeciently loop through the following + foreach (@toBeAssignedTo){ + $self->get_every_or_custom_value( + toBeAssignedTo=>$_, + toBeAssignedToAlias=> ${$self}{aliases}{$_} ? ${$self}{aliases}{$_} : $_, + ); + } + return; +} + +sub get_every_or_custom_value{ + my $self = shift; + my %input = @_; + + my $toBeAssignedTo = $input{toBeAssignedTo}; + my $toBeAssignedToAlias = $input{toBeAssignedToAlias}; + + # alias + if(${$self}{aliases}{$toBeAssignedTo}){ + $self->logger("aliased $toBeAssignedTo using ${$self}{aliases}{$toBeAssignedTo}") if($is_t_switch_active); + } + + # name of the object in the modifyLineBreaks yaml (e.g environments, ifElseFi, etc) + my $YamlName = ${$self}{modifyLineBreaksYamlName}; + + # if the YamlName is either optionalArguments or mandatoryArguments, then we'll be looking for information about the *parent* + my $name = ($YamlName =~ m/Arguments/) ? ${$self}{parent} : ${$self}{name}; + + # these variables just ease the notation what follows + my $everyValue = ${${$masterSettings{modifyLineBreaks}}{$YamlName}}{$toBeAssignedToAlias}; + my $customValue = ${${${$masterSettings{modifyLineBreaks}}{$YamlName}}{$name}}{$toBeAssignedToAlias}; + + # check for the *custom* value + if (defined $customValue){ + $self->logger("$name: $toBeAssignedToAlias=$customValue, (*custom* value) adjusting $toBeAssignedTo") if($is_t_switch_active); + ${$self}{$toBeAssignedTo} = $customValue !=0 ? $customValue : undef; + } else { + # check for the *every* value + if (defined $everyValue and $everyValue != 0){ + $self->logger("$name: $toBeAssignedToAlias=$everyValue, (*every* value) adjusting $toBeAssignedTo") if($is_t_switch_active); + ${$self}{$toBeAssignedTo} = $everyValue; + } + } + return; +} + +sub get_indentation_information{ + my $self = shift; + + #************************************** + # SEARCHING ORDER: + # noAdditionalIndent *per-name* basis + # indentRules *per-name* basis + # noAdditionalIndentGlobal + # indentRulesGlobal + #************************************** + + # noAdditionalIndent can be a scalar or a hash, e.g + # + # noAdditionalIndent: + # myexample: 1 + # + # OR + # + # noAdditionalIndent: + # myexample: + # body: 1 + # optionalArguments: 1 + # mandatoryArguments: 1 + # + # specifying as a scalar with no field (e.g myexample: 1) + # will be interpreted as noAdditionalIndent for *every* + # field, so the body, optional arguments and mandatory arguments + # will *all* receive noAdditionalIndent + # + # indentRules can also be a scalar or a hash, e.g + # indentRules: + # myexample: "\t" + # + # OR + # + # indentRules: + # myexample: + # body: " " + # optionalArguments: "\t \t" + # mandatoryArguments: "" + # + # specifying as a scalar with no field will + # mean that *every* field will receive the same treatment + + # if the YamlName is, for example, optionalArguments, mandatoryArguments, heading, then we'll be looking for information about the *parent* + my $name = (defined ${$self}{nameForIndentationSettings}) ? ${$self}{nameForIndentationSettings} : ${$self}{name}; + + # if the YamlName is not optionalArguments, mandatoryArguments, heading (possibly others) then assume we're looking for 'body' + my $YamlName = $self->get_object_attribute_for_indentation_settings; + + my $indentationInformation; + foreach my $indentationAbout ("noAdditionalIndent","indentRules"){ + # check that the 'thing' is defined + if(defined ${$masterSettings{$indentationAbout}}{$name}){ + if(ref ${$masterSettings{$indentationAbout}}{$name} eq "HASH"){ + $self->logger("$indentationAbout indentation specified with multiple fields for $name, searching for $name: $YamlName (see $indentationAbout)") if $is_t_switch_active ; + $indentationInformation = ${${$masterSettings{$indentationAbout}}{$name}}{$YamlName}; + } else { + $indentationInformation = ${$masterSettings{$indentationAbout}}{$name}; + $self->logger("$indentationAbout indentation specified for $name (for *all* fields, body, optionalArguments, mandatoryArguments, afterHeading), using '$indentationInformation' (see $indentationAbout)") if $is_t_switch_active ; + } + # return, after performing an integrity check + if(defined $indentationInformation){ + if($indentationAbout eq "noAdditionalIndent" and $indentationInformation == 1){ + $self->logger("Found! Using '' (see $indentationAbout)") if $is_t_switch_active; + return q(); + } elsif($indentationAbout eq "indentRules" and $indentationInformation=~m/^\h*$/){ + $self->logger("Found! Using '$indentationInformation' (see $indentationAbout)") if $is_t_switch_active; + return $indentationInformation ; + } + } + } + } + + # gather information + $YamlName = ${$self}{modifyLineBreaksYamlName}; + + foreach my $indentationAbout ("noAdditionalIndent","indentRules"){ + # global assignments in noAdditionalIndentGlobal and/or indentRulesGlobal + my $globalInformation = $indentationAbout."Global"; + next if(!(defined ${$masterSettings{$globalInformation}}{$YamlName})); + if( ($globalInformation eq "noAdditionalIndentGlobal") and ${$masterSettings{$globalInformation}}{$YamlName}==1){ + $self->logger("$globalInformation specified for $YamlName (see $globalInformation)") if $is_t_switch_active; + return q(); + } elsif($globalInformation eq "indentRulesGlobal") { + if(${$masterSettings{$globalInformation}}{$YamlName}=~m/^\h*$/){ + $self->logger("$globalInformation specified for $YamlName (see $globalInformation)") if $is_t_switch_active; + return ${$masterSettings{$globalInformation}}{$YamlName}; + } else { + $self->logger("$globalInformation specified (${$masterSettings{$globalInformation}}{$YamlName}) for $YamlName, but it needs to only contain horizontal space -- I'm ignoring this one") if $is_t_switch_active; + } + } + } + + # return defaultIndent, by default + $self->logger("Using defaultIndent for $name") if $is_t_switch_active; + return $masterSettings{defaultIndent}; +} + +sub get_object_attribute_for_indentation_settings{ + # when looking for noAdditionalIndent or indentRules, we may need to determine + # which thing we're looking for, e.g + # + # chapter: + # body: 0 + # optionalArguments: 1 + # mandatoryArguments: 1 + # afterHeading: 0 + # + # this method returns 'body' by default, but the other objects (optionalArgument, mandatoryArgument, afterHeading) + # return their appropriate identifier. + return "body"; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm new file mode 100644 index 00000000000..be7ea36661d --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm @@ -0,0 +1,240 @@ +package LatexIndent::Heading; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_heading construct_headings_levels/; +our $headingCounter; +our @headingsRegexpArray; +our $allHeadingsRegexp = q(); + +sub construct_headings_levels{ + my $self = shift; + + # grab the heading levels + my %headingsLevels = %{$masterSettings{indentAfterHeadings}}; + + # delete the values that have indentAfterThisHeading set to 0 + while( my ($headingName,$headingInfo)= each %headingsLevels){ + if(!${$headingsLevels{$headingName}}{indentAfterThisHeading}){ + $self->logger("Not indenting after $headingName (see indentAfterThisHeading)",'heading') if $is_t_switch_active; + delete $headingsLevels{$headingName}; + } else { + # *all heading* regexp, remembering put starred headings at the front of the regexp + if($headingName =~ m/\*/){ + $self->logger("Putting $headingName at the beginning of the allHeadings regexp, as it contains a *"); + $allHeadingsRegexp = $headingName.($allHeadingsRegexp eq '' ?q():"|$allHeadingsRegexp"); + } else { + $self->logger("Putting $headingName at the END of the allHeadings regexp, as it contains a *"); + $allHeadingsRegexp .= ($allHeadingsRegexp eq '' ?q():"|").$headingName ; + } + } + } + + # check for a * in the name + $allHeadingsRegexp =~ s/\*/\\\*/g; + + # sort the file extensions by preference + my @sortedByLevels = sort { ${$headingsLevels{$a}}{level} <=> $headingsLevels{$b}{level} } keys(%headingsLevels); + + # it could be that @sortedByLevels is empty; + return if !@sortedByLevels; + + $self->logger("All headings regexp: $allHeadingsRegexp",'heading'); + $self->logger("Now to construct headings regexp for each level:",'heading'); + + # loop through the levels, and create a regexp for each (min and max values are the first and last values respectively from sortedByLevels) + for(my $i = ${$headingsLevels{$sortedByLevels[0]}}{level}; $i <= ${$headingsLevels{$sortedByLevels[-1]}}{level}; $i++ ){ + # level regexp + my @tmp = grep { ${$headingsLevels{$_}}{level} == $i } keys %headingsLevels; + if(@tmp){ + my $headingsAtThisLevel = q(); + foreach(@tmp){ + # put starred headings at the front of the regexp + if($_ =~ m/\*/){ + $self->logger("Putting $_ at the beginning of this regexp, as it contains a *"); + $headingsAtThisLevel = $_.($headingsAtThisLevel eq '' ?q():"|$headingsAtThisLevel"); + } else { + $self->logger("Putting $_ at the END of this regexp, as it contains a *"); + $headingsAtThisLevel .= ($headingsAtThisLevel eq '' ?q():"|").$_ ; + } + } + + # make the stars escaped correctly + $headingsAtThisLevel =~ s/\*/\\\*/g; + push(@headingsRegexpArray,$headingsAtThisLevel); + $self->logger("Heading level regexp for level $i will contain: $headingsAtThisLevel"); + } + } + } + +sub find_heading{ + + # if there are no headings regexps, there's no point going any further + return if!@headingsRegexpArray; + + my $self = shift; + + # otherwise loop through the headings regexp + $self->logger("Searching for special begin/end (see specialBeginEnd)"); + + # loop through each headings match; note that we need to + # do it in *reverse* so as to ensure that the lower level headings get matched first of all + foreach(reverse(@headingsRegexpArray)){ + + # the regexp + my $headingRegExp = qr/ + ( + \\($_) # name stored into $2 + ) # beginning bit into $1 + ( + .*? + ) # body into $3 + (\R*)? # linebreaks at end of body into $4 + ((?:\\(?:$allHeadingsRegexp))|$) # up to another heading, or else the end of the file + /sx; + + while(${$self}{body} =~ m/$headingRegExp/){ + + # log file output + $self->logger("heading found: $2",'heading'); + + ${$self}{body} =~ s/ + $headingRegExp + / + # create a new heading object + my $headingObject = LatexIndent::Heading->new(begin=>q(), + body=>$1.$3, + end=>q(), + afterbit=>($4?$4:q()).($5?$5:q()), + name=>$2.":heading", + parent=>$2, + nameForIndentationSettings=>$2, + linebreaksAtEnd=>{ + begin=>0, + body=>0, + end=>0, + }, + modifyLineBreaksYamlName=>"afterHeading", + endImmediatelyFollowedByComment=>0, + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($headingObject); + ${@{${$self}{children}}[-1]}{replacementText}; + /xse; + } + } +} + +sub get_replacement_text{ + my $self = shift; + + # the replacement text for a heading (chapter, section, etc) needs to put the trailing part back in + $self->logger("Custom replacement text routine for heading ${$self}{name}"); + ${$self}{replacementText} = ${$self}{id}.${$self}{afterbit}; + delete ${$self}{afterbit}; +} + +sub create_unique_id{ + my $self = shift; + + $headingCounter++; + + ${$self}{id} = "$tokens{heading}$headingCounter"; + return; +} + +sub adjust_replacement_text_line_breaks_at_end{ + return; +} + +sub get_object_attribute_for_indentation_settings{ + # when looking for noAdditionalIndent or indentRules, we may need to determine + # which thing we're looking for, e.g + # + # chapter: + # body: 0 + # optionalArguments: 1 + # mandatoryArguments: 1 + # afterHeading: 0 + # + # this method returns 'body' by default, but the other objects (optionalArgument, mandatoryArgument, afterHeading) + # return their appropriate identifier. + my $self = shift; + + return ${$self}{modifyLineBreaksYamlName}; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # search for commands, keys, named grouping braces + $self->find_commands_or_key_equals_values_braces; + + # we need to transfer the details from the modifyLineBreaks of the command + # child object to the heading object. + # + # for example, if we have + # + # \chapter{some heading here} + # + # and we want to modify the linebreak before the \chapter command using, for example, + # + # commands: + # CommandStartsOnOwnLine: 1 + # + # then we need to transfer this information to the heading object + if($is_m_switch_active){ + $self->logger("Searching for linebreak preferences immediately infront of ${$self}{parent}",'heading'); + foreach(@{${$self}{children}}){ + if(${$_}{name} eq ${$self}{parent}){ + $self->logger("Named child found: ${$_}{name}"); + if(defined ${$_}{BeginStartsOnOwnLine}){ + $self->logger("Transferring information from ${$_}{id} (${$_}{name}) to ${$self}{id} (${$self}{name}) for BeginStartsOnOwnLine"); + ${$self}{BeginStartsOnOwnLine} = ${$_}{BeginStartsOnOwnLine}; + } else { + $self->logger("No information found in ${$_}{name} for BeginStartsOnOwnLine"); + } + last; + } + } + } + + # search for special begin/end + $self->find_special; + + return; +} + +sub add_surrounding_indentation_to_begin_statement{ + # almost all of the objects add surrounding indentation to the 'begin' statements, + # but some (e.g HEADING) have their own method + my $self = shift; + + $self->logger("Adding surrounding indentation after (empty, by design!) begin statement of ${$self}{name} (${$self}{id})"); + ${$self}{begin} .= ${$self}{surroundingIndentation}; # add indentation + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/HiddenChildren.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/HiddenChildren.pm new file mode 100644 index 00000000000..594e7dbd14e --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/HiddenChildren.pm @@ -0,0 +1,190 @@ +package LatexIndent::HiddenChildren; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use LatexIndent::Tokens qw/%tokens/; +use Data::Dumper; +use Exporter qw/import/; +our @EXPORT_OK = qw/find_surrounding_indentation_for_children update_family_tree get_family_tree check_for_hidden_children %familyTree/; + +# hiddenChildren can be stored in a global array, it doesn't matter what level they're at +our %familyTree; +our %allChildren; + + +#---------------------------------------------------------- +# Discussion surrounding hidden children +# +# Consider the following latex code +# +# \begin{one} +# body of one +# body of one +# body of one +# \begin{two} +# body of two +# body of two +# body of two +# body of two +# \end{two} +# \end{one} +# +# From the visual perspective, we might say that and are *nested* children; +# from the persepective of latexindent.pl, however, they actually have *the same level*. +# +# Graphically, you might represent it as follows +# +# * +# / \ +# / \ +# / \ +# O O +# +# where * represents the 'root' document object, and each 'O' is an environment object; the +# first one, on the left, represents and the second one, on the right, represents . +# (Remember that the environment regexp does not allow \begin within its body.) +# +# When processing the document, will be processed *before* . Furthermore, because +# and are at the same level, they are not *natural* ancestors of each other; as such, +# we say that is a *hidden* child, and that its 'adopted' ancestor is . +# +# We need to go to a lot of effort to make sure that knows about its ancestors and its +# surrounding indentation ( in this case). The subroutines in this file do that effort. +#---------------------------------------------------------- + +sub find_surrounding_indentation_for_children{ + my $self = shift; + + # output to logfile + $self->logger("FamilyTree before update:",'heading') if $is_t_switch_active; + $self->logger(Dumper(\%familyTree)) if($is_t_switch_active); + + # update the family tree with ancestors + $self->update_family_tree; + + # output information to the logfile + $self->logger("FamilyTree after update:",'heading') if $is_t_switch_active; + $self->logger(Dumper(\%familyTree)) if($is_t_switch_active); + + while( my ($idToSearch,$ancestorToSearch) = each %familyTree){ + $self->logger("Hidden child ID: ,$idToSearch, here are its ancestors:",'heading') if $is_t_switch_active; + foreach(@{${$ancestorToSearch}{ancestors}}){ + $self->logger("ID: ${$_}{ancestorID}") if($is_t_switch_active); + my $tmpIndentation = ref(${$_}{ancestorIndentation}) eq 'SCALAR'?${${$_}{ancestorIndentation}}:${$_}{ancestorIndentation}; + $tmpIndentation = $tmpIndentation ? $tmpIndentation : q(); + $self->logger("indentation: '$tmpIndentation'") if($is_t_switch_active); + } + } + + return; +} + +sub update_family_tree{ + my $self = shift; + + # loop through the hash + $self->logger("Updating FamilyTree...",'heading') if $is_t_switch_active; + while( my ($idToSearch,$ancestorToSearch)= each %familyTree){ + foreach(@{${$ancestorToSearch}{ancestors}}){ + my $ancestorID = ${$_}{ancestorID}; + $self->logger("current ID: $idToSearch, ancestor: $ancestorID") if($is_t_switch_active); + if($familyTree{$ancestorID}){ + $self->logger("$ancestorID is a key within familyTree, grabbing its ancestors") if($is_t_switch_active); + my $naturalAncestors = q(); + foreach(@{${$familyTree{$idToSearch}}{ancestors}}){ + $naturalAncestors .= "---".${$_}{ancestorID} if(${$_}{type} eq "natural"); + } + foreach(@{${$familyTree{$ancestorID}}{ancestors}}){ + $self->logger("ancestor of *hidden* child: ${$_}{ancestorID}") if($is_t_switch_active); + my $newAncestorId = ${$_}{ancestorID}; + my $type; + if($naturalAncestors =~ m/$ancestorID/){ + $type = "natural"; + } else { + $type = "adopted"; + } + my $matched = grep { $_->{ancestorID} eq $newAncestorId } @{${$familyTree{$idToSearch}}{ancestors}}; + push(@{${$familyTree{$idToSearch}}{ancestors}},{ancestorID=>${$_}{ancestorID},ancestorIndentation=>${$_}{ancestorIndentation},type=>$type}) unless($matched); + } + } else { + my $naturalAncestors = q(); + foreach(@{${$familyTree{$idToSearch}}{ancestors}}){ + $naturalAncestors .= "---".${$_}{ancestorID} if(${$_}{type} eq "natural"); + } + $self->logger("natural ancestors of $ancestorID: $naturalAncestors") if($is_t_switch_active); + foreach(@{${$allChildren{$ancestorID}}{ancestors}}){ + my $newAncestorId = ${$_}{ancestorID}; + my $type; + if($naturalAncestors =~ m/$newAncestorId/){ + $type = "natural"; + } else { + $type = "adopted"; + } + my $matched = grep { $_->{ancestorID} eq $newAncestorId } @{${$familyTree{$idToSearch}}{ancestors}}; + unless($matched){ + $self->logger("ancestor of UNHIDDEN child: ${$_}{ancestorID}") if($is_t_switch_active); + push(@{${$familyTree{$idToSearch}}{ancestors}},{ancestorID=>${$_}{ancestorID},ancestorIndentation=>${$_}{ancestorIndentation},type=>$type}); + } + } + } + } + } + +} + +sub check_for_hidden_children{ + + my $self = shift; + + # if there are no hidden children, then exit + return if ${$self}{body} !~ m/$tokens{beginOfToken}/; + + # grab the matches + my @matched = (${$self}{body} =~ /((?:$tokens{ifelsefiSpecial})?$tokens{beginOfToken}.[-a-z0-9]+?$tokens{endOfToken})/ig); + + # log file + $self->logger("Hidden children check") if $is_t_switch_active; + $self->logger(join("|",@matched)) if $is_t_switch_active; + + my $naturalAncestors = ${$self}{naturalAncestors}; + + # loop through the hidden children + foreach my $match (@matched){ + # update the family tree with ancestors of self + if(${$self}{ancestors}){ + foreach(@{${$self}{ancestors}}){ + my $newAncestorId = ${$_}{ancestorID}; + unless (grep { $_->{ancestorID} eq $newAncestorId } @{${$familyTree{$match}}{ancestors}}){ + my $type = ($naturalAncestors =~ m/${$_}{ancestorID}/ ) ? "natural" : "adopted"; + $self->logger("Adding ${$_}{ancestorID} to the $type family tree of $match") if($is_t_switch_active); + push(@{$familyTree{$match}{ancestors}},{ancestorID=>${$_}{ancestorID},ancestorIndentation=>${$_}{ancestorIndentation},type=>$type}); + } + } + } + + # update the family tree with self + unless (grep { $_->{ancestorID} eq ${$self}{id}} @{${$familyTree{$match}}{ancestors}}){ + my $type = ($naturalAncestors =~ m/${$self}{id}/ ) ? "natural" : "adopted"; + $self->logger("Adding ${$self}{id} to the $type family tree of hiddenChild $match") if($is_t_switch_active); + push(@{$familyTree{$match}{ancestors}},{ancestorID=>${$self}{id},ancestorIndentation=>${$self}{indentation},type=>$type}); + } + } + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/HorizontalWhiteSpace.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/HorizontalWhiteSpace.pm new file mode 100644 index 00000000000..360a8077022 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/HorizontalWhiteSpace.pm @@ -0,0 +1,62 @@ +package LatexIndent::HorizontalWhiteSpace; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @EXPORT_OK = qw/remove_trailing_whitespace remove_leading_space/; + +sub remove_trailing_whitespace{ + my $self = shift; + my %input = @_; + + # this method can be called before the indendation, and after, depending upon the input + if($input{when} eq "before"){ + return unless(${$masterSettings{removeTrailingWhitespace}}{beforeProcessing}); + $self->logger("Removing trailing white space *before* the document is processed (see removeTrailingWhitespace: beforeProcessing)",'heading') if $is_t_switch_active; + } elsif($input{when} eq "after"){ + return unless(${$masterSettings{removeTrailingWhitespace}}{afterProcessing}); + $self->logger("Removing trailing white space *after* the document is processed (see removeTrailingWhitespace: afterProcessing)",'heading') if $is_t_switch_active; + } else { + return; + } + + ${$self}{body} =~ s/ + \h+ # followed by possible horizontal space + $ # up to the end of a line + //xsmg; + + $self->logger("Processed body, *$input{when}* indentation (${$self}{name}):") if($is_t_switch_active); + $self->logger(${$self}{body}) if($is_t_switch_active); + +} + +sub remove_leading_space{ + my $self = shift; + $self->logger("Removing leading space from ${$self}{name} (verbatim/noindentblock already accounted for)",'heading') if $is_t_switch_active; + ${$self}{body} =~ s/ + ( + ^ # beginning of the line + \h* # with 0 or more horizontal spaces + )? # possibly + //mxg; + return; +} + + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm new file mode 100755 index 00000000000..e1ac17b3613 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm @@ -0,0 +1,276 @@ +package LatexIndent::IfElseFi; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_ifelsefi/; +our %previouslyFoundSettings; +our $ifElseFiCounter; + +# store the regular expresssion for matching and replacing the \if...\else...\fi statements +# note: we search for \else separately in an attempt to keep this regexp a little more managable +our $ifElseFiRegExp = qr/ + ( + \\ + (@?if[a-zA-Z@]*?) + \h* + (\R*) + ) # begin statement, e.g \ifnum, \ifodd + ( + \\(?!if)|\R|\h|\#|!-! # up until a \\, linebreak # or !-!, which is + ) # part of the tokens used for latexindent + ( + (?: + (?!\\if). + )*? # body, which can't include another \if + ) + (\R*) # linebreaks after body + ( + \\fi(?![a-zA-Z]) # \fi statement + ) + (\h*) # 0 or more horizontal spaces + (\R)? # linebreaks after \fi +/sx; + + +sub indent{ + my $self = shift; + + # determine the surrounding and current indentation + $self->determine_total_indentation; + + # line break checks after \if statement, can get messy if we + # have, for example + # \ifnum + # something + # which might be changed into + # \ifnumsomething + # which is undeserible + if (defined ${$self}{BodyStartsOnOwnLine} + and ${$self}{BodyStartsOnOwnLine}==-1 + and ${$self}{body} !~ m/^(\h|\\|(?:!-!))/s + ){ + ${$self}{begin} .= " "; + } + + # indent the body + $self->indent_body; + + # calculate and grab the surrounding indentation for the \else statement adjustment + $self->get_surrounding_indentation; + my $surroundingIndentation = ${$self}{surroundingIndentation}?${$self}{surroundingIndentation}:q(); + + if(${$self}{elsePresent} and ${$self}{linebreaksAtEnd}{ifbody}){ + $self->logger("Adding surrounding indentation to \\else statement ('$surroundingIndentation')")if $is_t_switch_active; + ${$self}{body} =~ s/\h*\\else/$surroundingIndentation\\else/; + $self->logger("Body (${$self}{name}) after \\else adjustment:\n${$self}{body}") if $is_t_switch_active; + } + + # indent the end statement + $self->indent_end_statement; + + # wrap-up statement + $self->wrap_up_statement; + + # line break checks *after* \end{statement} + if (defined ${$self}{EndFinishesWithLineBreak} + and ${$self}{EndFinishesWithLineBreak}==-1 + ) { + # add a single horizontal space after the child id, otherwise we can end up + # with things like + # before: + # \fi + # text + # after: + # \fitext + $self->logger("Adding a single space after \\fi statement (otherwise \\fi can be comined with next line of text in an unwanted way)",'heading') if $is_t_switch_active; + ${$self}{end} =${$self}{end}." "; + } + + return $self; +} + +sub find_ifelsefi{ + my $self = shift; + + while( ${$self}{body} =~ m/$ifElseFiRegExp\h*($trailingCommentRegExp)?/){ + + ${$self}{body} =~ s/ + $ifElseFiRegExp(\h*)($trailingCommentRegExp)? + / + # log file output + $self->logger("IfElseFi found: $2",'heading')if $is_t_switch_active; + + # create a new IfElseFi object + my $ifElseFi = LatexIndent::IfElseFi->new(begin=>$1.(($4 eq "\n" and !$3)?"\n":q()), + name=>$2, + # if $4 is a line break, don't count it twice (it will already be in 'begin') + body=>($4 eq "\n") ? $5.$6 : $4.$5.$6, + end=>$7, + linebreaksAtEnd=>{ + begin=>(($4 eq "\n")||$3)?1:0, + body=>$6?1:0, + end=>$9?1:0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"IfStartsOnOwnLine", + # end statements + EndStartsOnOwnLine=>"FiStartsOnOwnLine", + # after end statements + EndFinishesWithLineBreak=>"FiFinishesWithLineBreak", + }, + elsePresent=>0, + modifyLineBreaksYamlName=>"ifElseFi", + additionalAssignments=>["ElseStartsOnOwnLine","ElseFinishesWithLineBreak"], + endImmediatelyFollowedByComment=>$9?0:($11?1:0), + horizontalTrailingSpace=>$8?$8:q(), + ); + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($ifElseFi); + ${@{${$self}{children}}[-1]}{replacementText}.($10?$10:q()).($11?$11:q()); + /xse; + + } + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # check for existence of \else statement, and associated line break information + $self->check_for_else_statement; + + # search for headings (important to do this before looking for commands!) + $self->find_heading; + + # search for commands, keys, named grouping braces + $self->find_commands_or_key_equals_values_braces; + + # search for arguments + $self->find_opt_mand_arguments; + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for special begin/end + $self->find_special; + +} + +sub create_unique_id{ + my $self = shift; + + $ifElseFiCounter++; + + ${$self}{id} = "$tokens{ifelsefi}$ifElseFiCounter"; + return; +} + +sub check_for_else_statement{ + my $self = shift; + $self->logger("Looking for \\else statement (${$self}{name})",'heading') if $is_t_switch_active; + if(${$self}{body} =~ m/ + (\R*) # possible line breaks before \else statement + \\else + \h* # possible horizontal space + (\R*) # possible line breaks after \else statement + /x){ + $self->logger("found \\else statement, storing line break information:") if($is_t_switch_active); + + # linebreaks *before* \else statement + ${$self}{linebreaksAtEnd}{ifbody} = $1?1:0; + $self->logger("linebreaksAtEnd of ifbody: ${$self}{linebreaksAtEnd}{ifbody}") if($is_t_switch_active); + + # linebreaks *after* \else statement + ${$self}{linebreaksAtEnd}{else} = $2?1:0; + $self->logger("linebreaksAtEnd of else: ${$self}{linebreaksAtEnd}{else}") if($is_t_switch_active); + ${$self}{elsePresent}=1; + + # check that \else isn't the first thing in body + if(${$self}{body} =~ m/^\\else/s and ${$self}{linebreaksAtEnd}{begin}){ + ${$self}{linebreaksAtEnd}{ifbody} = 1; + $self->logger("\\else *begins* the ifbody, linebreaksAtEnd of ifbody: ${$self}{linebreaksAtEnd}{ifbody}") if($is_t_switch_active); + } + + # check if -m switch is active + return unless $is_m_switch_active; + + # possibly modify line break *before* \else statement + if(defined ${$self}{ElseStartsOnOwnLine}){ + if(${$self}{ElseStartsOnOwnLine}>=1 and !${$self}{linebreaksAtEnd}{ifbody}){ + # by default, assume that no trailing comment token is needed + my $trailingCommentToken = q(); + if(${$self}{ElseStartsOnOwnLine}==2){ + $self->logger("Adding a % immediately before else statement of ${$self}{name} (ElseStartsOnOwnLine==2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + } + + # add a line break after ifbody, if appropriate + $self->logger("Adding a linebreak before the \\else statement (see ElseStartsOnOwnLine)"); + ${$self}{body} =~ s/\\else/$trailingCommentToken\n\\else/s; + ${$self}{linebreaksAtEnd}{ifbody} = 1; + } elsif (${$self}{ElseStartsOnOwnLine}==-1 and ${$self}{linebreaksAtEnd}{ifbody}){ + # remove line break *after* ifbody, if appropriate + $self->logger("Removing linebreak before \\else statement (see ElseStartsOnOwnLine)"); + ${$self}{body} =~ s/\R*(\h*)\\else/$1\\else/sx; + ${$self}{linebreaksAtEnd}{ifbody} = 0; + } + } + + # possibly modify line break *before* \else statement + if(defined ${$self}{ElseFinishesWithLineBreak}){ + if(${$self}{ElseFinishesWithLineBreak}>=1 and !${$self}{linebreaksAtEnd}{else}){ + # by default, assume that no trailing comment token is needed + my $trailingCommentToken = q(); + if(${$self}{ElseFinishesWithLineBreak}==2){ + return if(${$self}{body} =~ m/\\else\h*$trailingCommentRegExp/s); + $self->logger("Adding a % immediately after else statement of ${$self}{name} (ElseFinishesWithLineBreak==2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + } + + # add a line break after else, if appropriate + $self->logger("Adding a linebreak after the \\else statement (see ElseFinishesWithLineBreak)")if $is_t_switch_active; + ${$self}{body} =~ s/\\else\h*/\\else$trailingCommentToken\n/s; + ${$self}{linebreaksAtEnd}{else} = 1; + } elsif (${$self}{ElseFinishesWithLineBreak}==-1 and ${$self}{linebreaksAtEnd}{else}){ + # remove line break *after* else, if appropriate, + # note the space so that, for example, + # \else + # some text + # becomes + # \else some text + # and not + # \elsesome text + $self->logger("Removing linebreak after \\else statement (see ElseFinishesWithLineBreak)")if $is_t_switch_active; + ${$self}{body} =~ s/\\else\h*\R*/\\else /sx; + ${$self}{linebreaksAtEnd}{else} = 0; + } + } + + return; + } else { + $self->logger("\\else statement not found") if($is_t_switch_active); + } +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm new file mode 100644 index 00000000000..600aed5040f --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm @@ -0,0 +1,371 @@ +package LatexIndent::Indent; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +use LatexIndent::HiddenChildren qw/%familyTree/; +use Data::Dumper; +use Exporter qw/import/; +our @EXPORT_OK = qw/indent wrap_up_statement determine_total_indentation indent_begin indent_body indent_end_statement final_indentation_check push_family_tree_to_indent get_surrounding_indentation indent_children_recursively check_for_blank_lines_at_beginning put_blank_lines_back_in_at_beginning add_surrounding_indentation_to_begin_statement/; +our %familyTree; + +sub indent{ + my $self = shift; + + # determine the surrounding and current indentation + $self->determine_total_indentation; + + # indent the begin statement + $self->indent_begin; + + # indent the body + $self->indent_body; + + # indent the end statement + $self->indent_end_statement; + + # output the completed object to the log file + $self->logger("Complete indented object (${$self}{name}) after indentation:\n${$self}{begin}${$self}{body}${$self}{end}") if $is_t_switch_active; + + # wrap-up statement + $self->wrap_up_statement; + return $self; +} + +sub wrap_up_statement{ + my $self = shift; + $self->logger("Finished indenting ${$self}{name}",'heading') if $is_t_switch_active; + return $self; + } + +sub determine_total_indentation{ + my $self = shift; + + # calculate and grab the surrounding indentation + $self->get_surrounding_indentation; + + # logfile information + my $surroundingIndentation = ${$self}{surroundingIndentation}; + $self->logger("indenting object ${$self}{name}") if($is_t_switch_active); + (my $during = $surroundingIndentation) =~ s/\t/TAB/g; + $self->logger("indentation *surrounding* object: '$during'") if($is_t_switch_active); + ($during = ${$self}{indentation}) =~ s/\t/TAB/g; + $self->logger("indentation *of* object: '$during'") if($is_t_switch_active); + ($during = $surroundingIndentation.${$self}{indentation}) =~ s/\t/TAB/g; + $self->logger("*total* indentation to be added: '$during'") if($is_t_switch_active); + + # form the total indentation of the object + ${$self}{indentation} = $surroundingIndentation.${$self}{indentation}; + +} + +sub get_surrounding_indentation{ + my $self = shift; + + my $surroundingIndentation = q(); + + if($familyTree{${$self}{id}}){ + $self->logger("Adopted ancestors found!") if($is_t_switch_active); + foreach(@{${$familyTree{${$self}{id}}}{ancestors}}){ + if(${$_}{type} eq "adopted"){ + my $newAncestorId = ${$_}{ancestorID}; + $self->logger("ancestor ID: $newAncestorId, adding indentation of $newAncestorId to surroundingIndentation of ${$self}{id}") if($is_t_switch_active); + $surroundingIndentation .= ref(${$_}{ancestorIndentation}) eq 'SCALAR' + ? + (${${$_}{ancestorIndentation}}?${${$_}{ancestorIndentation}}:q()) + : + (${$_}{ancestorIndentation}?${$_}{ancestorIndentation}:q()); + } + } + } + ${$self}{surroundingIndentation} = $surroundingIndentation; + +} + +sub indent_begin{ + # for most objects, the begin statement is just one line, but there are exceptions, e.g KeyEqualsValuesBraces + return; +} + +sub indent_body{ + my $self = shift; + + # grab the indentation of the object + my $indentation = ${$self}{indentation}; + + # output to the logfile + $self->logger("Body (${$self}{name}) before indentation:\n${$self}{body}") if $is_t_switch_active; + + # last minute check for modified bodyLineBreaks + $self->count_body_line_breaks if $is_m_switch_active; + + # some objects need to check for blank line tokens at the beginning + $self->check_for_blank_lines_at_beginning if $is_m_switch_active; + + # some objects can format their body to align at the & character + $self->align_at_ampersand if ${$self}{lookForAlignDelims}; + + # body indendation + if(${$self}{linebreaksAtEnd}{begin}==1){ + if(${$self}{body} =~ m/^\h*$/s){ + $self->logger("Body of ${$self}{name} is empty, not applying indentation") if $is_t_switch_active; + } else { + # put any existing horizontal space after the current indentation + $self->logger("Entire body of ${$self}{name} receives indendentation") if $is_t_switch_active; + ${$self}{body} =~ s/^(\h*)/$indentation$1/mg; # add indentation + } + } elsif(${$self}{linebreaksAtEnd}{begin}==0 and ${$self}{bodyLineBreaks}>0) { + if(${$self}{body} =~ m/ + (.*?) # content of first line + \R # first line break + (.*$) # rest of body + /sx){ + my $bodyFirstLine = $1; + my $remainingBody = $2; + $self->logger("first line of body: $bodyFirstLine",'heading') if $is_t_switch_active; + $self->logger("remaining body (before indentation):\n'$remainingBody'") if($is_t_switch_active); + + # add the indentation to all the body except first line + $remainingBody =~ s/^/$indentation/mg unless($remainingBody eq ''); # add indentation + $self->logger("remaining body (after indentation):\n$remainingBody'") if($is_t_switch_active); + + # put the body back together + ${$self}{body} = $bodyFirstLine."\n".$remainingBody; + } + } + + # if the routine check_for_blank_lines_at_beginning has been called, then the following routine + # puts blank line tokens back in + $self->put_blank_lines_back_in_at_beginning if $is_m_switch_active; + + # the final linebreak can be modified by a child object; see test-cases/commands/figureValign-mod5.tex, for example + if($is_m_switch_active and defined ${$self}{linebreaksAtEnd}{body} and ${$self}{linebreaksAtEnd}{body}==1 and ${$self}{body} !~ m/\R$/){ + $self->logger("Updating body for ${$self}{name} to contain a linebreak at the end (linebreaksAtEnd is 1, but there isn't currently a linebreak)") if($is_t_switch_active); + ${$self}{body} .= "\n"; + } + + # output to the logfile + $self->logger("Body (${$self}{name}) after indentation:\n${$self}{body}") if $is_t_switch_active; + return $self; +} + +sub check_for_blank_lines_at_beginning{ + # some objects need this routine + return; +} + +sub put_blank_lines_back_in_at_beginning{ + # some objects need this routine + return; +} + +sub indent_end_statement{ + my $self = shift; + my $surroundingIndentation = (${$self}{surroundingIndentation} and $familyTree{${$self}{id}}) + ? + (ref(${$self}{surroundingIndentation}) eq 'SCALAR'?${${$self}{surroundingIndentation}}:${$self}{surroundingIndentation}) + :q(); + + # end{statement} indentation, e.g \end{environment}, \fi, }, etc + if(${$self}{linebreaksAtEnd}{body}){ + ${$self}{end} =~ s/^\h*/$surroundingIndentation/mg; # add indentation + $self->logger("Adding surrounding indentation to ${$self}{end} (${$self}{name}: '$surroundingIndentation')") if($is_t_switch_active); + } + return $self; +} + +sub final_indentation_check{ + # problem: + # if a tab is appended to spaces, it will look different + # from spaces appended to tabs (see test-cases/items/spaces-and-tabs.tex) + # solution: + # move all of the tabs to the beginning of ${$self}{indentation} + # notes; + # this came to light when studying test-cases/items/items1.tex + + my $self = shift; + + my $indentation; + my $numberOfTABS; + my $after; + ${$self}{body} =~ s/ + ^((\h*|\t*)((\h+)(\t+))+) + / + # fix the indentation + $indentation = $1; + + # count the number of tabs + $numberOfTABS = () = $indentation=~ \/\t\/g; + $self->logger("Number of tabs: $numberOfTABS") if($is_t_switch_active); + + # log the after + ($after = $indentation) =~ s|\t||g; + $after = "TAB"x$numberOfTABS.$after; + $self->logger("Indentation after: '$after'") if($is_t_switch_active); + ($indentation = $after) =~s|TAB|\t|g; + $indentation; + /xsmeg; + +} + +sub indent_children_recursively{ + my $self = shift; + + unless(defined ${$self}{children}) { + $self->logger("No child objects (${$self}{name})") if $is_t_switch_active; + return; + } + + $self->logger('Pre-processed body:','heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + + # send the children through this indentation routine recursively + if(defined ${$self}{children}){ + foreach my $child (@{${$self}{children}}){ + $self->logger("Indenting child objects on ${$child}{name}") if $is_t_switch_active; + $child->indent_children_recursively; + } + } + + $self->logger("Replacing ids with begin, body, and end statements:",'heading') if $is_t_switch_active; + + # loop through document children hash + while( scalar (@{${$self}{children}}) > 0 ){ + my $index = 0; + # we work through the array *in order* + foreach my $child (@{${$self}{children}}){ + $self->logger("Searching ${$self}{name} for ${$child}{id}...",'heading') if $is_t_switch_active; + if(${$self}{body} =~ m/${$child}{id}/s){ + # we only care if id is first non-white space character + # and if followed by line break + # if m switch is active + my $IDFirstNonWhiteSpaceCharacter = 0; + my $IDFollowedImmediatelyByLineBreak = 0; + + # update the above two, if necessary + if ($is_m_switch_active){ + $IDFirstNonWhiteSpaceCharacter = (${$self}{body} =~ m/^${$child}{id}/m + or + ${$self}{body} =~ m/^\h\h*${$child}{id}/m + ) ?1:0; + $IDFollowedImmediatelyByLineBreak = (${$self}{body} =~ m/${$child}{id}\h*\R*/m) ?1:0; + } + + # log file info + $self->logger("${$child}{id} found!") if($is_t_switch_active); + $self->logger("Indenting ${$child}{name} (id: ${$child}{id})",'heading') if $is_t_switch_active; + $self->logger("looking up indentation scheme for ${$child}{name}") if($is_t_switch_active); + + # line break checks *after* + if (defined ${$child}{EndFinishesWithLineBreak} + and ${$child}{EndFinishesWithLineBreak}==-1 + and $IDFollowedImmediatelyByLineBreak) { + # remove line break *after* , if appropriate + my $EndStringLogFile = ${$child}{aliases}{EndFinishesWithLineBreak}||"EndFinishesWithLineBreak"; + $self->logger("Removing linebreak after ${$child}{end} (see $EndStringLogFile)") if $is_t_switch_active; + ${$self}{body} =~ s/${$child}{id}(\h*)?(\R|\h)*/${$child}{id}$1/s; + ${$child}{linebreaksAtEnd}{end} = 0; + } + + # perform indentation + $child->indent; + + # surrounding indentation is now up to date + my $surroundingIndentation = (${$child}{surroundingIndentation} and ${$child}{hiddenChildYesNo}) + ? + (ref(${$child}{surroundingIndentation}) eq 'SCALAR'?${${$child}{surroundingIndentation}}:${$child}{surroundingIndentation}) + :q(); + + # line break checks before + if(defined ${$child}{BeginStartsOnOwnLine}){ + my $BeginStringLogFile = ${$child}{aliases}{BeginStartsOnOwnLine}||"BeginStartsOnOwnLine"; + if(${$child}{BeginStartsOnOwnLine}>=1 and !$IDFirstNonWhiteSpaceCharacter){ + # by default, assume that no trailing comment token is needed + my $trailingCommentToken = q(); + if(${$child}{BeginStartsOnOwnLine}==2){ + $self->logger("Removing space immediately before ${$child}{id}, in preparation for adding % ($BeginStringLogFile == 2)") if $is_t_switch_active; + ${$self}{body} =~ s/\h*${$child}{id}/${$child}{id}/s; + $self->logger("Adding a % at the end of the line that ${$child}{begin} is on, then a linebreak ($BeginStringLogFile == 2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + } else { + $self->logger("Adding a linebreak at the beginning of ${$child}{begin} (see $BeginStringLogFile)") if $is_t_switch_active; + } + + # the trailing comment/linebreak magic + ${$child}{begin} = "$trailingCommentToken\n".${$child}{begin}; + $child->add_surrounding_indentation_to_begin_statement; + + # remove surrounding indentation ahead of % + ${$child}{begin} =~ s/^(\h*)%/%/ if(${$child}{BeginStartsOnOwnLine}==2); + } elsif (${$child}{BeginStartsOnOwnLine}==-1 and $IDFirstNonWhiteSpaceCharacter){ + # important to check we don't move the begin statement next to a blank-line-token + my $blankLineToken = $tokens{blanklines}; + if(${$self}{body} !~ m/$blankLineToken\R*\h*${$child}{id}/s){ + $self->logger("Removing linebreak before ${$child}{begin} (see $BeginStringLogFile in ${$child}{modifyLineBreaksYamlName} YAML)") if $is_t_switch_active; + ${$self}{body} =~ s/(\h*)(?:\R*|\h*)+${$child}{id}/$1${$child}{id}/s; + } else { + $self->logger("Not removing linebreak ahead of ${$child}{begin}, as blank-line-token present (see preserveBlankLines)") if $is_t_switch_active; + } + } + } + + $self->logger(Dumper(\%{$child}),'ttrace') if($is_tt_switch_active); + + # replace ids with body + ${$self}{body} =~ s/${$child}{id}/${$child}{begin}${$child}{body}${$child}{end}/; + + # log file info + $self->logger("Body (${$self}{name}) now looks like:",'heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + + # remove element from array: http://stackoverflow.com/questions/174292/what-is-the-best-way-to-delete-a-value-from-an-array-in-perl + splice(@{${$self}{children}}, $index, 1); + + # output to the log file + $self->logger("deleted child key ${$child}{name} (parent is: ${$self}{name})") if $is_t_switch_active; + + # restart the loop, as the size of the array has changed + last; + } else { + $self->logger("${$child}{id} not found") if($is_t_switch_active); + } + + # increment the loop counter + $index++; + } + } + + # logfile info + $self->logger("${$self}{name} has this many children:",'heading') if $is_t_switch_active; + $self->logger(scalar @{${$self}{children}}) if $is_t_switch_active; + $self->logger("Post-processed body (${$self}{name}):") if($is_t_switch_active); + $self->logger(${$self}{body}) if($is_t_switch_active); + +} + +sub add_surrounding_indentation_to_begin_statement{ + # almost all of the objects add surrounding indentation to the 'begin' statements, + # but some (e.g HEADING) have their own method + my $self = shift; + + my $surroundingIndentation = ${$self}{surroundingIndentation}; + ${$self}{begin} =~ s/^(\h*)?/$surroundingIndentation/mg; # add indentation + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm new file mode 100644 index 00000000000..d85f4e24c31 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm @@ -0,0 +1,149 @@ +package LatexIndent::Item; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_items construct_list_of_items/; +our $itemCounter; +our $listOfItems = q(); +our $itemRegExp; + +sub construct_list_of_items{ + my $self = shift; + + # put together a list of the items + while( my ($item,$lookForThisItem)= each %{$masterSettings{itemNames}}){ + $listOfItems .= ($listOfItems eq "")?"$item":"|$item" if($lookForThisItem); + } + + # detail items in the log + $self->logger("List of items: $listOfItems (see itemNames)",'heading'); + + $itemRegExp = qr/ + ( + \\($listOfItems) + \h* + (\R*)? + ) + ( + (?: # cluster-only (), don't capture + (?! + (?:\\(?:$listOfItems)) # cluster-only (), don't capture + ). # any character, but not \\$item + )* + ) + (\R)? + /sx; + + + return; +} + +sub find_items{ + # no point carrying on if the list of items is empty + return if($listOfItems eq ""); + + my $self = shift; + + return unless ${$masterSettings{indentAfterItems}}{${$self}{name}}; + + # otherwise loop through the item names + $self->logger("Searching for items (see itemNames) in ${$self}{name} (see indentAfterItems)") if $is_t_switch_active; + $self->logger(Dumper(\%{$masterSettings{itemNames}})) if $is_t_switch_active; + + while(${$self}{body} =~ m/$itemRegExp\h*($trailingCommentRegExp)?/){ + + # log file output + $self->logger("Item found: $2",'heading') if $is_t_switch_active; + + ${$self}{body} =~ s/ + $itemRegExp(\h*)($trailingCommentRegExp)? + / + # create a new Item object + my $itemObject = LatexIndent::Item->new(begin=>$1, + body=>$4, + end=>q(), + name=>$2, + linebreaksAtEnd=>{ + begin=>$3?1:0, + body=>$5?1:0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"ItemStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"ItemFinishesWithLineBreak", + }, + modifyLineBreaksYamlName=>"items", + endImmediatelyFollowedByComment=>$5?0:($7?1:0), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($itemObject); + ${@{${$self}{children}}[-1]}{replacementText}.($6?$6:q()).($7?$7:q()); + /xseg; + } +} + + +sub create_unique_id{ + my $self = shift; + + $itemCounter++; + + ${$self}{id} = "$tokens{item}$itemCounter"; + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # the item body could hoover up line breaks; we do an additional check + ${${$self}{linebreaksAtEnd}}{body}=1 if(${$self}{body} =~ m/\R+$/s ); + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for headings (part, chapter, section, setc) + $self->find_heading; + + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces; + + # search for special begin/end + $self->find_special; + +} + +sub remove_line_breaks_begin{ + # the \item command can need a trailing white space if the line breaks have been removed after it and + # there is no white space + my $self = shift; + my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; + $self->logger("Removing linebreak at the end of begin (see $BodyStringLogFile)"); + ${$self}{begin} =~ s/\R*$//sx; + ${$self}{begin} .= " " unless(${$self}{begin} =~ m/\h$/s or ${$self}{body} =~ m/^\h/s or ${$self}{body} =~ m/^\R/s ); + ${$self}{linebreaksAtEnd}{begin} = 0; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/KeyEqualsValuesBraces.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/KeyEqualsValuesBraces.pm new file mode 100755 index 00000000000..41fcb981a15 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/KeyEqualsValuesBraces.pm @@ -0,0 +1,122 @@ +package LatexIndent::KeyEqualsValuesBraces; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_m_switch_active/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Command"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/construct_key_equals_values_regexp $key_equals_values_bracesRegExp $key_equals_values_bracesRegExpTrailingComment/; +our $key_equals_values_braces_Counter; +our $key_equals_values_bracesRegExp; +our $key_equals_values_bracesRegExpTrailingComment; + +sub construct_key_equals_values_regexp{ + my $self = shift; + + # grab the arguments regexp + my $optAndMandRegExp = $self->get_arguments_regexp; + + # blank line token + my $blankLineToken = $tokens{blanklines}; + + # store the regular expresssion for matching and replacing + $key_equals_values_bracesRegExp = qr/ + ( + (?: + (?:(?logger("= found on own line in ${$self}{name}, adding indentation") if $is_t_switch_active; + ${$self}{begin} =~ s/=/${$self}{indentation}=/s; + } +} + +sub check_linebreaks_before_equals{ + # check if -m switch is active + return unless $is_m_switch_active; + + my $self = shift; + + # linebreaks *infront* of = symbol + if(${$self}{begin} =~ /\R\h*=/s){ + if(defined ${$self}{EqualsStartsOnOwnLine} and ${$self}{EqualsStartsOnOwnLine}==-1){ + $self->logger("Removing linebreak before = symbol in ${$self}{name} (see EqualsStartsOnOwnLine)") if $is_t_switch_active; + ${$self}{begin} =~ s/(\R|\h)*=/=/s; + } + } else { + if(defined ${$self}{EqualsStartsOnOwnLine} and ${$self}{EqualsStartsOnOwnLine}==1){ + $self->logger("Adding a linebreak before = symbol for ${$self}{name} (see EqualsStartsOnOwnLine)") if $is_t_switch_active; + ${$self}{begin} =~ s/=/\n=/s; + } elsif(defined ${$self}{EqualsStartsOnOwnLine} and ${$self}{EqualsStartsOnOwnLine}==2){ + $self->logger("Adding a % linebreak immediately before = symbol for ${$self}{name} (see EqualsStartsOnOwnLine)") if $is_t_switch_active; + ${$self}{begin} =~ s/\h*=/%\n=/s; + } + } + return; +} + +sub create_unique_id{ + my $self = shift; + + $key_equals_values_braces_Counter++; + ${$self}{id} = "$tokens{key_equals_values_braces}$key_equals_values_braces_Counter"; + return; +} + +sub get_replacement_text{ + my $self = shift; + + # the replacement text for a key = {value} needes to accomodate the leading [ OR { OR % OR , OR any combination thereof + $self->logger("Custom replacement text routine for ${$self}{name}") if $is_t_switch_active; + ${$self}{replacementText} = ${$self}{beginningbit}.${$self}{id}; + delete ${$self}{beginningbit}; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm new file mode 100644 index 00000000000..89cffa58a81 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm @@ -0,0 +1,166 @@ +package LatexIndent::LogFile; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/%switches/; +use FindBin; +use File::Basename; # to get the filename and directory path +use Exporter qw/import/; +our @EXPORT_OK = qw/logger output_logfile processSwitches/; +our @logFileNotes; + +# log file methods +# log file methods +# log file methods +# reference: http://stackoverflow.com/questions/6736998/help-calling-a-sub-routine-from-a-perl-module-and-printing-to-logfile + +sub logger{ + shift; + my $line = shift; + my $infoLevel = shift; + push(@logFileNotes,{line=>$line,level=>$infoLevel?$infoLevel:'default'}); + return +} + +sub processSwitches{ + my $self = shift; + + # details of the script to log file + $self->logger("$FindBin::Script version 3.0, a script to indent .tex files",'heading'); + $self->logger("$FindBin::Script lives here: $FindBin::RealBin/"); + + # time the script is used + my $time = localtime(); + $self->logger("$time"); + + if(scalar(@ARGV) < 1 or $switches{showhelp}) { + print < + used to specify the location of backup files and indent.log + -m, --modifylinebreaks + modify linebreaks before, during, and at the end of code blocks; + trailing comments can also be added using this feature +ENDQUOTE + ; + exit(2); +} + + # log the switches from the user + $self->logger('Processing switches','heading'); + + # check on the trace mode switch (should be turned on if ttrace mode active) + $switches{trace} = $switches{ttrace} ? 1 : $switches{trace}; + + # output details of switches + $self->logger('-t|--trace: Trace mode active (you have used either -t or --trace)') if($switches{trace} and !$switches{ttrace}); + $self->logger('-tt|--ttrace: TTrace mode active (you have used either -tt or --ttrace)') if($switches{tracingModeVeryDetailed}); + $self->logger('-s|--silent: Silent mode active (you have used either -s or --silent)') if($switches{silentMode}); + $self->logger('-d|--onlydefault: Only defaultSettings.yaml will be used (you have used either -d or --onlydefault)') if($switches{onlyDefault}); + $self->logger("-w|--overwrite: Overwrite mode active, will make a back up of ${$self}{fileName} first") if($switches{overwrite}); + $self->logger("-l|--localSettings: Read localSettings YAML file") if($switches{readLocalSettings}); + $self->logger("-o|--outputfile: output to file") if($switches{outputToFile}); + $self->logger("-m|--modifylinebreaks: modify line breaks") if($switches{modifyLineBreaks}); + $self->logger("-g|--logfile: logfile name") if($switches{logFileName}); + $self->logger("-c|--cruft: cruft directory") if($switches{cruftDirectory}); + + # check if overwrite and outputfile are active similtaneously + if($switches{overwrite} and $switches{outputToFile}){ + $self->logger("Options check",'heading'); + $self->logger("You have called latexindent.pl with both -o and -w"); + $self->logger("-o (output to file) will take priority, and -w (over write) will be ignored"); + $switches{overwrite}=0; + } + + # cruft directory + ${$self}{cruftDirectory} = $switches{cruftDirectory}||(dirname ${$self}{fileName}); + die "Could not find directory ${$self}{cruftDirectory}\nExiting, no indentation done." if(!(-d ${$self}{cruftDirectory})); + my $logfileName = $switches{logFileName}||"indent.log"; + $self->logger("Directory for backup files and $logfileName: ${$self}{cruftDirectory}",'heading'); + + # output location of modules + if($FindBin::Script eq 'latexindent.pl' or ($FindBin::Script eq 'latexindent.exe' and $switches{trace} )) { + my @listOfModules = ('FindBin', 'YAML::Tiny', 'File::Copy', 'File::Basename', 'Getopt::Long','File::HomeDir'); + $self->logger("Perl modules are being loaded from the following directories:",'heading'); + foreach my $moduleName (@listOfModules) { + (my $file = $moduleName) =~ s|::|/|g; + require $file . '.pm'; + $self->logger($INC{$file .'.pm'}); + } + $self->logger("Latex Indent perl modules are being loaded from, for example:",'heading'); + (my $file = 'LatexIndent::Document') =~ s|::|/|g; + require $file . '.pm'; + $self->logger($INC{$file .'.pm'}); + } + return; +} + +sub output_logfile{ + my $self = shift; + my $logfile; + my $logfileName = $switches{logFileName}||"indent.log"; + + open($logfile,">","${$self}{cruftDirectory}/$logfileName") or die "Can't open $logfileName"; + + # put the final line in the logfile + $self->logger("${$masterSettings{logFilePreferences}}{endLogFileWith}",'heading'); + + # github info line + $self->logger("Please direct all communication/issues to: ",'heading') if ${$masterSettings{logFilePreferences}}{showGitHubInfoFooter}; + $self->logger("https://github.com/cmhughes/latexindent.pl") if ${$masterSettings{logFilePreferences}}{showGitHubInfoFooter}; + + # output the logfile + foreach my $line (@logFileNotes){ + if(${$line}{level} eq 'heading'){ + print $logfile ${$line}{line},"\n"; + } elsif(${$line}{level} eq 'default') { + # add tabs to the beginning of lines + # for default logfile lines + ${$line}{line} =~ s/^/\t/mg; + print $logfile ${$line}{line},"\n"; + } + } + + close($logfile); +} + + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/MandatoryArgument.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/MandatoryArgument.pm new file mode 100644 index 00000000000..172e002eda4 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/MandatoryArgument.pm @@ -0,0 +1,130 @@ +package LatexIndent::MandatoryArgument; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_mandatory_arguments get_mand_arg_reg_exp/; +our $mandatoryArgumentCounter; + +sub find_mandatory_arguments{ + my $self = shift; + + my $mandArgRegExp = $self->get_mand_arg_reg_exp; + + # pick out the mandatory arguments + while(${$self}{body} =~ m/$mandArgRegExp\h*($trailingCommentRegExp)*(.*)/s){ + # log file output + $self->logger("Mandatory argument found, body in ${$self}{name}",'heading') if $is_t_switch_active; + $self->logger("(last argument)") if($9 eq '' and $is_t_switch_active); + + ${$self}{body} =~ s/ + $mandArgRegExp(\h*)($trailingCommentRegExp)*(.*) + / + # create a new Mandatory Argument object + my $mandatoryArg = LatexIndent::MandatoryArgument->new(begin=>$1, + name=>${$self}{name}.":mandatoryArgument", + nameForIndentationSettings=>${$self}{parent}, + parent=>${$self}{parent}, + body=>$3.($4?$4:q()), + end=>$5, + linebreaksAtEnd=>{ + begin=>$2?1:0, + body=>$4?1:0, + end=>$7?1:0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"LCuBStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"MandArgBodyStartsOnOwnLine", + # end statements + EndStartsOnOwnLine=>"RCuBStartsOnOwnLine", + # after end statements + EndFinishesWithLineBreak=>"RCuBFinishesWithLineBreak", + }, + horizontalTrailingSpace=>$6?$6:q(), + modifyLineBreaksYamlName=>"mandatoryArguments", + # the last argument (determined by $10 eq '') needs information from the argument container object + endImmediatelyFollowedByComment=>($10 eq '')?${$self}{endImmediatelyFollowedByComment}:($9?1:0), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($mandatoryArg); + ${@{${$self}{children}}[-1]}{replacementText}.($8?$8:q()).($9?$9:q()).($10?$10:q()); + /xseg; + $self->wrap_up_tasks; + } + } + +sub create_unique_id{ + my $self = shift; + + $mandatoryArgumentCounter++; + ${$self}{id} = "$tokens{mandatoryArgument}$mandatoryArgumentCounter"; + return; +} + +sub get_mand_arg_reg_exp{ + + my $mandArgRegExp = qr/ + (?find_ifelsefi; + + # search for special begin/end + $self->find_special; + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm new file mode 100644 index 00000000000..bcfb2336264 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm @@ -0,0 +1,174 @@ +package LatexIndent::ModifyLineBreaks; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use Data::Dumper; +use Exporter qw/import/; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +our @EXPORT_OK = qw/modify_line_breaks_body modify_line_breaks_end adjust_line_breaks_end_parent remove_line_breaks_begin/; +our @allObjects; + +sub modify_line_breaks_body{ + my $self = shift; + + # add a line break after \begin{statement} if appropriate + if(defined ${$self}{BodyStartsOnOwnLine}){ + my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; + if(${$self}{BodyStartsOnOwnLine}>=1 and !${$self}{linebreaksAtEnd}{begin}){ + if(${$self}{BodyStartsOnOwnLine}==1){ + # modify the begin statement + $self->logger("Adding a linebreak at the end of begin, ${$self}{begin} (see $BodyStringLogFile)") if $is_t_switch_active; + ${$self}{begin} .= "\n"; + ${$self}{linebreaksAtEnd}{begin} = 1; + $self->logger("Removing leading space from body of ${$self}{name} (see $BodyStringLogFile)") if $is_t_switch_active; + ${$self}{body} =~ s/^\h*//; + } elsif(${$self}{BodyStartsOnOwnLine}==2){ + # by default, assume that no trailing comment token is needed + my $trailingCommentToken = q(); + if(${$self}{body} !~ m/^\h*$trailingCommentRegExp/s){ + # modify the begin statement + $self->logger("Adding a % at the end of begin, ${$self}{begin}, followed by a linebreak ($BodyStringLogFile == 2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + ${$self}{begin} =~ s/\h*$//; + ${$self}{begin} .= "$trailingCommentToken\n"; + ${$self}{linebreaksAtEnd}{begin} = 1; + $self->logger("Removing leading space from body of ${$self}{name} (see $BodyStringLogFile)") if $is_t_switch_active; + ${$self}{body} =~ s/^\h*//; + } else { + $self->logger("Even though $BodyStringLogFile == 2, ${$self}{begin} already finishes with a %, so not adding another.") if $is_t_switch_active; + } + } + } elsif (${$self}{BodyStartsOnOwnLine}==-1 and ${$self}{linebreaksAtEnd}{begin}){ + # remove line break *after* begin, if appropriate + $self->remove_line_breaks_begin; + } + } + } + +sub remove_line_breaks_begin{ + my $self = shift; + my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; + $self->logger("Removing linebreak at the end of begin (see $BodyStringLogFile)") if $is_t_switch_active; + ${$self}{begin} =~ s/\R*$//sx; + ${$self}{linebreaksAtEnd}{begin} = 0; +} + +sub modify_line_breaks_end{ + my $self = shift; + + # possibly modify line break *before* \end{statement} + if(defined ${$self}{EndStartsOnOwnLine}){ + my $EndStringLogFile = ${$self}{aliases}{EndStartsOnOwnLine}||"EndStartsOnOwnLine"; + if(${$self}{EndStartsOnOwnLine}>=1 and !${$self}{linebreaksAtEnd}{body}){ + # add a line break after body, if appropriate + $self->logger("Adding a linebreak at the end of body (see $EndStringLogFile)") if $is_t_switch_active; + + # by default, assume that no trailing comment token is needed + my $trailingCommentToken = q(); + if(${$self}{EndStartsOnOwnLine}==2){ + $self->logger("Adding a % immediately after body of ${$self}{name} ($EndStringLogFile==2)") if $is_t_switch_active; + $trailingCommentToken = "%".$self->add_comment_symbol; + ${$self}{body} =~ s/\h*$//s; + } + + # modified end statement + if(${$self}{body} =~ m/^\h*$/s and ${$self}{BodyStartsOnOwnLine} >=1 ){ + ${$self}{linebreaksAtEnd}{body} = 0; + } else { + ${$self}{body} .= "$trailingCommentToken\n"; + ${$self}{linebreaksAtEnd}{body} = 1; + } + } elsif (${$self}{EndStartsOnOwnLine}==-1 and ${$self}{linebreaksAtEnd}{body}){ + # remove line break *after* body, if appropriate + + # check to see that body does *not* finish with blank-line-token, + # if so, then don't remove that final line break + if(${$self}{body} !~ m/$tokens{blanklines}$/s){ + $self->logger("Removing linebreak at the end of body (see $EndStringLogFile)") if $is_t_switch_active; + ${$self}{body} =~ s/\R*$//sx; + ${$self}{linebreaksAtEnd}{body} = 0; + } else { + $self->logger("Blank line token found at end of body (${$self}{name}), see preserveBlankLines, not removing line break before ${$self}{end}") if $is_t_switch_active; + } + } + } + + # possibly modify line break *after* \end{statement} + if(defined ${$self}{EndFinishesWithLineBreak} + and ${$self}{EndFinishesWithLineBreak}>=1 + and !${$self}{linebreaksAtEnd}{end}){ + my $EndStringLogFile = ${$self}{aliases}{EndFinishesWithLineBreak}||"EndFinishesWithLineBreak"; + if(${$self}{EndFinishesWithLineBreak}==1){ + $self->logger("Adding a linebreak at the end of ${$self}{end} (see $EndStringLogFile)") if $is_t_switch_active; + ${$self}{linebreaksAtEnd}{end} = 1; + + # modified end statement + ${$self}{replacementText} .= "\n"; + } elsif(${$self}{EndFinishesWithLineBreak}==2){ + if(${$self}{endImmediatelyFollowedByComment}){ + # no need to add a % if one already exists + $self->logger("Even though $EndStringLogFile == 2, ${$self}{end} is immediately followed by a %, so not adding another; not adding line break.") if $is_t_switch_active; + } else { + # otherwise, create a trailing comment, and tack it on + $self->logger("Adding a % immediately after, ${$self}{end} ($EndStringLogFile==2)") if $is_t_switch_active; + my $trailingCommentToken = "%".$self->add_comment_symbol; + ${$self}{end} =~ s/\h*$//s; + ${$self}{replacementText} .= "$trailingCommentToken\n"; + ${$self}{linebreaksAtEnd}{end} = 1; + } + } + } + +} + +sub adjust_line_breaks_end_parent{ + # when a parent object contains a child object, the line break + # at the end of the parent object can become messy + return unless $is_m_switch_active; + + my $self = shift; + + # most recent child object + my $child = @{${$self}{children}}[-1]; + + # adjust parent linebreaks information + if(${$child}{linebreaksAtEnd}{end} and ${$self}{body} =~ m/${$child}{replacementText}\h*\R*$/s and !${$self}{linebreaksAtEnd}{body}){ + $self->logger("ID: ${$child}{id}") if($is_t_switch_active); + $self->logger("${$child}{begin}...${$child}{end} is found at the END of body of parent, ${$self}{name}, avoiding a double line break:") if($is_t_switch_active); + $self->logger("adjusting ${$self}{name} linebreaksAtEnd{body} to be 1") if($is_t_switch_active); + ${$self}{linebreaksAtEnd}{body}=1; + } + + # the modify line switch can adjust line breaks, so we need another check, + # see for example, test-cases/environments/environments-remove-line-breaks-trailing-comments.tex + if(defined ${$child}{linebreaksAtEnd}{body} + and !${$child}{linebreaksAtEnd}{body} + and ${$child}{body} =~ m/\R(?:$trailingCommentRegExp\h*)?$/s ){ + # log file information + $self->logger("Undisclosed line break at the end of body of ${$child}{name}: '${$child}{end}'") if($is_t_switch_active); + $self->logger("Adding a linebreak at the end of body for ${$child}{id}") if($is_t_switch_active); + + # make the adjustments + ${$child}{body} .= "\n"; + ${$child}{linebreaksAtEnd}{body}=1; + } + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/NamedGroupingBracesBrackets.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/NamedGroupingBracesBrackets.pm new file mode 100755 index 00000000000..ea2c5323cf3 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/NamedGroupingBracesBrackets.pm @@ -0,0 +1,71 @@ +package LatexIndent::NamedGroupingBracesBrackets; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @ISA = "LatexIndent::Command"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/construct_grouping_braces_brackets_regexp $grouping_braces_regexp $grouping_braces_regexpTrailingComment/; +our $groupingBracesCounter; +our $grouping_braces_regexp; +our $grouping_braces_regexpTrailingComment; + +sub construct_grouping_braces_brackets_regexp{ + my $self = shift; + + # grab the arguments regexp + my $optAndMandRegExp = $self->get_arguments_regexp; + + # store the regular expresssion for matching and replacing + $grouping_braces_regexp = qr/ + ( + \h|\R|\{|\[|\$|\) + ) + ( + [0-9a-zA-Z@\*><]+? # lowercase|uppercase letters, @, *, numbers, forward slash, dots + ) # $2 name + (\h*) # $3 h-space + (\R*) # $4 linebreaks + ($optAndMandRegExp) # $5 mand|opt arguments (at least one) + (\R)? # $8 linebreak + /sx; + + # something {value} grouping braces with trailing comment + $grouping_braces_regexpTrailingComment = qr/$grouping_braces_regexp\h*((?:$trailingCommentRegExp\h*)*)?/; + +} + +sub create_unique_id{ + my $self = shift; + + $groupingBracesCounter++; + ${$self}{id} = "$tokens{groupingBraces}$groupingBracesCounter"; + return; +} + +sub get_replacement_text{ + my $self = shift; + + # the replacement text for a key = {value} needes to accomodate the leading [ OR { OR % OR , OR any combination thereof + $self->logger("Custom replacement text routine for ${$self}{name}") if $is_t_switch_active; + ${$self}{replacementText} = ${$self}{beginningbit}.${$self}{id}; + delete ${$self}{beginningbit}; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/OptionalArgument.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/OptionalArgument.pm new file mode 100644 index 00000000000..b949e9b7e92 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/OptionalArgument.pm @@ -0,0 +1,115 @@ +package LatexIndent::OptionalArgument; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_optional_arguments/; +our $optionalArgumentCounter; +our $optArgRegExp = qr/ + (?logger("Optional argument found, body in ${$self}{name}",'heading') if $is_t_switch_active; + $self->logger("(last argument)") if($9 eq '' and $is_t_switch_active); + + ${$self}{body} =~ s/ + $optArgRegExp(\h*)($trailingCommentRegExp)*(.*) + / + # create a new Optional Argument object + my $optionalArg = LatexIndent::OptionalArgument->new(begin=>$1, + name=>${$self}{name}.":optionalArgument", + nameForIndentationSettings=>${$self}{parent}, + parent=>${$self}{parent}, + body=>$3.($4?$4:q()), + end=>$5, + linebreaksAtEnd=>{ + begin=>$2?1:0, + body=>$4?1:0, + end=>$7?1:0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"LSqBStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"OptArgBodyStartsOnOwnLine", + # end statements + EndStartsOnOwnLine=>"RSqBStartsOnOwnLine", + # after end statements + EndFinishesWithLineBreak=>"RSqBFinishesWithLineBreak", + }, + modifyLineBreaksYamlName=>"optionalArguments", + # the last argument (determined by $10 eq '') needs information from the argument container object + endImmediatelyFollowedByComment=>($10 eq '')?${$self}{endImmediatelyFollowedByComment}:($9?1:0), + horizontalTrailingSpace=>$6?$6:q(), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($optionalArg); + ${@{${$self}{children}}[-1]}{replacementText}.($8?$8:q()).($9?$9:q()).($10?$10:q()); + /xseg; + } + } + +sub get_object_attribute_for_indentation_settings{ + my $self = shift; + + return ${$self}{modifyLineBreaksYamlName}; +} + +sub create_unique_id{ + my $self = shift; + + $optionalArgumentCounter++; + ${$self}{id} = "$tokens{optionalArgument}$optionalArgumentCounter"; + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for special begin/end + $self->find_special; + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm new file mode 100644 index 00000000000..a3a62dd3f56 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm @@ -0,0 +1,64 @@ +package LatexIndent::Preamble; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our $preambleCounter; + +sub create_unique_id{ + my $self = shift; + + $preambleCounter++; + ${$self}{id} = "$tokens{preamble}$preambleCounter$tokens{endOfToken}"; + return; +} + +sub get_replacement_text{ + my $self = shift; + + # the replacement text for preamble needs to put the \\begin{document} back in + $self->logger("Custom replacement text routine for preamble ${$self}{name}"); + ${$self}{replacementText} = ${$self}{id}.${$self}{afterbit}; + delete ${$self}{afterbit}; +} + +sub indent{ + # preamble doesn't receive any additional indentation + return; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # search for environments + $self->find_environments; + + # search for ifElseFi blocks + $self->find_ifelsefi; + + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces if(!$masterSettings{preambleCommandsBeforeEnvironments}); + + # search for special begin/end + $self->find_special; + + +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/RoundBrackets.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/RoundBrackets.pm new file mode 100644 index 00000000000..f320d007fa2 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/RoundBrackets.pm @@ -0,0 +1,100 @@ +package LatexIndent::RoundBrackets; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_round_brackets/; +our $roundBracketCounter; +our $roundBracketRegExp = qr/ + (?new(begin=>$1, + name=>${$self}{name}.":roundBracket", + nameForIndentationSettings=>${$self}{parent}, + parent=>${$self}{parent}, + body=>$3.($4?$4:q()), + end=>$5, + linebreaksAtEnd=>{ + begin=>$2?1:0, + body=>$4?1:0, + end=>$7?1:0, + }, + modifyLineBreaksYamlName=>"roundBracket", + # the last argument (determined by $10 eq '') needs information from the argument container object + endImmediatelyFollowedByComment=>($10 eq '')?${$self}{endImmediatelyFollowedByComment}:($9?1:0), + horizontalTrailingSpace=>$6?$6:q(), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($roundBracket); + ${@{${$self}{children}}[-1]}{replacementText}.($8?$8:q()).($9?$9:q()).($10?$10:q()); + /xseg; + } + } + +sub get_object_attribute_for_indentation_settings{ + my $self = shift; + + return ${$self}{modifyLineBreaksYamlName}; +} + +sub create_unique_id{ + my $self = shift; + + $roundBracketCounter++; + ${$self}{id} = "$tokens{roundBracket}$roundBracketCounter"; + return; +} + +sub tasks_particular_to_each_object{ + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm new file mode 100644 index 00000000000..ba7b905b492 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm @@ -0,0 +1,184 @@ +package LatexIndent::Special; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/find_special construct_special_begin/; +our $specialCounter; +our $specialBegins = q(); +our $specialAllMatchesRegExp = q(); +our %individualSpecialRegExps; + +sub construct_special_begin{ + my $self = shift; + + # put together a list of the begin terms in special + while( my ($specialName,$BeginEnd)= each %{$masterSettings{specialBeginEnd}}){ + # only append the regexps if lookForThis is 1 + $specialBegins .= ($specialBegins eq ""?q():"|").${$BeginEnd}{begin} if(${$BeginEnd}{lookForThis}); + } + + # put together a list of the begin terms in special + while( my ($specialName,$BeginEnd)= each %{$masterSettings{specialBeginEnd}}){ + + # only append the regexps if lookForThis is 1 + if(${$BeginEnd}{lookForThis}){ + # the beginning parts + $specialBegins .= ($specialBegins eq ""?q():"|").${$BeginEnd}{begin}; + + # the overall regexp + $specialAllMatchesRegExp .= ($specialAllMatchesRegExp eq ""?q():"|") + .qr/ + ${$BeginEnd}{begin} + (?: # cluster-only (), don't capture + (?! + (?:$specialBegins) # cluster-only (), don't capture + ). # any character, but not anything in $specialBegins + )*? + ${$BeginEnd}{end} + /sx; + + # store the individual special regexp + $individualSpecialRegExps{$specialName} = qr/ + ( + ${$BeginEnd}{begin} + \h* + (\R*)? + ) + ( + (?: # cluster-only (), don't capture + (?! + (?:$specialBegins) # cluster-only (), don't capture + ). # any character, but not anything in $specialBegins + )*? + (\R*)? + ) + ( + ${$BeginEnd}{end} + ) + (\h*) + (\R)? + /sx + + } else { + $self->logger("The special regexps won't include anything from $specialName (see lookForThis)",'heading') if $is_t_switch_active ; + } + } + + # move $$ to the beginning + if($specialBegins =~ m/\|\\\$\\\$/){ + $specialBegins =~ s/\|(\\\$\\\$)//; + $specialBegins = $1."|".$specialBegins; + } + + # info to the log file + $self->logger("The special beginnings regexp is: $specialBegins (see specialBeginEnd)",'heading') if $is_t_switch_active; + + # overall special regexp + $self->logger("The overall special regexp is: $specialAllMatchesRegExp(see specialBeginEnd)",'heading') if $is_t_switch_active; + + } + +sub find_special{ + my $self = shift; + + # no point carrying on if the list of specials is empty + return if($specialBegins eq ""); + + # otherwise loop through the special begin/end + $self->logger("Searching for special begin/end (see specialBeginEnd)") if $is_t_switch_active ; + $self->logger(Dumper(\%{$masterSettings{specialBeginEnd}})) if $is_tt_switch_active; + + # keep looping as long as there is a special match of some kind + while(${$self}{body} =~ m/$specialAllMatchesRegExp/sx){ + + # loop through each special match + while( my ($specialName,$BeginEnd)= each %{$masterSettings{specialBeginEnd}}){ + + # log file + if(${$BeginEnd}{lookForThis}){ + $self->logger("Looking for $specialName",'heading') if $is_t_switch_active ; + } else { + $self->logger("Not looking for $specialName (see lookForThis)",'heading') if $is_t_switch_active ; + next; + } + + # the regexp + my $specialRegExp = $individualSpecialRegExps{$specialName}; + + while(${$self}{body} =~ m/$specialRegExp(\h*)($trailingCommentRegExp)?/){ + + # global substitution + ${$self}{body} =~ s/ + $specialRegExp(\h*)($trailingCommentRegExp)? + / + # log file output + $self->logger("special found: $specialName",'heading') if $is_t_switch_active; + + # create a new special object + my $specialObject = LatexIndent::Special->new(begin=>$1, + body=>$3, + end=>$5, + name=>$specialName, + linebreaksAtEnd=>{ + begin=>$2?1:0, + body=>$4?1:0, + end=>$7?1:0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"SpecialBeginStartsOnOwnLine", + # body statements + BodyStartsOnOwnLine=>"SpecialBodyStartsOnOwnLine", + # end statements + EndStartsOnOwnLine=>"SpecialEndStartsOnOwnLine", + # after end statements + EndFinishesWithLineBreak=>"SpecialEndFinishesWithLineBreak", + }, + modifyLineBreaksYamlName=>"specialBeginEnd", + endImmediatelyFollowedByComment=>$7?0:($9?1:0), + horizontalTrailingSpace=>$6?$6:q(), + ); + + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($specialObject); + ${@{${$self}{children}}[-1]}{replacementText}.($8?$8:q()).($9?$9:q()); + /xseg; + + $self->wrap_up_tasks; + } + } + } +} + + +sub create_unique_id{ + my $self = shift; + + $specialCounter++; + + ${$self}{id} = "$tokens{special}$specialCounter"; + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Switches.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Switches.pm new file mode 100644 index 00000000000..a5b07936a6d --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Switches.pm @@ -0,0 +1,37 @@ +package LatexIndent::Switches; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use Exporter qw/import/; +our @EXPORT_OK = qw/%switches storeSwitches $is_m_switch_active $is_t_switch_active $is_tt_switch_active/; +our %switches; +our $is_m_switch_active; +our $is_t_switch_active; +our $is_tt_switch_active; + +sub storeSwitches{ + my $self = shift; + + # copy document switches into hash local to this module + %switches = %{${$self}{switches}}; + $is_m_switch_active = defined $switches{modifyLineBreaks}?$switches{modifyLineBreaks}: 0; + $is_t_switch_active = defined $switches{trace}?$switches{trace}: 0; + $is_tt_switch_active = defined $switches{ttrace}?$switches{ttrace}: 0; + $is_t_switch_active = $is_tt_switch_active ? $is_tt_switch_active : $is_t_switch_active; + delete ${$self}{switches}; + } +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm new file mode 100644 index 00000000000..8a9a100dc26 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm @@ -0,0 +1,68 @@ +package LatexIndent::Tokens; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use Exporter qw/import/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +our @EXPORT_OK = qw/token_check %tokens/; + +# each of the tokens begins the same way -- this is exploited during the hidden Children routine +my $beginningToken = "LTXIN-TK-"; +my $ifelsefiSpecial = "!-!"; + +# the %tokens hash is passed around many modules +our %tokens = ( + environment=>$beginningToken."ENVIRONMENT", + ifelsefiSpecial=>$ifelsefiSpecial, + ifelsefi=>$ifelsefiSpecial.$beginningToken."IFELSEFI", + item=>$beginningToken."ITEMS", + trailingComment=>"latexindenttrailingcomment", + blanklines=>$beginningToken."blank-line", + arguments=>$beginningToken."ARGUMENTS", + optionalArgument=>$beginningToken."OPTIONAL-ARGUMENT", + mandatoryArgument=>$beginningToken."MANDATORY-ARGUMENT", + roundBracket=>$beginningToken."ROUND-BRACKET", + verbatim=>$beginningToken."VERBATIM", + command=>$beginningToken."COMMAND", + key_equals_values_braces=>$beginningToken."KEY-VALUE-BRACES", + groupingBraces=>$beginningToken."GROUPING-BRACES", + unNamedgroupingBraces=>$beginningToken."UN-NAMED-GROUPING-BRACES", + special=>$beginningToken."SPECIAL", + heading=>$beginningToken."HEADING", + filecontents=>$beginningToken."FILECONTENTS", + preamble=>$beginningToken."preamble", + beginOfToken=>$beginningToken, + doubleBackSlash=>$beginningToken."DOUBLEBACKSLASH", + alignmentBlock=>$beginningToken."ALIGNMENTBLOCK", + endOfToken=>"-END", + ); + +sub token_check{ + my $self = shift; + + $self->logger("Token check",'heading') if $is_t_switch_active; + # we use tokens for trailing comments, environments, commands, etc, so check that they're not in the body + foreach( keys %tokens){ + while(${$self}{body} =~ m/$tokens{$_}/si){ + $self->logger("Found $tokens{$_} within body, updating replacement token to $tokens{$_}-LIN") if($is_t_switch_active); + $tokens{$_} .= "-LIN"; + } + } +} + + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/TrailingComments.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/TrailingComments.pm new file mode 100644 index 00000000000..f8987d271f1 --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/TrailingComments.pm @@ -0,0 +1,112 @@ +package LatexIndent::TrailingComments; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @EXPORT_OK = qw/remove_trailing_comments put_trailing_comments_back_in $trailingCommentRegExp add_comment_symbol construct_trailing_comment_regexp/; +our @trailingComments; +our $commentCounter = 0; +our $trailingCommentRegExp; + +sub construct_trailing_comment_regexp{ + $trailingCommentRegExp = qr/(?$tokens{trailingComment}.$commentCounter.$tokens{endOfToken},value=>q()}); + + # log file info + $self->logger("Updating trailing comment array",'heading')if $is_t_switch_active; + $self->logger(Dumper(\@trailingComments),'ttrace') if($is_tt_switch_active); + + # the returned value + return $tokens{trailingComment}.$commentCounter.$tokens{endOfToken}; +} + +sub remove_trailing_comments{ + my $self = shift; + $self->logger("Storing trailing comments",'heading')if $is_t_switch_active; + + # perform the substitution + ${$self}{body} =~ s/ + (?$tokens{trailingComment}.$commentCounter.$tokens{endOfToken},value=>$1}); + + # replace comment with dummy text + "%".$tokens{trailingComment}.$commentCounter.$tokens{endOfToken}; + /xsmeg; + if(@trailingComments){ + $self->logger("Trailing comments stored in:") if($is_t_switch_active); + $self->logger(Dumper(\@trailingComments)) if($is_t_switch_active); + } else { + $self->logger("No trailing comments found") if($is_t_switch_active); + } + return; +} + +sub put_trailing_comments_back_in{ + my $self = shift; + return unless( @trailingComments > 0 ); + + $self->logger("Returning trailing comments to body",'heading')if $is_t_switch_active; + + # loop through trailing comments in reverse so that, for example, + # latexindenttrailingcomment1 doesn't match the first + # part of latexindenttrailingcomment18, which would result in an 8 left over (bad) + while( my $comment = pop @trailingComments){ + my $trailingcommentID = ${$comment}{id}; + my $trailingcommentValue = ${$comment}{value}; + if(${$self}{body} =~ m/%$trailingcommentID + ( + (?! # not immediately preceeded by + (?logger("Comment not at end of line $trailingcommentID, moving it to end of line")if $is_t_switch_active; + ${$self}{body} =~ s/%$trailingcommentID(.*)$/$1%$trailingcommentValue/m; + } else { + ${$self}{body} =~ s/%$trailingcommentID/%$trailingcommentValue/; + } + $self->logger("replace %$trailingcommentID with %$trailingcommentValue") if($is_t_switch_active); + } + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/UnNamedGroupingBracesBrackets.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/UnNamedGroupingBracesBrackets.pm new file mode 100644 index 00000000000..268f5b5adfa --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/UnNamedGroupingBracesBrackets.pm @@ -0,0 +1,135 @@ +package LatexIndent::UnNamedGroupingBracesBrackets; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Exporter qw/import/; +our @ISA = "LatexIndent::Command"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/construct_unnamed_grouping_braces_brackets_regexp $un_named_grouping_braces_RegExp $un_named_grouping_braces_RegExp_trailing_comment/; +our $unNamedGroupingBracesCounter; +our $un_named_grouping_braces_RegExp; +our $un_named_grouping_braces_RegExp_trailing_comment; + +sub construct_unnamed_grouping_braces_brackets_regexp{ + my $self = shift; + + # grab the arguments regexp + my $optAndMandRegExp = $self->get_arguments_regexp; + + # blank line token + my $blankLineToken = $tokens{blanklines}; + + # for example #1 #2, etc + my $numberedArgRegExp = $self->get_numbered_arg_regexp; + + # store the regular expresssion for matching and replacing + $un_named_grouping_braces_RegExp = qr/ + # NOT + (?! + (?: + (?:(?logger("Custom replacement text routine for ${$self}{name}") if $is_t_switch_active; + + # the un-named object is a little special, as it doesn't have a name; as such, if there are blank lines before + # the braces/brackets, we have to insert them + # + # also, the argument reg-exp can pick up a leading comment (with line break), which needs to be put + # into the replacement text (see documentation/demonstrations/pstricks.tex and test-cases/unnamed-braces/unnamed.tex for example) + ${$self}{body} =~ s/(.*?)(\{|\[)/$2/s; + ${$self}{replacementText} = ${$self}{beginningbit}.($1 ne ''?$1:q()).${$self}{id}; + + # but now turn off the switch for linebreaksAtEnd{begin}, otherwise the first brace gets too much indentation + # (see, for example, test-cases/namedGroupingBracesBrackets/special-characters-minimal.tex) + ${${$self}{linebreaksAtEnd}}{begin} = 0; + $self->logger("Beginning bit is: ${$self}{beginningbit}") if($is_t_switch_active); + delete ${$self}{beginningbit}; +} + +sub check_for_blank_lines_at_beginning{ + # some examples can have blank line tokens at the beginning of the body, + # which can confuse the routine below + # See, for example, + # test-cases/namedGroupingBracesBrackets/special-characters-minimal-blank-lines-m-switch.tex + # compared to + # test-cases/namedGroupingBracesBrackets/special-characters-minimal-blank-lines-default.tex + my $self = shift; + + # blank line token + my $blankLineToken = $tokens{blanklines}; + + # if the body begins with 2 or more blank line tokens + if(${$self}{body} =~ m/^((?:$blankLineToken\R){2,})/s){ + + # remove them + ${$self}{body} =~ s/^((?:$blankLineToken\R)+)//s; + + # store + my $blank_line_tokens_at_beginning_of_body = $1; + + # and count them, for use after the indentation routine + ${$self}{blankLinesAtBeginning} = () = $blank_line_tokens_at_beginning_of_body =~ /$blankLineToken\R/sg + } + return; +} + +sub put_blank_lines_back_in_at_beginning{ + my $self = shift; + + # some bodies have blank lines at the beginning + if(${$self}{blankLinesAtBeginning}){ + for(my $i=0; $i<${$self}{blankLinesAtBeginning}; $i++){ + ${$self}{body} = $tokens{blanklines}.${$self}{body}; + } + } + return +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm new file mode 100644 index 00000000000..f3804aaf94d --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm @@ -0,0 +1,296 @@ +package LatexIndent::Verbatim; +# 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 +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# See http://www.gnu.org/licenses/. +# +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl +use strict; +use warnings; +use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::GetYamlSettings qw/%masterSettings/; +use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active/; +use Data::Dumper; +use Exporter qw/import/; +our @EXPORT_OK = qw/put_verbatim_back_in find_verbatim_environments find_noindent_block find_verbatim_commands put_verbatim_commands_back_in/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our $verbatimCounter; + +sub find_noindent_block{ + my $self = shift; + + # noindent block + $self->logger('looking for NOINDENTBLOCk environments (see noIndentBlock)','heading') if $is_t_switch_active; + $self->logger(Dumper(\%{$masterSettings{noIndentBlock}})) if($is_t_switch_active); + while( my ($noIndentBlock,$yesno)= each %{$masterSettings{noIndentBlock}}){ + if($yesno){ + $self->logger("looking for $noIndentBlock:$yesno environments") if $is_t_switch_active; + + my $noIndentRegExp = qr/ + ( + (?!<\\) + % + \h* # possible horizontal spaces + \\begin\{ + $noIndentBlock # environment name captured into $2 + \} # %* \begin{noindentblock} statement + ) + ( + .*? + ) # non-greedy match (body) + ( + (?!<\\) + % # % + \h* # possible horizontal spaces + \\end\{$noIndentBlock\} # \end{noindentblock} + ) # %* \end{} statement + /sx; + + while( ${$self}{body} =~ m/$noIndentRegExp/sx){ + + # create a new Environment object + my $noIndentBlock = LatexIndent::Verbatim->new( begin=>$1, + body=>$2, + end=>$3, + name=>$noIndentBlock, + ); + + # give unique id + $noIndentBlock->create_unique_id; + + # verbatim children go in special hash + ${$self}{verbatim}{${$noIndentBlock}{id}}=$noIndentBlock; + + # log file output + $self->logger("NOINDENTBLOCK environment found: $noIndentBlock") if $is_t_switch_active; + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/$noIndentRegExp/${$noIndentBlock}{id}/sx; + + $self->logger("replaced with ID: ${$noIndentBlock}{id}") if $is_t_switch_active; + } + } else { + $self->logger("*not* looking for $noIndentBlock as $noIndentBlock:$yesno") if $is_t_switch_active; + } + } + return; +} + +sub find_verbatim_environments{ + my $self = shift; + + # verbatim environments + $self->logger('looking for VERBATIM environments (see verbatimEnvironments)','heading') if $is_t_switch_active; + $self->logger(Dumper(\%{$masterSettings{verbatimEnvironments}})) if($is_t_switch_active); + while( my ($verbEnv,$yesno)= each %{$masterSettings{verbatimEnvironments}}){ + if($yesno){ + $self->logger("looking for $verbEnv:$yesno environments") if $is_t_switch_active; + + my $verbatimRegExp = qr/ + ( + \\begin\{ + $verbEnv # environment name captured into $1 + \} # \begin{} statement + ) + ( + .*? + ) # any character, but not \\begin + ( + \\end\{$verbEnv\}# \end{} statement + ) + /sx; + + while( ${$self}{body} =~ m/$verbatimRegExp/sx){ + + # create a new Environment object + my $verbatimBlock = LatexIndent::Verbatim->new( begin=>$1, + body=>$2, + end=>$3, + name=>$verbEnv, + ); + # give unique id + $verbatimBlock->create_unique_id; + + # verbatim children go in special hash + ${$self}{verbatim}{${$verbatimBlock}{id}}=$verbatimBlock; + + # log file output + $self->logger("VERBATIM environment found: $verbEnv") if $is_t_switch_active; + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/$verbatimRegExp/${$verbatimBlock}{id}/sx; + + $self->logger("replaced with ID: ${$verbatimBlock}{id}") if $is_t_switch_active; + } + } else { + $self->logger("*not* looking for $verbEnv as $verbEnv:$yesno") if $is_t_switch_active; + } + } + return; +} + +sub find_verbatim_commands{ + my $self = shift; + + # verbatim commands need to be treated separately to verbatim environments; + # note that, for example, we could quite reasonably have \lstinline!%!, which + # would need to be found *before* trailing comments have been removed. Similarly, + # verbatim commands need to be put back in *after* trailing comments have been put + # back in + $self->logger('looking for VERBATIM commands (see verbatimCommands)','heading'); + $self->logger(Dumper(\%{$masterSettings{verbatimCommands}})) if($is_tt_switch_active); + while( my ($verbCommand,$yesno)= each %{$masterSettings{verbatimCommands}}){ + if($yesno){ + $self->logger("looking for $verbCommand:$yesno Commands") if $is_t_switch_active; + + my $verbatimCommandRegExp = qr/ + ( + \\$verbCommand + \h* + ) # name of command into $1 + ( + \[ + (?: + (?! + (?:(?new( begin=>$1.($2?$2:q()).$3, + body=>$4, + end=>$3, + name=>$verbCommand, + optArg=>$2?$2:q(), + ); + # give unique id + $verbatimCommand->create_unique_id; + + # output, if desired + $self->logger(Dumper($verbatimCommand),'ttrace') if($is_tt_switch_active); + + # verbatim children go in special hash + ${$self}{verbatimCommands}{${$verbatimCommand}{id}}=$verbatimCommand; + + # log file output + $self->logger("VERBATIM command found: $verbCommand") if $is_t_switch_active; + + # remove the environment block, and replace with unique ID + ${$self}{body} =~ s/$verbatimCommandRegExp/${$verbatimCommand}{id}/sx; + + $self->logger("replaced with ID: ${$verbatimCommand}{id}") if $is_t_switch_active; + } + } else { + $self->logger("*not* looking for $verbCommand as $verbCommand:$yesno") if $is_t_switch_active; + } + } + return; + +} + +sub put_verbatim_back_in { + my $self = shift; + + # if there are no verbatim children, return + return unless(${$self}{verbatim}); + + # search for environments/commands + $self->logger('Putting verbatim back in, here is the pre-processed body:','heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + + # loop through document children hash + while( (scalar keys %{${$self}{verbatim}})>0 ){ + while( my ($key,$child)= each %{${$self}{verbatim}}){ + if(${$self}{body} =~ m/${$child}{id}/mx){ + + # replace ids with body + ${$self}{body} =~ s/${$child}{id}/${$child}{begin}${$child}{body}${$child}{end}/; + + # log file info + $self->logger('Body now looks like:','heading') if $is_tt_switch_active; + $self->logger(${$self}{body},'ttrace') if($is_tt_switch_active); + + # delete the hash so it won't be operated upon again + delete ${$self}{verbatim}{${$child}{id}}; + $self->logger("deleted key") if $is_t_switch_active; + } + } + } + + # logfile info + $self->logger("Number of children:",'heading') if $is_t_switch_active; + $self->logger(scalar keys %{${$self}{verbatim}}) if $is_t_switch_active; + $self->logger('Post-processed body:','heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + return; +} + +sub put_verbatim_commands_back_in { + my $self = shift; + + # if there are no verbatim children, return + return unless(${$self}{verbatimCommands}); + + # search for environments/commands + $self->logger('Putting verbatim commands back in, here is the pre-processed body:','heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + + # loop through document children hash + while( (scalar keys %{${$self}{verbatimCommands}})>0 ){ + while( my ($key,$child)= each %{${$self}{verbatimCommands}}){ + if(${$self}{body} =~ m/${$child}{id}/mx){ + + # replace ids with body + ${$self}{body} =~ s/${$child}{id}/${$child}{begin}${$child}{body}${$child}{end}/; + + # log file info + $self->logger('Body now looks like:','heading') if $is_tt_switch_active; + $self->logger(${$self}{body},'ttrace') if($is_tt_switch_active); + + # delete the hash so it won't be operated upon again + delete ${$self}{verbatimCommands}{${$child}{id}}; + $self->logger("deleted key") if $is_t_switch_active; + } + } + } + + # logfile info + $self->logger("Number of children:",'heading'); + $self->logger(scalar keys %{${$self}{verbatimCommands}}); + $self->logger('Post-processed body:','heading') if $is_t_switch_active; + $self->logger(${$self}{body}) if($is_t_switch_active); + return; +} + +sub create_unique_id{ + my $self = shift; + + $verbatimCounter++; + ${$self}{id} = "$tokens{verbatim}$verbatimCounter$tokens{endOfToken}"; + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml index ef620846f4f..20040817b12 100755 --- a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml +++ b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml @@ -1,5 +1,5 @@ # -# defaultSettings.yaml for latexindent.pl, +# defaultSettings.yaml for latexindent.pl, version 3.0 # a script that aims to # beautify .tex, .sty, .cls files # @@ -13,8 +13,17 @@ # # Please read the manual first to understand what each switch does :) -# Default value of indentation -defaultIndent: "\t" +# 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 # default file extension of backup file (if original is overwritten with -w switch) # for example, if your .tex file is called @@ -50,19 +59,62 @@ maxNumberOfBackUps: 0 # the back up will be written to myfile.bak4 cycleThroughBackUps: 0 +# preferences for information displayed in the log file +logFilePreferences: + showEveryYamlRead: 1 + showAmalgamatedSettings: 0 + endLogFileWith: '--------------' + showGitHubInfoFooter: 1 + +# verbatim environments- environments specified +# in this hash table will not be changed at all! +verbatimEnvironments: + verbatim: 1 + lstlisting: 1 + +# verbatim commands such as \verb! body !, \lstinline$something else$ +verbatimCommands: + verb: 1 + lstinline: 1 + +# no indent blocks (not necessarily verbatim +# environments) which are marked as %\begin{noindent} +# or anything else that the user puts in this hash +# table +noIndentBlock: + noindent: 1 + cmhtest: 1 + +# remove trailing whitespace from all lines +removeTrailingWhitespace: + beforeProcessing: 0 + afterProcessing: 1 + +# \begin{document} and \end{document} are treated differently +# by latexindent within filecontents environments +fileContentsEnvironments: + filecontents: 1 + filecontents*: 1 + # indent preamble indentPreamble: 0 -# always look for split { }, which means that the user doesn't -# have to complete checkunmatched, checkunmatchedELSE -alwaysLookforSplitBraces: 1 +# assume no preamble in cls, sty, by default +lookForPreamble: + .tex: 1 + .sty: 0 + .cls: 0 + .bib: 0 -# always look for split [ ], which means that the user doesn't -# have to complete checkunmatchedbracket -alwaysLookforSplitBrackets: 1 +# some preambles can contain \begin and \end statements +# that are not in their 'standard environment block', for example, +# consider the following key = values: +# preheadhook={\begin{mdframed}[style=myframedstyle]}, +# postfoothook=\end{mdframed}, +preambleCommandsBeforeEnvironments: 0 -# remove trailing whitespace from all lines -removeTrailingWhitespace: 0 +# Default value of indentation +defaultIndent: "\t" # environments that have tab delimiters, add more # as needed @@ -91,48 +143,43 @@ lookForAlignDelims: dcases: 1 listabla: 1 -# if you have indent rules for particular environments -# or commands, put them in here; for example, you might just want -# to use a space " " or maybe a double tab "\t\t" -indentRules: - myenvironment: "\t\t" - anotherenvironment: "\t\t\t\t" - chapter: " " - section: " " - item: " " - -# verbatim environments- environments specified -# in this hash table will not be changed at all! -verbatimEnvironments: - verbatim: 1 - lstlisting: 1 +# if you want the script to look for \item commands +# and format it, as follows (for example), +# \begin{itemize} +# \item content here +# next line is indented +# next line is indented +# \item another item +# \end{itemize} +# then populate indentAfterItems. See also itemNames +indentAfterItems: + itemize: 1 + enumerate: 1 + list: 1 -# no indent blocks (not necessarily verbatim -# environments) which are marked as %\begin{noindent} -# or anything else that the user puts in this hash -# table -noIndentBlock: - noindent: 1 - cmhtest: 1 +# if you want to use other names for your items (such as, for example, part) +# then populate them here- note that you can trick latexindent.pl +# into indenting all kinds of commands (within environments specified in +# indentAfterItems) using this technique. +itemNames: + item: 1 + myitem: 1 -# if you don't want to have additional indentation -# in an environment put it in this hash table; note that -# environments in this hash table will inherit -# the *current* level of indentation they just won't -# get any *additional*. -noAdditionalIndent: - myexample: 1 - mydefinition: 1 - problem: 1 - exercises: 1 - mysolution: 1 - foreach: 0 - widepage: 1 - comment: 1 - \[: 0 - \]: 0 - document: 1 - frame: 0 +# specialBeginEnd is mainly mathmode focus, although +# there's no restrictions +specialBeginEnd: + displayMath: + begin: '\\\[' + end: '\\\]' + lookForThis: 1 + inlineMath: + begin: '(?>' - traceModeAddCurrentIndent: '||' - traceModeDecreaseIndent: '<<' - traceModeBetweenLines: "\n" +# set indentRules globally for codeblocks; these need +# to be horizontal spaces, if they are to be used +indentRulesGlobal: + environments: 0 + commands: 0 + optionalArguments: 0 + mandatoryArguments: 0 + ifElseFi: 0 + items: 0 + keyEqualsValuesBracesBrackets: 0 + namedGroupingBracesBrackets: 0 + UnNamedGroupingBracesBrackets: 0 + specialBeginEnd: 0 + afterHeading: 0 + filecontents: 0 -# \begin{document} and \end{document} are treated differently -# by latexindent within filecontents environments -fileContentsEnvironments: - filecontents: 1 - filecontents*: 1 +# command code block details +commandCodeBlocks: + roundParenthesesAllowed: 1 + stringsAllowedBetweenArguments: + node: 1 + at: 1 + to: 1 + decoration: 1 + ++: 1 + --: 1 - -# *** NOTE *** -# If you have specified alwaysLookforSplitBraces: 1 -# and alwaysLookforSplitBrackets: 1 then you don't need -# to worry about completing +# modifyLineBreaks will only be searched if the -m +# switch is active +# BeginStartsOnOwnLine: 1 +# if a begin statement is not already on its own line, +# then, with -m active, it will be moved to its own line. # -# checkunmatched -# checkunmatchedELSE -# checkunmatchedbracket +# when set to 1, e.g +# some text some text \begin{myenvironment} +# will be changed to +# some text some text +# \begin{myenvironment} +# when set to -1, e.g +# some text some text +# \begin{myenvironment} +# will be changed to +# some text some text \begin{myenvironment} +# when set to 0, the switch is ignored # -# in other words, you don't really need to edit anything -# below this line- it used to be necessary for older -# versions of the script, but not anymore :) -#*** *** - -# commands that might split {} across lines -# such as \parbox, \marginpar, etc -checkunmatched: - parbox: 1 - vbox: 1 - -# very similar to %checkunmatched except these -# commands might have an else construct -checkunmatchedELSE: - pgfkeysifdefined: 1 - DTLforeach: 1 - ifthenelse: 1 - -# commands that might split [] across lines -# such as \pgfplotstablecreatecol, etc -checkunmatchedbracket: - pgfplotstablecreatecol: 1 - pgfplotstablesave: 1 - pgfplotstabletypeset: 1 - mycommand: 1 - psSolid: 1 - +# BodyStartsOnOwnLine: 1 +# if body does not already start on its own line, then with +# -m active, it will be moved to its own line. +# +# when set to 1, e.g +# \begin{myenv}body text body text +# will be changed to +# \begin{myenv} +# body text body text +# when set to -1, e.g +# \begin{myenv} +# body text body text +# will be changed to +# \begin{myenv}body text body text +# when set to 0, the switch is ignored +# +# EndStartsOnOwnLine: 1 +# if an end statement is not already on its own line, +# then, with -m active, it will be moved to its own line. +# +# when set to 1, e.g +# some text some text \end{myenvironment} +# will be changed to +# some text some text +# \end{myenvironment} +# when set to -1, e.g +# some text some text +# \end{myenvironment} +# will be changed to +# some text some text \end{myenvironment} +# when set to 0, the switch is ignored +# +# EndFinishesWithLineBreak: 1 +# this switch adjusts line breaks immmediately +# after an end statement (with -m active) +# +# when set to 1, e.g +# \end{myenvironment}some text some text +# will be changed to +# \end{myenvironment} +# some text some text +# when set to -1, e.g +# \end{myenvironment} +# some text some text +# will be changed to +# \end{myenvironment}some text some text +# when set to 0, the switch is ignored +# +# Naturally, you can specify settings for individual environments, +# commands, headings, etc, populate as you wish. +modifyLineBreaks: + preserveBlankLines: 1 + condenseMultipleBlankLinesInto: 1 + environments: + BeginStartsOnOwnLine: 0 + BodyStartsOnOwnLine: 0 + EndStartsOnOwnLine: 0 + EndFinishesWithLineBreak: 0 + equation*: + BeginStartsOnOwnLine: 0 + BodyStartsOnOwnLine: 0 + EndStartsOnOwnLine: 0 + EndFinishesWithLineBreak: 0 + ifElseFi: + IfStartsOnOwnLine: 0 + BodyStartsOnOwnLine: 0 + ElseStartsOnOwnLine: 0 + ElseFinishesWithLineBreak: 0 + FiStartsOnOwnLine: 0 + FiFinishesWithLineBreak: 0 + ifnum: + IfStartsOnOwnLine: 0 + BodyStartsOnOwnLine: 0 + ElseStartsOnOwnLine: 0 + ElseFinishesWithLineBreak: 0 + FiStartsOnOwnLine: 0 + FiFinishesWithLineBreak: 0 + commands: + CommandStartsOnOwnLine: 0 + CommandNameFinishesWithLineBreak: 0 + optionalArguments: + LSqBStartsOnOwnLine: 0 + OptArgBodyStartsOnOwnLine: 0 + RSqBStartsOnOwnLine: 0 + RSqBFinishesWithLineBreak: 0 + mandatoryArguments: + LCuBStartsOnOwnLine: 0 + MandArgBodyStartsOnOwnLine: 0 + RCuBStartsOnOwnLine: 0 + RCuBFinishesWithLineBreak: 0 + keyEqualsValuesBracesBrackets: + KeyStartsOnOwnLine: 0 + EqualsStartsOnOwnLine: 0 + EqualsFinishesWithLineBreak: 0 + items: + ItemStartsOnOwnLine: 0 + ItemFinishesWithLineBreak: 0 + namedGroupingBracesBrackets: + NameStartsOnOwnLine: 0 + NameFinishesWithLineBreak: 0 + specialBeginEnd: + SpecialBeginStartsOnOwnLine: 0 + SpecialBodyStartsOnOwnLine: 0 + SpecialEndStartsOnOwnLine: 0 + SpecialEndFinishesWithLineBreak: 0 diff --git a/Master/texmf-dist/scripts/latexindent/latexindent.pl b/Master/texmf-dist/scripts/latexindent/latexindent.pl index cdd979a8ccf..06adc58a1b8 100755 --- a/Master/texmf-dist/scripts/latexindent/latexindent.pl +++ b/Master/texmf-dist/scripts/latexindent/latexindent.pl @@ -11,57 +11,34 @@ # # See http://www.gnu.org/licenses/. # -# For details of how to use this file, please see readme.txt +# Chris Hughes, 2017 +# +# For all communication, please visit: https://github.com/cmhughes/latexindent.pl -# load packages/modules: assume strict and warnings are part of every perl distribution use strict; use warnings; +use FindBin; # help find defaultSettings.yaml +use Getopt::Long; # to get the switches/options/flags -# list of modules -my @listOfModules = ('FindBin','YAML::Tiny','File::Copy','File::Basename','Getopt::Long','File::HomeDir'); - -# check the other modules are available -foreach my $moduleName (@listOfModules) { - # references: - # http://stackoverflow.com/questions/251694/how-can-i-check-if-i-have-a-perl-module-before-using-it - # http://stackoverflow.com/questions/1917261/how-can-i-dynamically-include-perl-modules-without-using-eval - eval { - (my $file = $moduleName) =~ s|::|/|g; - require $file . '.pm'; - $moduleName->import(); - 1; - } or die "$moduleName Perl Module not currently installed; please install the module, and then try running latexindent.pl again; exiting"; -} - -# now that we have confirmed the modules are available, load them -use FindBin; # help find defaultSettings.yaml -use YAML::Tiny; # interpret defaultSettings.yaml and other potential settings files -use File::Copy; # to copy the original file to backup (if overwrite option set) -use File::Basename; # to get the filename and directory path -use Getopt::Long; # to get the switches/options/flags -use File::HomeDir; # to get users home directory, regardless of OS +# use lib to make sure that @INC contains the latexindent directory +use lib $FindBin::RealBin; +use LatexIndent::Document; # get the options -my $overwrite; -my $outputToFile; -my $silentMode; -my $tracingMode; -my $tracingModeVeryDetailed; -my $readLocalSettings=0; -my $onlyDefault; -my $showhelp; -my $cruftDirectory; +my %switches = (readLocalSettings=>0); GetOptions ( - "overwrite|w"=>\$overwrite, -"outputfile|o"=>\$outputToFile, -"silent|s"=>\$silentMode, -"trace|t"=>\$tracingMode, -"ttrace|tt"=>\$tracingModeVeryDetailed, -"local|l:s"=>\$readLocalSettings, -"onlydefault|d"=>\$onlyDefault, -"help|h"=>\$showhelp, -"cruft|c=s"=>\$cruftDirectory, + "silent|s"=>\$switches{silentMode}, + "trace|t"=>\$switches{trace}, + "ttrace|tt"=>\$switches{ttrace}, + "local|l:s"=>\$switches{readLocalSettings}, + "onlydefault|d"=>\$switches{onlyDefault}, + "overwrite|w"=>\$switches{overwrite}, + "outputfile|o=s"=>\$switches{outputToFile}, + "modifylinebreaks|m"=>\$switches{modifyLineBreaks}, + "logfile|g=s"=>\$switches{logFileName}, + "help|h"=>\$switches{showhelp}, + "cruft|c=s"=>\$switches{cruftDirectory}, ); # check local settings doesn't interfer with reading the file; @@ -74,20 +51,9 @@ GetOptions ( # # In such circumstances, we correct the mistake by assuming that # the only argument is the file to be indented, and place it in @ARGV -if($readLocalSettings and scalar(@ARGV) < 1) { - push(@ARGV,$readLocalSettings); - $readLocalSettings = ''; -} - -# this can also happen if the script is called as -# -# latexindent.pl -o -l myfile.tex outputfile.tex -# -# in which case, the GetOptions routine mistakes myfile.tex -# as the optional parameter to the l flag. -if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) { - unshift(@ARGV,$readLocalSettings); - $readLocalSettings = ''; +if($switches{readLocalSettings} and scalar(@ARGV) < 1) { + push(@ARGV,$switches{readLocalSettings}); + $switches{readLocalSettings} = ''; } # default value of readLocalSettings @@ -95,2054 +61,10 @@ if($readLocalSettings and scalar(@ARGV) < 2 and $outputToFile) { # latexindent -l myfile.tex # # means that we wish to use localSettings.yaml -if(defined($readLocalSettings) and ($readLocalSettings eq '')){ - $readLocalSettings = 'localSettings.yaml'; -} - -# detailed tracing mode also implies regular tracing mode -$tracingMode = $tracingModeVeryDetailed ? 1 : $tracingMode; - -# version number -my $versionNumber = "2.2"; - -# Check the number of input arguments- if it is 0 then simply -# display the list of options (like a manual) -if(scalar(@ARGV) < 1 or $showhelp) { - print < - used to specify the location of backup files and indent.log -ENDQUOTE - ; - exit(2); -} - -# set up default for cruftDirectory using the one from the input file, -# unless it has been specified using -c="/some/directory" -$cruftDirectory=dirname $ARGV[0] unless(defined($cruftDirectory)); - -die "Could not find directory $cruftDirectory\nExiting, no indentation done." if(!(-d $cruftDirectory)); - -# we'll be outputting to the logfile and to standard output -my $logfile; -my $out = *STDOUT; - -# open the log file -open($logfile,">","$cruftDirectory/indent.log") or die "Can't open indent.log"; - -# output time to log file -my $time = localtime(); -print $logfile $time; - -# output version to log file -print $logfile <2) { - for my $fh ($out,$logfile) {print $fh <new; - -# Open defaultSettings.yaml -$defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" ); -print $logfile "\tReading defaultSettings.yaml from $FindBin::RealBin/defaultSettings.yaml\n\n" if($defaultSettings); - -# if latexindent.exe is invoked from TeXLive, then defaultSettings.yaml won't be in -# the same directory as it; we need to navigate to it -if(!$defaultSettings) { - $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml"); - print $logfile "\tReading defaultSettings.yaml (2nd attempt, TeXLive, Windows) from $FindBin::RealBin/../../texmf-dist/scripts/latexindent/defaultSettings.yaml\n\n" if($defaultSettings); -} - -# if both of the above attempts have failed, we need to exit -if(!$defaultSettings) { - for my $fh ($out,$logfile) { - print $fh <[0]}; - -# empty array to store the paths -my @absPaths; - -# scalar to read user settings -my $userSettings; - -# get information about user settings- first check if indentconfig.yaml exists -my $indentconfig = File::HomeDir->my_home . "/indentconfig.yaml"; -# if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml -$indentconfig = File::HomeDir->my_home . "/.indentconfig.yaml" if(! -e $indentconfig); - -if ( -e $indentconfig and !$onlyDefault ) { - print $logfile "\tReading path information from $indentconfig\n"; - # if both indentconfig.yaml and .indentconfig.yaml exist - if ( -e File::HomeDir->my_home . "/indentconfig.yaml" and -e File::HomeDir->my_home . "/.indentconfig.yaml") { - print $logfile File::HomeDir->my_home,"/.indentconfig.yaml has been found, but $indentconfig takes priority\n"; - } elsif ( -e File::HomeDir->my_home . "/indentconfig.yaml" ) { - print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/.indentconfig.yaml can be used\n"; - - } elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) { - print $logfile "\tAlternatively, ",File::HomeDir->my_home,"/indentconfig.yaml can be used\n"; - } - - # read the absolute paths from indentconfig.yaml - $userSettings = YAML::Tiny->read( "$indentconfig" ); - - # integrity check - if($userSettings) { - print $logfile "\t",Dump \%{$userSettings->[0]}; - print $logfile "\n"; - @absPaths = @{$userSettings->[0]->{paths}}; - } else { - print $logfile <my_home,"\n"; - print $logfile "\tTo specify user settings you would put indentconfig.yaml here: \n\t",File::HomeDir->my_home,"/indentconfig.yaml\n\n"; - print $logfile "\tAlternatively, you can use the hidden file .indentconfig.yaml as: \n\t",File::HomeDir->my_home,"/.indentconfig.yaml\n\n"; - } -} - -# get information about LOCAL settings, assuming that $readLocalSettings exists -my $directoryName = dirname $ARGV[0]; - -# add local settings to the paths, if appropriate -if ( (-e "$directoryName/$readLocalSettings") and $readLocalSettings and !(-z "$directoryName/$readLocalSettings")) { - print $logfile "\tAdding $directoryName/$readLocalSettings to paths\n\n"; - push(@absPaths,"$directoryName/$readLocalSettings"); -} elsif ( !(-e "$directoryName/$readLocalSettings") and $readLocalSettings) { - print $logfile "\tWARNING yaml file not found: \n\t$directoryName/$readLocalSettings not found\n"; - print $logfile "\t\tcarrying on without it.\n"; -} - -# read in the settings from each file -foreach my $settings (@absPaths) { - # check that the settings file exists and that it isn't empty - if (-e $settings and !(-z $settings)) { - print $logfile "\tReading USER settings from $settings\n"; - $userSettings = YAML::Tiny->read( "$settings" ); - - # if we can read userSettings - if($userSettings) { - # update the MASTER setttings to include updates from the userSettings - while(my($userKey, $userValue) = each %{$userSettings->[0]}) { - # the update approach is slightly different for hashes vs scalars/arrays - if (ref($userValue) eq "HASH") { - while(my ($userKeyFromHash,$userValueFromHash) = each %{$userSettings->[0]{$userKey}}) { - $masterSettings{$userKey}{$userKeyFromHash} = $userValueFromHash; - } - } else { - $masterSettings{$userKey} = $userValue; - } - } - # output settings to $logfile - if($masterSettings{logFilePreferences}{showEveryYamlRead}){ - print $logfile Dump \%{$userSettings->[0]}; - print $logfile "\n"; - } else { - print $logfile "\t\tNot showing settings in the log file, see showEveryYamlRead.\n"; - } - } else { - # otherwise print a warning that we can not read userSettings.yaml - print $logfile "WARNING\n\t$settings \n\t contains invalid yaml format- not reading from it\n"; - } - } else { - # otherwise keep going, but put a warning in the log file - print $logfile "\nWARNING\n\t",File::HomeDir->my_home,"/indentconfig.yaml\n"; - if (-z $settings) { - print $logfile "\tspecifies $settings \n\tbut this file is EMPTY- not reading from it\n\n" - } else { - print $logfile "\tspecifies $settings \n\tbut this file does not exist- unable to read settings from this file\n\n" - } - } -} - -# some people may wish to see showAlmagamatedSettings -# which details the overall state of the settings modified -# from the default in various user files -if($masterSettings{logFilePreferences}{showAlmagamatedSettings}){ - print $logfile "Almagamated/overall settings to be used:\n"; - print $logfile Dump \%masterSettings ; -} - -# scalar variables -my $defaultIndent = $masterSettings{defaultIndent}; -my $alwaysLookforSplitBraces = $masterSettings{alwaysLookforSplitBraces}; -my $alwaysLookforSplitBrackets = $masterSettings{alwaysLookforSplitBrackets}; -my $backupExtension = $masterSettings{backupExtension}; -my $indentPreamble = $masterSettings{indentPreamble}; -my $onlyOneBackUp = $masterSettings{onlyOneBackUp}; -my $maxNumberOfBackUps = $masterSettings{maxNumberOfBackUps}; -my $removeTrailingWhitespace = $masterSettings{removeTrailingWhitespace}; -my $cycleThroughBackUps = $masterSettings{cycleThroughBackUps}; - -# hash variables -my %lookForAlignDelims= %{$masterSettings{lookForAlignDelims}}; -my %indentRules= %{$masterSettings{indentRules}}; -my %verbatimEnvironments= %{$masterSettings{verbatimEnvironments}}; -my %noIndentBlock= %{$masterSettings{noIndentBlock}}; -my %checkunmatched= %{$masterSettings{checkunmatched}}; -my %checkunmatchedELSE= %{$masterSettings{checkunmatchedELSE}}; -my %checkunmatchedbracket= %{$masterSettings{checkunmatchedbracket}}; -my %noAdditionalIndent= %{$masterSettings{noAdditionalIndent}}; -my %indentAfterHeadings= %{$masterSettings{indentAfterHeadings}}; -my %indentAfterItems= %{$masterSettings{indentAfterItems}}; -my %itemNames= %{$masterSettings{itemNames}}; -my %constructIfElseFi= %{$masterSettings{constructIfElseFi}}; -my %fileExtensionPreference= %{$masterSettings{fileExtensionPreference}}; -my %fileContentsEnvironments= %{$masterSettings{fileContentsEnvironments}}; - -# original name of file -my $fileName = $ARGV[0]; - -# sort the file extensions by preference -my @fileExtensions = sort { $fileExtensionPreference{$a} <=> $fileExtensionPreference{$b} } keys(%fileExtensionPreference); - -# get the base file name, allowing for different extensions (possibly no extension) -my ($dir, $name, $ext) = fileparse($fileName, @fileExtensions); - -# quick check to make sure given file type is supported -if( -e $ARGV[0] and !$ext ){ -for my $fh ($out,$logfile) {print $fh <1) { - print $logfile "\t WARNING: onlyOneBackUp=$onlyOneBackUp and maxNumberOfBackUps: $maxNumberOfBackUps\n"; - print $logfile "\t\t setting onlyOneBackUp=0 which will allow you to reach $maxNumberOfBackUps back ups\n"; - $onlyOneBackUp = 0; - } - - # if the user has specified that $maxNumberOfBackUps = 1 then - # they only want one backup - if($maxNumberOfBackUps==1) { - $onlyOneBackUp=1 ; - print $logfile "\t FYI: you set maxNumberOfBackUps=1, so I'm setting onlyOneBackUp: 1 \n"; - } elsif($maxNumberOfBackUps<=0 and !$onlyOneBackUp) { - $onlyOneBackUp=0 ; - $maxNumberOfBackUps=-1; - } - - # if onlyOneBackUp is set, then the backup file will - # be overwritten each time - if($onlyOneBackUp) { - $backupFile .= $backupExtension; - print $logfile "\tcopying $fileName to $backupFile\n"; - print $logfile "\t$backupFile was overwritten\n\n" if (-e $backupFile); - } else { - # start with a backup file .bak0 (or whatever $backupExtension is present) - my $backupCounter = 0; - $backupFile .= $backupExtension.$backupCounter; - - # if it exists, then keep going: .bak0, .bak1, ... - while (-e $backupFile or $maxNumberOfBackUps>1) { - if($backupCounter==$maxNumberOfBackUps) { - print $logfile "\t maxNumberOfBackUps reached ($maxNumberOfBackUps)\n"; - - # some users may wish to cycle through back up files, e.g: - # copy myfile.bak1 to myfile.bak0 - # copy myfile.bak2 to myfile.bak1 - # copy myfile.bak3 to myfile.bak2 - # - # current back up is stored in myfile.bak4 - if($cycleThroughBackUps) { - print $logfile "\t cycleThroughBackUps detected (see cycleThroughBackUps) \n"; - for(my $i=1;$i<=$maxNumberOfBackUps;$i++) { - # remove number from backUpFile - my $oldBackupFile = $backupFile; - $oldBackupFile =~ s/$backupExtension.*/$backupExtension/; - my $newBackupFile = $oldBackupFile; - - # add numbers back on - $oldBackupFile .= $i; - $newBackupFile .= $i-1; - - # check that the oldBackupFile exists - if(-e $oldBackupFile){ - print $logfile "\t\t copying $oldBackupFile to $newBackupFile \n"; - copy($oldBackupFile,$newBackupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n"; - } - } - } - - # rest maxNumberOfBackUps - $maxNumberOfBackUps=1 ; - last; # break out of the loop - } elsif(!(-e $backupFile)) { - $maxNumberOfBackUps=1 ; - last; # break out of the loop - } - print $logfile "\t $backupFile already exists, incrementing by 1...\n"; - $backupCounter++; - $backupFile =~ s/$backupExtension.*/$backupExtension$backupCounter/; - } - print $logfile "\n\t copying $fileName to $backupFile\n\n"; - } - - # output these lines to the log file - print $logfile "\tBackup file: ",$backupFile,"\n"; - print $logfile "\tOverwriting file: ",$fileName,"\n\n"; - copy($fileName,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n"; -} - -if(!($outputToFile or $overwrite)) { - print $logfile "Just out put to the terminal :)\n\n" if !$silentMode ; -} - - -# scalar variables -my $line; # $line: takes the $line of the file -my $inpreamble=!$indentPreamble; - # $inpreamble: switch to determine if in - # preamble or not -my $inverbatim=0; # $inverbatim: switch to determine if in - # a verbatim environment or not -my $delimiters=0; # $delimiters: switch that governs if - # we need to check for & or not -my $trailingcomments; # $trailingcomments stores the comments at the end of - # a line -my $lineCounter=0; # $lineCounter keeps track of the line number -my $inIndentBlock=0; # $inindentblock: switch to determine if in - # a inindentblock or not -my $inFileContents=0; # $inFileContents: switch to determine if we're in a filecontents environment - -# array variables -my @lines; # @lines: stores the newly indented lines -my @mainfile; # @mainfile: stores input file; used to - # grep for \documentclass - -# array of hashes, containing details of commands & environments -my @masterIndentationArrayOfHashes; - -# check to see if the current file has \documentclass, if so, then -# it's the main file, if not, then it doesn't have preamble -open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; - @mainfile=; -close(MAINFILE); - -# if the MAINFILE doesn't have a \documentclass statement, then -# it shouldn't have preamble -if(scalar(@{[grep(m/^\s*\\documentclass/, @mainfile)]})==0) { - $inpreamble=0; - - print $logfile "Trace:\tNo documentclass detected, assuming no preamble\n" if($tracingMode); -} else { - print $logfile "Trace:\t documentclass detected, assuming preamble\n" if($tracingMode); -} - -# the previous OPEN command puts us at the END of the file -open(MAINFILE, $fileName) or die "Could not open input file, $fileName"; - -# loop through the lines in the INPUT file -while() { - # increment the line counter - $lineCounter++; - - # very detailed output to logfile - if($tracingModeVeryDetailed){ - if( @masterIndentationArrayOfHashes){ - print $logfile "\nLine $lineCounter\t (detailed trace) indentation hash: \n" if($tracingMode); - for my $href ( @masterIndentationArrayOfHashes) { - print $logfile Dump \%{$href}; - } - } - } - - # tracing mode - print $logfile $masterSettings{logFilePreferences}{traceModeBetweenLines} if($tracingMode and !($inpreamble or $inverbatim or $inIndentBlock)); - - # check to see if we're still in the preamble - # or in a verbatim environment or in IndentBlock - if(!($inpreamble or $inverbatim or $inIndentBlock)) { - # if not, remove all leading spaces and tabs - # from the current line, assuming it isn't empty - s/^\t*// if($_ !~ /^((\s*)|(\t*))*$/); - s/^\s*// if($_ !~ /^((\s*)|(\t*))*$/); - - # tracing mode - print $logfile "Line $lineCounter\t removing leading spaces\n" if($tracingMode); - } else { - # otherwise check to see if we've reached the main - # part of the document - if(m/^\s*\\begin\{document\}/ and !$inFileContents and !$inverbatim) { - $inpreamble = 0; - - # tracing mode - print $logfile "Line $lineCounter\t \\begin{document} found, switching indentation searches on. \n" if($tracingMode); - } else { - # tracing mode - if($inpreamble) { - print $logfile "Line $lineCounter\t still in PREAMBLE, leaving exisiting leading space (see indentPreamble)\n" if($tracingMode); - } elsif($inverbatim) { - print $logfile "Line $lineCounter\t in VERBATIM-LIKE environment, leaving exisiting leading space\n" if($tracingMode); - } elsif($inIndentBlock) { - print $logfile "Line $lineCounter\t in NO INDENT BLOCK, leaving exisiting leading space\n" if($tracingMode); - } - } - } - - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - # \END{ENVIRONMENTS}, or CLOSING } or CLOSING ] - - # check to see if we're ending a filecontents environment - if( $_ =~ m/^\s*\\end\{(.*?)\}/ and $fileContentsEnvironments{$1} and $inFileContents){ - print $logfile "Line $lineCounter\t Found END of filecontents environment (see fileContentsEnvironments)\n" if($tracingMode); - $inFileContents = 0; - } - - # set the delimiters switch - $delimiters = @masterIndentationArrayOfHashes?$masterIndentationArrayOfHashes[-1]{alignmentDelimiters}:0; - - if($inverbatim){ - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in VERBATIM-LIKE environment, looking for $masterIndentationArrayOfHashes[-1]{end} \n" if($tracingMode); - } elsif($inIndentBlock) { - print $logfile "Line $lineCounter\t in NO INDENT BLOCK, doing nothing\n" if($tracingMode); - } elsif($delimiters) { - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: in ALIGNMENT BLOCK environment, looking for $masterIndentationArrayOfHashes[-1]{end}\n" if($tracingMode); - } elsif($inpreamble and !$inFileContents) { - print $logfile "Line $lineCounter\t In preamble, looking for \\begin{document}\n" if($tracingMode); - } elsif($inpreamble and $inFileContents) { - print $logfile "Line $lineCounter\t In preamble, in filecontents environment\n" if($tracingMode); - } else { - print $logfile "Line $lineCounter\t $masterSettings{logFilePreferences}{traceModeDecreaseIndent} PHASE 1: looking for reasons to DECREASE indentation of CURRENT line \n" if($tracingMode); - } - - # check to see if we have \end{something} or \] - &at_end_of_env_or_eq() unless ($inpreamble or $inIndentBlock); - - # check to see if we have %* \end{something} for alignment blocks - # outside of environments - &end_command_with_alignment(); - - # check to see if we're at the end of a noindent - # block %\end{noindent} - &at_end_noindent(); - - # only check for unmatched braces if we're not in - # a verbatim-like environment or in the preamble or in a - # noIndentBlock or in a delimiter block - if(!($inverbatim or $inpreamble or $inIndentBlock or $delimiters)) { - # The check for closing } and ] relies on counting, so - # we have to remove trailing comments so that any {, }, [, ] - # that are found after % are not counted - # - # note that these lines are NOT in @lines, so we - # have to store the $trailingcomments to put - # back on after the counting - # - # note the use of (?",$fileName); - print OUTPUTFILE @lines; - close(OUTPUTFILE); -} - -# if -o is active then output to $ARGV[1] -if($outputToFile) { - open(OUTPUTFILE,">",$ARGV[1]); - print OUTPUTFILE @lines; - close(OUTPUTFILE); - print $logfile "Output from indentation written to $ARGV[1].\n"; -} - -# final line of the logfil -print $logfile "\n",$masterSettings{logFilePreferences}{endLogFileWith}; - -# close the log file -close($logfile); - +my $document = LatexIndent::Document->new(name=>"masterdocument",fileName=>$ARGV[0],switches=>\%switches); +$document->latexindent; exit(0); - -sub indent_if_else_fi{ - # PURPOSE: set indentation of line that contains \else, \fi command - # - # - - # @masterIndentationArrayOfHashes could be empty -- if so, exit - return unless @masterIndentationArrayOfHashes; - return unless $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}; - - # look for \fi - if( $_ =~ m/^\s*\\fi/) { - # tracing mode - print $logfile "Line $lineCounter\t \\fi command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode); - &decrease_indent($masterIndentationArrayOfHashes[-1]{name}); - } - # look for \else or \or - elsif( $_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) { - # tracing mode - print $logfile "Line $lineCounter\t \\else command found, matching: \\",$masterIndentationArrayOfHashes[-1]{name}, "\n" if($tracingMode); - print $logfile "Line $lineCounter\t decreasing indent, still looking for \\fi to match \\",¤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}=""; - } -} - -sub indent_after_if_else_fi{ - # PURPOSE: set indentation *after* \if construct such as - # - # \ifnum\x=2 - # - # - # \else - # - # - # \fi - # - # How to read /^\s*\\(if.*?)(\s|\\|\#) - # - # ^\s* begins with multiple spaces (possibly none) - # \\(if.*?)(\s|\\|\#) matches \if... up to either a - # space, a \, or a # - # Note: this won't match \if.*\fi - if( $_ =~ m/^\s*\\(if.*?)(\s|\\|\#)/ and $_ !~ m/^\s*\\(if.*?\\fi)/ and $constructIfElseFi{$1}) { - # tracing mode - print $logfile "Line $lineCounter\t ifelsefi construct found: $1 \n" if($tracingMode); - &increase_indent({name=>$1,type=>"ifelseif"}); - } elsif(@masterIndentationArrayOfHashes) { - if( ($_ =~ m/^\s*\\else/ or $_ =~ m/^\s*\\or/ ) and $constructIfElseFi{$masterIndentationArrayOfHashes[-1]{name}}) { - # tracing mode - print $logfile "Line $lineCounter\t setting indent *after* \\else or \\or command found for $masterIndentationArrayOfHashes[-1]{name} \n" if($tracingMode); - - # recover the indentation to be implemented *after* the \else or \or - $masterIndentationArrayOfHashes[-1]{indent}=$indentRules{$masterIndentationArrayOfHashes[-1]{name}}||$defaultIndent unless ($noAdditionalIndent{$masterIndentationArrayOfHashes[-1]{name}}); - } - } -} - -sub indent_item{ - # PURPOSE: when considering environments that can contain items, such - # as enumerate, itemize, etc, this subroutine sets the indentation for the item *itself* - - return unless(scalar(@masterIndentationArrayOfHashes)>1); - return unless $indentAfterItems{$masterIndentationArrayOfHashes[-2]{name}}; - - if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ and $itemNames{$1}){ - # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - if($itemNames{$masterIndentationArrayOfHashes[-1]{name}}) { - print $logfile "Line $lineCounter\t $1 found - neutralizing indentation from previous ",$masterIndentationArrayOfHashes[-1]{name},"\n" if($tracingMode); - &decrease_indent($1); - } - } - -} - -sub indent_after_item{ - # PURPOSE: Set the indentation *after* the item - # This matches a line that begins with - # - # \item - # \item[ - # \myitem - # \myitem[ - # - # or anything else specified in itemNames - # - return unless @masterIndentationArrayOfHashes; - return unless $indentAfterItems{$masterIndentationArrayOfHashes[-1]{name}}; - - if( $_ =~ m/^\s*\\(.*?)(\[|\s)/ - and $itemNames{$1}) { - # tracing mode - print $logfile "Line $lineCounter\t $1 found within ",$masterIndentationArrayOfHashes[-1]{name}," environment (see indentAfterItems and itemNames)\n" if($tracingMode); - &increase_indent({name=>$1,type=>"item"}); - } -} - -sub begin_command_with_alignment{ - # PURPOSE: This matches - # %* \begin{tabular} - # with any number of spaces (possibly none) between - # the * and \begin{noindent}. - # - # the comment symbol IS indended! - # - # This is to align blocks that contain delimeters that - # are NOT contained in an alignment block in the usual way, e.g - # \matrix{ - # %* \begin{tabular} - # 1 & 2 \\ - # 3 & 4 \\ - # %* \end{tabular} - # } - - if( $_ =~ m/^\s*%\*\s*\\begin\{(.*?)\}/ and $lookForAlignDelims{$1}) { - # increase the indentation - &increase_indent({name=>$1, - alignmentDelimiters=>1, - type=>"environment", - begin=>"\\begin{$1}", - end=>"\\end{$1}"}); - # tracing mode - print $logfile "Line $lineCounter\t Delimiter environment started: $1 (see lookForAlignDelims)\n" if($tracingMode); - } -} - -sub end_command_with_alignment{ - # PURPOSE: This matches - # %* \end{tabular} - # with any number of spaces (possibly none) between - # the * and \end{tabular} (or any other name used from - # lookFroAlignDelims) - # - # Note: the comment symbol IS indended! - # - # This is to align blocks that contain delimeters that - # are NOT contained in an alignment block in the usual way, e.g - # \matrix{ - # %* \begin{tabular} - # 1 & 2 \\ - # 3 & 4 \\ - # %* \end{tabular} - # } - return unless @masterIndentationArrayOfHashes; - return unless $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}; - - if( $_ =~ m/^\s*%\*\s*\\end\{(.*?)\}/ and $lookForAlignDelims{$1}) { - # same subroutine used at the end of regular tabular, align, etc - # environments - if($delimiters) { - &print_aligned_block(); - &decrease_indent($1); - } else { - # tracing mode - print $logfile "Line $lineCounter\t FYI: did you mean to start a delimiter block on a previous line? \n" if($tracingMode); - print $logfile "Line $lineCounter\t perhaps using %* \\begin{$1}\n" if($tracingMode); - } - } -} - -sub indent_heading{ - # PURPOSE: This matches - # \part - # \chapter - # \section - # \subsection - # \subsubsection - # \paragraph - # \subparagraph - # - # and anything else listed in indentAfterHeadings - # - # This subroutine specifies the indentation for the - # heading itself, i.e the line that has \chapter, \section etc - if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}){ - # tracing mode - print $logfile "Line $lineCounter\t Heading found: $1 \n" if($tracingMode); - - # get the heading settings, it's a hash within a hash - my %currentHeading = %{$indentAfterHeadings{$1}}; - - # $previousHeadingLevel: scalar that stores which heading - # we are under: \part, \chapter, etc - my $previousHeadingLevel=0; - - # form an array of the headings available - my @headingStore=(); - foreach my $env (@masterIndentationArrayOfHashes){ - if($env->{type} eq 'heading'){ - push(@headingStore,$env->{name}); - # update heading level - $previousHeadingLevel= $env->{headinglevel}; - } - } - - # if current heading level < old heading level, - if($currentHeading{level}<$previousHeadingLevel) { - # decrease indentation, but only if - # specified in indentHeadings. Note that this check - # needs to be done here- decrease_indent won't - # check a nested hash - - if(scalar(@headingStore)) { - while($currentHeading{level}<$previousHeadingLevel and scalar(@headingStore)) { - my $higherHeadingName = pop(@headingStore); - my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; - - # tracing mode - print $logfile "Line $lineCounter\t stepping UP heading level from $higherHeadingName \n" if($tracingMode); - - &decrease_indent($higherHeadingName) if($higherLevelHeading{indent}); - $previousHeadingLevel=$higherLevelHeading{level}; - } - # put the heading name back in to storage - push(@headingStore,$1); - } - } elsif($currentHeading{level}==$previousHeadingLevel) { - if(scalar(@headingStore)) { - my $higherHeadingName = pop(@headingStore); - my %higherLevelHeading = %{$indentAfterHeadings{$higherHeadingName}}; - &decrease_indent($higherHeadingName) if($higherLevelHeading{indent}); - } - } - } -} - -sub indent_after_heading{ - # PURPOSE: This matches - # \part - # \chapter - # \section - # \subsection - # \subsubsection - # \paragraph - # \subparagraph - # - # and anything else listed in indentAfterHeadings - # - # This subroutine is specifies the indentation for - # the text AFTER the heading, i.e the body of conent - # in each \chapter, \section, etc - if( $_ =~ m/^\s*\\(.*?)(\[|{)/ and $indentAfterHeadings{$1}) { - # get the heading settings- it's a hash within a hash - my %currentHeading = %{$indentAfterHeadings{$1}}; - - &increase_indent({name=>$1,type=>"heading",headinglevel=>$currentHeading{level}}) if($currentHeading{indent}); - } -} - -sub at_end_noindent{ - # PURPOSE: This matches - # % \end{noindent} - # with any number of spaces (possibly none) between - # the comment and \end{noindent}. - # - # the comment symbol IS indended! - # - # This is for blocks of code that the user wants - # to leave untouched- similar to verbatim blocks - - if( $_ =~ m/^%\s*\\end\{(.*?)\}/ and $noIndentBlock{$1}) { - $inIndentBlock=0; - # tracing mode - print $logfile "Line $lineCounter\t % \\end{no indent block} found, switching inIndentBlock OFF \n" if($tracingMode); - } -} - -sub at_beg_noindent{ - # PURPOSE: This matches - # % \begin{noindent} - # with any number of spaces (possibly none) between - # the comment and \begin{noindent}. - # - # the comment symbol IS indended! - # - # This is for blocks of code that the user wants - # to leave untouched- similar to verbatim blocks - - if( $_ =~ m/^%\s*\\begin\{(.*?)\}/ and $noIndentBlock{$1}) { - $inIndentBlock = 1; - # tracing mode - print $logfile "Line $lineCounter\t % \\begin{no indent block} found, switching inIndentBlock ON \n" if($tracingMode); - } -} - -sub start_command_or_key_unmatched_brackets{ - # PURPOSE: This matches - # \pgfplotstablecreatecol[... - # - # or any other command/key that has brackets [ ] - # split across lines specified in the - # hash tables, %checkunmatchedbracket - # - # How to read: ^\s*(\\)?(.*?)(\[\s*) - # - # ^ line begins with - # \s* any (or no)spaces - # (\\)? matches a \ backslash but not necessarily - # (.*?) non-greedy character match and store the result - # ((?$commandname,matchedBRACKETS=>$matchedBRACKETS,type=>'splitBrackets'}); - } - } -} - -sub end_command_or_key_unmatched_brackets{ - # PURPOSE: Check for the closing BRACKET of a command that - # splits its BRACKETS across lines, such as - # - # \pgfplotstablecreatecol[ ... - # - # It works by checking if we have any entries - # in the array @masterIndentationArrayOfHashes, and making - # sure that we're not starting another command/key - # that has split BRACKETS (nesting). - # - # It also checks that the line is not commented. - # - # We count the number of [ and ADD to the counter - # ] and SUBTRACT to the counter - return unless @masterIndentationArrayOfHashes; - return unless ($masterIndentationArrayOfHashes[-1]{type} eq 'splitBrackets'); - print $logfile "Line $lineCounter\t Searching for closing BRACKET ] $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - if(!($_ =~ m/^\s*(\\)?(.*?)(\s*\[)/ - and ($checkunmatchedbracket{$2} or $alwaysLookforSplitBrackets)) - and $_ !~ m/^\s*%/) { - - # get the details of the most recent command name - my $commandname = $masterIndentationArrayOfHashes[-1]{name}; - my $matchedBRACKETS = $masterIndentationArrayOfHashes[-1]{matchedBRACKETS}; - - # match [ but don't match \[ - $matchedBRACKETS++ while ($_ =~ m/(? 0 ) { - # tracing mode - print $logfile "Line $lineCounter\t Found opening BRACE { $commandname\n" if($tracingMode); - - &increase_indent({name=>$commandname, - matchedbraces=>$matchedbraces, - lookforelse=>$lookforelse, - countzeros=>0, - type=>"splitbraces"}); - } elsif($matchedbraces<0) { - # if $matchedbraces < 0 then we must be matching - # braces from a previous split-braces command - - # keep matching { OR }, and don't match \{ or \} - while ($_ =~ m/(((?$2, - type=>"environment", - begin=>"\\begin{$2}", - end=>"\\end{$2}"}); - - # check for verbatim-like environments - if($verbatimEnvironments{$2}){ - $inverbatim = 1; - # tracing mode - print $logfile "Line $lineCounter\t \\begin{verbatim-like} found, $2, switching ON verbatim \n" if($tracingMode); - - # remove the key and value from %lookForAlignDelims hash - # to avoid any further confusion - if($lookForAlignDelims{$2}) { - print $logfile "WARNING\n\t Line $lineCounter\t $2 is in *both* lookForAlignDelims and verbatimEnvironments\n"; - print $logfile "\t\t\t ignoring lookForAlignDelims and prioritizing verbatimEnvironments\n"; - print $logfile "\t\t\t Note that you only get this message once per environment\n"; - delete $lookForAlignDelims{$2}; - } - } - } -} - -sub at_end_of_env_or_eq{ - # PURPOSE: Check if we're at the END of an environment - # or at the END of a displayed equation \] - # - # This subroutine checks for matches of the form - # - # \end{environmentname} - # or - # \] - # - # Note: environmentname can begin with a backslash - # which might happen in a sty or cls file. - # - # It also checks to see if the current environment - # had alignment delimiters; if so, we need to turn - # OFF the $delimiter switch - - return unless @masterIndentationArrayOfHashes; - print $logfile "Line $lineCounter\t looking for \\end{$masterIndentationArrayOfHashes[-1]{name}} \n" if($tracingMode); - - if( ($_ =~ m/^\s*\\end\{\\?(.*?)\}/ or $_=~ m/^(\\\])/) and $_ !~ m/\s*^%/) { - # check if we're at the end of a verbatim-like environment - if($verbatimEnvironments{$1}) { - $inverbatim = 0; - # tracing mode - - print $logfile "Line $lineCounter\t \\end{verbatim-like} found: $1, switching off verbatim \n" if($tracingMode); - print $logfile "Line $lineCounter\t removing leading spaces \n" if($tracingMode); - #s/^\ *//; - s/^\t+// if($_ ne ""); - s/^\s+// if($_ ne ""); - } - - # check if we're in an environment that is looking - # to indent after each \item - if(scalar(@masterIndentationArrayOfHashes) and $itemNames{$masterIndentationArrayOfHashes[-1]{name}}) { - &decrease_indent($masterIndentationArrayOfHashes[-1]{name}); - } - - # if we're at the end of an environment that receives no additional indent, log it, and move on - if($noAdditionalIndent{$1}){ - print $logfile "Line $lineCounter\t \\end{$1} finished a no-additional-indent environment (see noAdditionalIndent)\n" if($tracingMode); - } - - # some commands contain \end{environmentname}, which - # can cause a problem if \begin{environmentname} was not - # started previously; if @masterIndentationArrayOfHashes is empty, - # then we don't need to check for \end{environmentname} - if(@masterIndentationArrayOfHashes) { - # check to see if \end{environment} fits with most recent \begin{...} - my %previousEnvironment = %{$masterIndentationArrayOfHashes[-1]}; - - # check to see if we need to turn off alignment - # delimiters and output the current block - if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters} and ($previousEnvironment{name} eq $1)) { - &print_aligned_block(); - } - - # tracing mode - print $logfile "Line $lineCounter\t \\end{environment} found: $1 \n" if($tracingMode and !$verbatimEnvironments{$1}); - - # check to see if \end{environment} fits with most recent \begin{...} - if($previousEnvironment{name} eq $1) { - # decrease the indentation (if appropriate) - print $logfile "Line $lineCounter\t removed $1 from Indentation array\n" if($tracingMode); - &decrease_indent($1); - } else { - # otherwise put the environment name back on the stack - print $logfile "Line $lineCounter\t WARNING: \\end{$1} found on its own line, not matched to \\begin{$previousEnvironment{name}}\n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); - } - - # need a special check for \[ and \] - if($1 eq "\\\]") { - &decrease_indent($1); - } - } - - # if we're at the end of the document, we remove all current - # indentation- this is especially prominent in examples that - # have headings, and the user has chosen to indentAfterHeadings - if($1 eq "document" and !$inFileContents and !$inpreamble and !$delimiters and !$inverbatim and !$inIndentBlock and @masterIndentationArrayOfHashes) { - @masterIndentationArrayOfHashes=(); - - # tracing mode - if($tracingMode) { - print $logfile "Line $lineCounter\t \\end{$1} found, emptying indentation array \n" unless ($delimiters or $inverbatim or $inIndentBlock or $1 eq "\\\]"); - } - } - } -} - -sub print_aligned_block{ - # PURPOSE: this subroutine does a few things related - # to printing blocks of code that contain - # delimiters, such as align, tabular, etc - # - # It does the following - # - turns off delimiters switch - # - processes the block - # - deletes the block - $delimiters=0; - - # tracing mode - print $logfile "Line $lineCounter\t Delimiter body FINISHED: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - # print the current FORMATTED block - my @block = &format_block(@{$masterIndentationArrayOfHashes[-1]{block}}); - foreach $line (@block) { - # add the indentation and add the - # each line of the formatted block - # to the output - # unless this would only create trailing whitespace and the - # corresponding option is set - unless ($line =~ m/^$/ and $removeTrailingWhitespace) { - $line =¤t_indentation().$line; - } - push(@lines,$line); - } -} - -sub format_block{ - # PURPOSE: Format a delimited environment such as the - # tabular or align environment that contains & - # - # INPUT: @block array containing unformatted block - # from, for example, align, or tabular - # OUTPUT: @formattedblock array containing FORMATTED block - - # @block is the input - my @block=@_; - - # tracing mode - print $logfile "\t\tFormatting alignment block: $masterIndentationArrayOfHashes[-1]{name}\n" if($tracingMode); - - # step the line counter back to the beginning of the block- - # it will be increased back to the end of the block in the - # loop later on: foreach $row (@tmpblock) - $lineCounter -= scalar(@block); - - # local array variables - my @formattedblock; - my @tmprow=(); - my @tmpblock=(); - my @maxmstringsize=(); - my @ampersandCount=(); - - # local scalar variables - my $alignrowcounter=-1; - my $aligncolcounter=-1; - my $tmpstring; - my $row; - my $column; - my $maxmcolstrlength; - my $i; - my $j; - my $fmtstring; - my $linebreak; - my $maxNumberAmpersands = 0; - my $currentNumberAmpersands; - my $trailingcomments; - - # local hash table - my %stringsize=(); - - # loop through the block and count & per line- store the biggest - # NOTE: this needs to be done in its own block so that - # we can know what the maximum number of & in the block is - foreach $row (@block) { - # delete trailing comments - $trailingcomments=''; - if($row =~ m/((? $maxNumberAmpersands ); - - # put trailing comments back on - if($trailingcomments){ - $row =~ s/%TC/$trailingcomments/; - } - } - - # tracing mode - print $logfile "\t\tmaximum number of & in any row: $maxNumberAmpersands\n" if($tracingMode); - - # loop through the lines in the @block - foreach $row (@block){ - # get the ampersand count - $currentNumberAmpersands = shift(@ampersandCount); - - # increment row counter - $alignrowcounter++; - - # clear the $linebreak variable - $linebreak=''; - - # check for line break \\ - # and don't mess with a line that doesn't have the maximum - # number of & - if($row =~ m/\\\\/ and $currentNumberAmpersands==$maxNumberAmpersands ) { - # remove \\ and all characters that follow - # and put it back in later, once the measurement - # has been done - $row =~ s/(\\\\.*)//; - $linebreak = $1; - } - - if($currentNumberAmpersands==$maxNumberAmpersands) { - - # remove trailing comments - $trailingcomments=''; - if($row =~ m/((?$maxmcolstrlength) { - $maxmcolstrlength = $stringsize{$i.$j}; - } - } - } - push(@maxmstringsize,$maxmcolstrlength); - } - - # README: printf( formatting, expression) - # - # formatting has the form %-50s & %-20s & %-19s - # (the numbers have been made up for example) - # the - symbols mean that each column should be left-aligned - # the numbers represent how wide each column is - # the s represents string - # the & needs to be inserted - - # join up the maximum string lengths using "s %-" - $fmtstring = join("s & %-",@maxmstringsize); - - # add an s to the end, and a newline - $fmtstring .= "s "; - - # add %- to the beginning - $fmtstring = "%-".$fmtstring; - - # process the @tmpblock of aligned material - foreach $row (@tmpblock) { - $linebreak=''; - # check for line break \\ - if($row =~ m/\\\\/) { - # remove \\ and all characters that follow - # and put it back in later - $row =~ s/(\\\\.*$)//; - $linebreak = $1; - } - - if($row =~ m/NOFORMATTING/) { - $row =~ s/NOFORMATTING//; - $tmpstring=$row; - - # tracing mode - print $logfile "\t\tLine $lineCounter\t maximum number of & NOT found- not aligning delimiters \n" if($tracingMode); - } else { - # remove trailing comments - $trailingcomments=''; - if($row =~ m/((?1?"spaces":"space"," before \\\\ (see $masterIndentationArrayOfHashes[-1]{name} spacesBeforeDoubleBackSlash)\n" if($tracingMode); - $tmpstring =~ s/\\\\/$spaceString\\\\/; - } - } - - # put trailing comments back on - if($trailingcomments) { - $tmpstring =~ s/%TC/$trailingcomments/; - } - - # tracing mode - print $logfile "\t\tLine $lineCounter\t Found maximum number of & so aligning delimiters\n" if($tracingMode); - } - - # remove trailing whitespace - if ($removeTrailingWhitespace) { - print $logfile "\t\tLine $lineCounter\t removing trailing whitespace from delimiter aligned line\n" if ($tracingMode); - $tmpstring =~ s/\s+$/\n/; - } - - push(@formattedblock,$tmpstring); - - # increase the line counter - $lineCounter++; - } - - # return the formatted block - @formattedblock; -} - -sub increase_indent{ - # PURPOSE: Adjust the indentation - # of the current environment, command, etc; - # check that it's not an environment - # that doesn't want indentation. - - my %infoHash = %{pop(@_)}; - my $command = $infoHash{name}; - - # check for conflicting hash keys - &check_conflicting_keys($command); - - # quick check for verbatim Environment - if($inverbatim){ - print $logfile "Line $lineCounter\t currently inverbatim environment, not increasing indentation\n" if($tracingMode); - return; - } - - if($indentRules{$command}) { - # tracing mode - print $logfile "Line $lineCounter\t increasing indent using rule for $command (see indentRules)\n" if($tracingMode); - } else { - # default indentation - if(!($noAdditionalIndent{$command} or $verbatimEnvironments{$command})) { - # tracing mode - print $logfile "Line $lineCounter\t increasing indent using defaultIndent\n" if($tracingMode); - } elsif($noAdditionalIndent{$command}) { - # tracing mode - print $logfile "Line $lineCounter\t no additional indent added for $command (see noAdditionalIndent)\n" if($tracingMode); - } - } - - # add to the master array of hashes - push(@masterIndentationArrayOfHashes,\%infoHash); - - # handle the keys slightly different when dealing with environments or commands - if($infoHash{type} eq 'environment'){ - # environments - if(!$noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent; - } - # check to see if we need to look for alignment delimiters - if($lookForAlignDelims{$command}){ - # there are two ways to complete the lookForAlignDelims field, either as a scalar - # or as a hash, so that we can check for alignDoubleBackSlash. - # - # tabular: - # delims: 1 - # alignDoubleBackSlash: 1 - # - # or, simply, - # - # tabular: 1 - # - # We need to perform a check to see which has been done. - if(ref($lookForAlignDelims{$command}) eq 'HASH'){ - # tabular: - # delims: 1 - # alignDoubleBackSlash: 1 - $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=defined $lookForAlignDelims{$command}{delims}?$lookForAlignDelims{$command}{delims}:1; - $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=defined $lookForAlignDelims{$command}{alignDoubleBackSlash}?$lookForAlignDelims{$command}{alignDoubleBackSlash}:1; - $masterIndentationArrayOfHashes[-1]{spacesBeforeDoubleBackSlash}=$lookForAlignDelims{$command}{spacesBeforeDoubleBackSlash}||0; - } else { - # tabular: 1 - $masterIndentationArrayOfHashes[-1]{alignmentDelimiters}=1; - $masterIndentationArrayOfHashes[-1]{alignDoubleBackSlash}=1; - } - if($masterIndentationArrayOfHashes[-1]{alignmentDelimiters}==1){ - # tracing mode - print $logfile "Line $lineCounter\t Delimiter environment started: $command (see lookForAlignDelims)\n" if($tracingMode); - } - } - } else { - # commands, headings, etc - if(!$noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{indent} = $indentRules{$command}||$defaultIndent; - } - } - - # details of noAdditionalIndent to the main hash - if($noAdditionalIndent{$command}){ - $masterIndentationArrayOfHashes[-1]{noAdditionalIndent} = 'yes'; - } -} - -sub decrease_indent{ - # PURPOSE: Adjust the indentation - # of the current environment; - # check that it's not an environment - # that doesn't want indentation. - - # if there is no evidence of indentation, then return - return unless(scalar(@masterIndentationArrayOfHashes)); - - # otherwise get details of the most recent command, environment, item, if, heading, etc - my $command = pop(@_); - - if(!$inverbatim) { - print $logfile "Line $lineCounter\t removing ", $masterIndentationArrayOfHashes[-1]{name}, " from masterIndentationArrayOfHashes\n" if($tracingMode); - pop(@masterIndentationArrayOfHashes); - # tracing mode - if($tracingMode) { - if(@masterIndentationArrayOfHashes) { - print $logfile "Line $lineCounter\t decreasing masterIndentationArrayOfHashes to: ",¤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/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index cee413d00d4..39b4d22daac 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -1236,6 +1236,7 @@ chomp ($Build = `cd $Master/../Build/source && pwd`); 'ktv-texdata' => '&PREHOOK_ktv_texdata', 'latex-git-log' => '&PREHOOK_latex_git_log', 'latexdiff' => '&PREHOOK_latexdiff', + 'latexindent' => '&PREHOOK_latexindent', 'lilyglyphs' => '&PREHOOK_lilyglyphs', 'lollipop' => '&PREHOOK_flatten1', 'mathspic' => '&PREHOOK_mathspic', @@ -2727,7 +2728,7 @@ $standardttf = '\.ttf|\.TTC'; 'epspdf' => '(epspdf(|\.help|boot|tk)|\.rb|makegray\.pro)$', 'latex2nemeth' => '\.jar$', 'latex-make' => '\.py$', - 'latexindent' => 'Settings\.yaml$', + 'latexindent' => 'LatexIndent|\.yaml$', 'lilyglyphs' => 'lilyglyphs_common.py', 'lua-alt-getopt' => '\.lua$', 'lua2dox' => '\.(lua|def)$', @@ -5200,6 +5201,11 @@ sub PREHOOK_latexdiff { &SYSTEM ("$MV latexdiff-vc latexdiff-vc.pl"); } +sub PREHOOK_latexindent { + print "PREHOOK_$package - mv documentation/* doc\n"; + &SYSTEM ("$MV documentation/* ."); +} + sub PREHOOK_lilyglyphs { print "PREHOOK_$package - mv */*.py scripts for specialscripts, rm ~\n"; &SYSTEM ("$MV scripts/* ."); -- cgit v1.2.3