summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm')
-rw-r--r--Master/texmf-dist/scripts/latexindent/LatexIndent/AlignmentAtAmpersand.pm255
1 files changed, 255 insertions, 0 deletions
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{<something>} 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 = () = $_ =~ /(?<!\\)&/g;
+ $maximumNumberOfAmpersands = $numberOfAmpersands if($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 = () = $_ =~ /(?<!\\)&/g;
+ if($numberOfAmpersands == $maximumNumberOfAmpersands){
+ # remove any trailing comments
+ my $trailingComments;
+ if($_ =~ m/$trailingCommentRegExp/ ){
+ $_ =~ s/($trailingCommentRegExp)//;
+ $trailingComments = $1;
+ }
+
+ # if the line finishes with an &, then add an empty space,
+ # otherwise the column count is off
+ $_ .= ($_ =~ m/(?<!\\)&$/ ? " ":q());
+
+ # loop through the columns
+ my $columnCount = 0;
+ my $strippedRow = '';
+ foreach my $column (split(/(?<!\\)&/,$_)){
+ # remove leading space
+ $column =~ s/^\h*//;
+
+ # remove trailing space
+ $column =~ s/\h*$//;
+
+ # if a column has finished with a \ then we need to add a trailing space,
+ # otherwise the \ can be put next to &. See test-cases/texexchange/112343-gonzalo for example
+ $column .= ($column =~ m/\\$/ ? " ": q());
+
+ # store the column size
+ $columnSizes[$columnCount] = length($column) if(length($column)>$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(/(?<!\\)&/,${$_}{row})).(${$_}{endPiece} ? ${$_}{endPiece} :q() ).(${$_}{trailingComment}? ${$_}{trailingComment} : q() );
+
+ # possibly remove space ahead of \\
+ ${$_}{row} =~ s/\h*\\\\/\\\\/ if(!${$self}{alignDoubleBackSlash});
+
+ # possibly insert spaces infront of \\
+ if(defined ${$self}{spacesBeforeDoubleBackSlash} and ${$self}{spacesBeforeDoubleBackSlash}>=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;