diff options
author | Karl Berry <karl@freefriends.org> | 2017-08-22 21:26:11 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-08-22 21:26:11 +0000 |
commit | e231f2be95092edeb9fdef8644d3703c56656433 (patch) | |
tree | 35170ff1259e003c847a2953bbd4a316ef36f8de /Master/texmf-dist/scripts/latexindent | |
parent | 5b86a262bc6cd64f5fb9f93028dc3e2762361822 (diff) |
latexindent (22aug17)
git-svn-id: svn://tug.org/texlive/trunk@45098 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/latexindent')
21 files changed, 569 insertions, 266 deletions
diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm index 569cead9584..9643bf11375 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Arguments.pm @@ -142,19 +142,23 @@ sub find_opt_mand_arguments{ 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(); + # possibly add a comment or a blank line, depending on if BeginStartsOnOwnLine == 2 or 3 respectively + # at the end of the begin statement + my $trailingCharacterToken = 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; + $trailingCharacterToken = "%".$self->add_comment_symbol; $self->logger("Removing trailing space on ${$self}{begin}") if $is_t_switch_active; ${$self}{begin} =~ s/\h*$//s; + } elsif (${${${$arguments}{children}}[0]}{BeginStartsOnOwnLine}==3) { + $self->logger("Adding a blank line immediately ${$self}{begin} ($BeginStringLogFile==3)") if $is_t_switch_active; + $trailingCharacterToken = "\n".(${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:q()); } # modification - ${$self}{begin} .= "$trailingCommentToken\n"; + ${$self}{begin} .= "$trailingCharacterToken\n"; ${$self}{linebreaksAtEnd}{begin} = 1; } } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm index f4572dd6797..7f5c5b63cca 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/BlankLines.pm @@ -87,19 +87,18 @@ sub unprotect_blank_lines{ my $blankLineToken = $tokens{blanklines}; # loop through the body, looking for the blank line token - while(${$self}{body} =~ m/$blankLineToken/m){ + while(${$self}{body} =~ m/$blankLineToken/s){ # 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}{body} =~ s/^\h*$blankLineToken$//mg; + + # when there's stuff *after* the blank line token + ${$self}{body} =~ s/(^\h*)$blankLineToken/"\n".$1/meg; + + # when there is stuff before and after the blank line token + ${$self}{body} =~ s/^(.*?)$blankLineToken\h*(.*?)\h*$/$1."\n".($2?"\n".$2:$2)/meg; + + # when there is only stuff *after* the blank line token + ${$self}{body} =~ s/^$blankLineToken\h*(.*?)$/$1."\n"/emg; } $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); diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm index 70712a03626..db876c4c8c5 100755 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Command.pm @@ -43,11 +43,28 @@ sub construct_command_regexp{ mode=>"lineBreaksAtEnd", stringBetweenArguments=>1); + # put together a list of the special command names (this was mostly motivated by the \@ifnextchar[ issue) + my %commandNameSpecial = %{${$masterSettings{commandCodeBlocks}}{commandNameSpecial}}; + + my $commandNameSpecialRegExp = q(); + while( my ($commandName,$yesNo)= each %commandNameSpecial){ + # change + and - to escaped characters + $commandName =~ s/\+/\\+/g; + $commandName =~ s/\-/\\-/g; + $commandName =~ s/\[/\\[/g; + + # form the regexp + $commandNameSpecialRegExp .= ($commandNameSpecialRegExp eq '' ? q() : "|").$commandName if $yesNo; + } + + # details to log file + $self->logger("The special command names regexp is: $commandNameSpecialRegExp (see commandNameSpecial)",'heading') if $is_t_switch_active; + # construct the command regexp $commandRegExp = qr/ - (\\|@) + (\\|\\@|@) ( - [+a-zA-Z@\*0-9_\:]+? # lowercase|uppercase letters, @, *, numbers + [+a-zA-Z@\*0-9_\:]+?|$commandNameSpecialRegExp # lowercase|uppercase letters, @, *, numbers ) (\h*) (\R*)? @@ -104,6 +121,13 @@ sub tasks_particular_to_each_object{ ${${$self}{linebreaksAtEnd}}{end} = ${${${${${$self}{children}}[0]}{children}[-1]}{linebreaksAtEnd}}{end}; ${$self}{replacementText} .= "\n"; + # if the last argument has EndFinishesWithLineBreak == 3 + if (${${${${$self}{children}}[0]}{children}[-1]}{EndFinishesWithLineBreak} == 3 ){ + my $EndStringLogFile = ${${${${$self}{children}}[0]}{children}[-1]}{aliases}{EndFinishesWithLineBreak}||"EndFinishesWithLineBreak"; + $self->logger("Adding another blank line to replacement text for ${$self}{name} as last argument has $EndStringLogFile == 3 ") if $is_t_switch_active; + ${$self}{replacementText} .= (${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:"\n")."\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; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm index 93d8c404928..8697c20e86c 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm @@ -30,7 +30,7 @@ use LatexIndent::BlankLines qw/protect_blank_lines unprotect_blank_lines condens use LatexIndent::ModifyLineBreaks qw/modify_line_breaks_body modify_line_breaks_end remove_line_breaks_begin adjust_line_breaks_end_parent max_char_per_line paragraphs_on_one_line construct_paragraph_reg_exp/; 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::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 post_indentation_check/; 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/; @@ -39,7 +39,8 @@ use LatexIndent::DoubleBackSlash qw/dodge_double_backslash un_dodge_double_backs # 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::IfElseFi qw/find_ifelsefi construct_ifelsefi_regexp/; +use LatexIndent::Else qw/check_for_else_statement/; 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/; @@ -109,6 +110,7 @@ sub operate_on_file{ sub construct_regular_expressions{ my $self = shift; $self->construct_trailing_comment_regexp; + $self->construct_ifelsefi_regexp; $self->construct_list_of_items; $self->construct_special_begin; $self->construct_headings_levels; @@ -171,25 +173,20 @@ sub find_objects{ my $self = shift; # search for environments - $self->logger('looking for ENVIRONMENTS'); + $self->logger('looking for ENVIRONMENTS') if $is_t_switch_active; $self->find_environments; # search for ifElseFi blocks - $self->logger('looking for IFELSEFI'); + $self->logger('looking for IFELSEFI') if $is_t_switch_active; $self->find_ifelsefi; # search for headings (part, chapter, section, setc) - $self->logger('looking for HEADINGS (chapter, section, part, etc)'); + $self->logger('looking for HEADINGS (chapter, section, part, etc)') if $is_t_switch_active; $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; + # the ordering of finding commands and special code blocks can change + $self->find_commands_or_key_equals_values_braces_and_special; + # documents without preamble need a manual call to the paragraph_one_line routine if ($is_m_switch_active and !${$self}{preamblePresent}){ ${$self}{removeParagraphLineBreaks} = ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{all}||${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{masterDocument}||0; @@ -198,7 +195,7 @@ sub find_objects{ # if there are no children, return if(${$self}{children}){ - $self->logger("Objects have been found.",'heading'); + $self->logger("Objects have been found.",'heading') if $is_t_switch_active; } else { $self->logger("No objects found."); return; @@ -206,10 +203,34 @@ sub find_objects{ # 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}})); + $self->logger("Operating on: ${$self}{name}",'heading')if $is_t_switch_active; + $self->logger("Number of children: ".scalar (@{${$self}{children}})) if $is_t_switch_active; + + return; +} +sub find_commands_or_key_equals_values_braces_and_special{ + my $self = shift; + + # the order in which we search for specialBeginEnd and commands/key/braces + # can change depending upon specialBeforeCommand + if(${$masterSettings{specialBeginEnd}}{specialBeforeCommand}){ + # search for special begin/end + $self->logger('looking for SPECIAL begin/end *before* looking for commands (see specialBeforeCommand)') if $is_t_switch_active; + $self->find_special; + + # search for commands with arguments + $self->logger('looking for COMMANDS and key = {value}') if $is_t_switch_active; + $self->find_commands_or_key_equals_values_braces; + } else { + # search for commands with arguments + $self->logger('looking for COMMANDS and key = {value}') if $is_t_switch_active; + $self->find_commands_or_key_equals_values_braces; + + # search for special begin/end + $self->logger('looking for SPECIAL begin/end') if $is_t_switch_active; + $self->find_special; + } return; } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Else.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Else.pm new file mode 100644 index 00000000000..878a68dc1cb --- /dev/null +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Else.pm @@ -0,0 +1,109 @@ +package LatexIndent::Else; +# 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/check_for_else_statement/; +our $elseCounter; + +# store the regular expresssion for matching and replacing the \else statements +our $elseRegExp = qr/ + ( + \\else + \h* # possible horizontal space + (\R*) # possible line breaks after \else statement + ) + (.*?)$ + /sx; + +sub check_for_else_statement{ + my $self = shift; + $self->logger("Looking for \\else statement (${$self}{name})",'heading') if $is_t_switch_active; + + ${$self}{body} =~ s/$elseRegExp(\h*)($trailingCommentRegExp)? + / # log file output + $self->logger("else found: ${$self}{name}",'heading')if $is_t_switch_active; + + # create a new IfElseFi object + my $else = LatexIndent::Else->new(begin=>$1, + name=>${$self}{name}, + storageNameAppend=>"else", + body=>$3, + end=>q(), + linebreaksAtEnd=>{ + begin=>$2?1:0, + body=>0, + end=>0, + }, + aliases=>{ + # begin statements + BeginStartsOnOwnLine=>"ElseStartsOnOwnLine", + # end statements + BodyStartsOnOwnLine=>"ElseFinishesWithLineBreak", + }, + modifyLineBreaksYamlName=>"ifElseFi", + endImmediatelyFollowedByComment=>0, + horizontalTrailingSpace=>q(), + ); + # the settings and storage of most objects has a lot in common + $self->get_settings_and_store_new_object($else); + ${@{${$self}{children}}[-1]}{replacementText}; + /xse; + return; +} + +sub remove_line_breaks_begin{ + # the \else 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; +} + +sub tasks_particular_to_each_object{ + my $self = shift; + + # search for headings (important to do this before looking for commands!) + $self->find_heading; + + # search for commands and special code blocks + $self->find_commands_or_key_equals_values_braces_and_special; + return; +} + +sub get_indentation_information{ + return q(); +} + +sub create_unique_id{ + my $self = shift; + + $elseCounter++; + + ${$self}{id} = "$tokens{else}$elseCounter"; + return; +} + +1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm index 2f6afe07e4b..0dd2fa80174 100755 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Environment.pm @@ -103,8 +103,8 @@ sub tasks_particular_to_each_object{ # 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 commands and special code blocks + $self->find_commands_or_key_equals_values_braces_and_special; # search for arguments $self->find_opt_mand_arguments; @@ -112,8 +112,6 @@ sub tasks_particular_to_each_object{ # search for ifElseFi blocks $self->find_ifelsefi; - # search for special begin/end - $self->find_special; } sub create_unique_id{ diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm index d4d13507a13..802b2a1ef9d 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/FileContents.pm @@ -34,11 +34,11 @@ sub find_file_contents_environments_and_preamble{ my @fileContentsStorageArray; # fileContents environments - $self->logger('looking for FILE CONTENTS environments (see fileContentsEnvironments)','heading'); + $self->logger('looking for FILE CONTENTS environments (see fileContentsEnvironments)','heading') if $is_t_switch_active; $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"); + $self->logger("looking for $fileContentsEnv:$yesno environments") if $is_t_switch_active; # the trailing * needs some care if($fileContentsEnv =~ m/\*$/){ @@ -119,7 +119,7 @@ sub find_file_contents_environments_and_preamble{ # 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"); + $self->logger("\\begin{document} found in body (after searching for filecontents)-- assuming that a preamble exists",'heading') if $is_t_switch_active ; # create a preamble object $preamble = LatexIndent::Preamble->new( begin=>q(), @@ -142,19 +142,19 @@ sub find_file_contents_environments_and_preamble{ $preamble->get_replacement_text; # log file output - $self->logger("preamble found: $preamble"); + $self->logger("preamble found: $preamble") if $is_t_switch_active; # remove the environment block, and replace with unique ID ${$self}{body} =~ s/$preambleRegExp/${$preamble}{replacementText}/sx; - $self->logger("replaced with ID: ${$preamble}{replacementText}"); + $self->logger("replaced with ID: ${$preamble}{replacementText}") if $is_t_switch_active; # 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)"); + $self->logger("NOT storing ${$preamble}{id} for indentation -- will store as VERBATIM object (see indentPreamble)") if $is_t_switch_active; $preamble->unprotect_blank_lines; ${$self}{verbatim}{${$preamble}{id}} = $preamble; } @@ -220,13 +220,8 @@ sub tasks_particular_to_each_object{ # 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; - - + # search for commands and special code blocks + $self->find_commands_or_key_equals_values_braces_and_special; } 1; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm index 0d51d5837db..bb0e47f2576 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm @@ -36,7 +36,7 @@ sub readSettings{ my $self = shift; $defaultSettings = YAML::Tiny->read( "$FindBin::RealBin/defaultSettings.yaml" ); - $self->logger("YAML settings read",'heading'); + $self->logger("YAML settings read: defaultSettings.yaml",'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 @@ -60,6 +60,7 @@ sub readSettings{ # we'll need the home directory a lot in what follows my $homeDir = File::HomeDir->my_home; + $self->logger("YAML settings read: indentconfig.yaml or .indentconfig.yaml",'heading'); # get information about user settings- first check if indentconfig.yaml exists my $indentconfig = "$homeDir/indentconfig.yaml"; @@ -91,7 +92,9 @@ sub readSettings{ 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}); + $self->logger("Ignoring the -y switch: $switches{yaml} (you used the -d switch)") if($switches{yaml}); $switches{readLocalSettings}=0; + $switches{yaml}=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)"); @@ -100,11 +103,6 @@ sub readSettings{ } } - # get information about LOCAL settings, assuming that $readLocalSettings exists - my $directoryName = dirname (${$self}{fileName}); - - my @localSettings; - # local settings can be called with a + symbol, for example # -l=+myfile.yaml # -l "+ myfile.yaml" @@ -117,6 +115,14 @@ sub readSettings{ # and # -l + myfile.yaml # will *only* load localSettings.yaml, and myfile.yaml will be ignored + my @localSettings; + + $self->logger("YAML settings read: -l switch",'heading') if $switches{readLocalSettings}; + + # remove leading, trailing, and intermediate space + $switches{readLocalSettings} =~ s/^\h*//g; + $switches{readLocalSettings} =~ s/\h*$//g; + $switches{readLocalSettings} =~ s/\h*,\h*/,/g; if($switches{readLocalSettings} =~ m/\+/){ $self->logger("+ found in call for -l switch: will add localSettings.yaml"); @@ -132,7 +138,7 @@ sub readSettings{ # -l = myyaml1.yaml,myyaml2.yaml # and in which case, we need to read them all if($switches{readLocalSettings} =~ m/,/){ - $self->logger("Multiple localSettings found, separated by commas:",'heading'); + $self->logger("Multiple localSettings found, separated by commas:"); @localSettings = split(/,/,$switches{readLocalSettings}); } else { push(@localSettings,$switches{readLocalSettings}) if($switches{readLocalSettings}); @@ -141,21 +147,30 @@ sub readSettings{ # add local settings to the paths, if appropriate foreach (@localSettings) { # check for an extension (.yaml) - my ($dir, $name, $ext) = fileparse($_, "yaml"); + my ($name, $dir , $ext) = fileparse($_, "yaml"); # if no extension is found, append the current localSetting with .yaml $_ = $_.($_=~m/\.\z/ ? q() : ".")."yaml" if(!$ext); + # if the -l switch is called on its own, or else with + + # and latexindent.pl is called from a different directory, then + # we need to account for this + if($_ eq "localSettings.yaml"){ + $_ = dirname (${$self}{fileName})."/".$_; + } + # check for existence and non-emptiness - 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."); + if ( (-e $_) and !(-z $_)) { + $self->logger("Adding $_ to YAML read paths"); + push(@absPaths,"$_"); + } elsif ( !(-e $_) ) { + $self->logger("WARNING yaml file not found: $_ not found. Proceeding without it."); } } + # heading for the log file + $self->logger("YAML settings, reading from the following files:",'heading') if @absPaths; + # read in the settings from each file foreach my $settings (@absPaths) { # check that the settings file exists and that it isn't empty @@ -221,6 +236,145 @@ sub readSettings{ } } + # read settings from -y|--yaml switch + if($switches{yaml}){ + # report to log file + $self->logger("YAML settings read: -y switch",'heading'); + + # remove any horizontal space before or after , OR : OR ; or at the beginning or end of the switch value + $switches{yaml} =~ s/\h*(,|:|;)\h*/$1/g; + $switches{yaml} =~ s/^\h*//g; + + # store settings, possibly multiple ones split by commas + my @yamlSettings; + if($switches{yaml} =~ m/,/){ + @yamlSettings = split(/,/,$switches{yaml}); + } else { + push(@yamlSettings,$switches{yaml}); + } + + # it is possible to specify, for example, + # + # -y=indentAfterHeadings:paragraph:indentAfterThisHeading:1;level:1 + # -y=specialBeginEnd:displayMath:begin:'\\\[';end: '\\\]';lookForThis: 1 + # + # which should be translated into + # + # indentAfterHeadings: + # paragraph: + # indentAfterThisHeading:1 + # level:1 + # + # so we need to loop through the comma separated list and search + # for semi-colons + my $settingsCounter=0; + my @originalYamlSettings = @yamlSettings; + foreach(@originalYamlSettings){ + # increment the counter + $settingsCounter++; + + # check for a match of the ; + if($_ =~ m/;/){ + my (@subfield) = split(/;/,$_); + + # the content up to the first ; is called the 'root' + my $root = shift @subfield; + + # split the root at : + my (@keysValues) = split(/:/,$root); + + # get rid of the last *two* elements, which will be + # key: value + # for example, in + # -y=indentAfterHeadings:paragraph:indentAfterThisHeading:1;level:1 + # then @keysValues holds + # indentAfterHeadings:paragraph:indentAfterThisHeading:1 + # so we need to get rid of both + # 1 + # indentAfterThisHeading + # so that we are in a position to concatenate + # indentAfterHeadings:paragraph + # with + # level:1 + # to form + # indentAfterHeadings:paragraph:level:1 + pop(@keysValues); + pop(@keysValues); + + # update the appropriate piece of the -y switch, for example: + # -y=indentAfterHeadings:paragraph:indentAfterThisHeading:1;level:1 + # needs to be changed to + # -y=indentAfterHeadings:paragraph:indentAfterThisHeading:1 + # the + # indentAfterHeadings:paragraph:level:1 + # will be added in the next part + $yamlSettings[$settingsCounter-1] = $root; + + # reform the root + $root = join(":",@keysValues); + $self->logger("Sub-field detected (; present) and the root is: $root") if $is_t_switch_active; + + # now we need to attach the $root back together with any subfields + foreach(@subfield){ + # splice the new field into @yamlSettings (reference: https://perlmaven.com/splice-to-slice-and-dice-arrays-in-perl) + splice @yamlSettings,$settingsCounter,0,$root.":".$_; + + # increment the counter + $settingsCounter++; + } + $self->logger("-y switch value interpreted as: ".join(',',@yamlSettings)); + } + } + + # loop through each of the settings specified in the -y switch + foreach(@yamlSettings){ + # split each value at semi-colon + my (@keysValues) = split(/:/,$_); + + # $value will always be the last element + my $value = $keysValues[-1]; + + # horizontal space needs special treatment + if($value =~ m/^(?:"|')(\h*)(?:"|')$/){ + # pure horizontal space + $value = $1; + } elsif($value =~ m/^(?:"|')((?:\\t)*)(?:"|')$/){ + # tabs + $value =~ s/^(?:"|')//; + $value =~ s/(?:"|')$//; + $value =~ s/\\t/\t/g; + } + + if(scalar(@keysValues) == 2){ + # for example, -y="defaultIndent: ' '" + my $key = $keysValues[0]; + $self->logger("Updating masterSettings with $key: $value"); + $masterSettings{$key} = $value; + } elsif(scalar(@keysValues) == 3){ + # for example, -y="indentRules: one: '\t\t\t\t'" + my $parent = $keysValues[0]; + my $child = $keysValues[1]; + $self->logger("Updating masterSettings with $parent: $child: $value"); + $masterSettings{$parent}{$child} = $value; + } elsif(scalar(@keysValues) == 4){ + # for example, -y='modifyLineBreaks : environments: EndStartsOnOwnLine:3' -m + my $parent = $keysValues[0]; + my $child = $keysValues[1]; + my $grandchild = $keysValues[2]; + $self->logger("Updating masterSettings with $parent: $child: $grandchild: $value"); + $masterSettings{$parent}{$child}{$grandchild} = $value; + } elsif(scalar(@keysValues) == 5){ + # for example, -y='modifyLineBreaks : environments: one: EndStartsOnOwnLine:3' -m + my $parent = $keysValues[0]; + my $child = $keysValues[1]; + my $grandchild = $keysValues[2]; + my $greatgrandchild = $keysValues[3]; + $self->logger("Updating masterSettings with $parent: $child: $grandchild: $greatgrandchild: $value"); + $masterSettings{$parent}{$child}{$grandchild}{$greatgrandchild} = $value; + } + } + } + # some users may wish to see showAmalgamatedSettings # which details the overall state of the settings modified # from the default in various user files @@ -236,7 +390,7 @@ sub get_indentation_settings_for_this_object{ my $self = shift; # create a name for previously found settings - my $storageName = ${$self}{name}.${$self}{modifyLineBreaksYamlName}; + my $storageName = ${$self}{name}.${$self}{modifyLineBreaksYamlName}.(defined ${$self}{storageNameAppend}?${$self}{storageNameAppend}:q()); # check for storage of repeated objects if ($previouslyFoundSettings{$storageName}){ @@ -371,8 +525,10 @@ sub modify_line_breaks_settings{ $self->logger("$YamlName specified with fields in removeParagraphLineBreaks, looking for $name") if $is_t_switch_active; ${$self}{removeParagraphLineBreaks} = ${${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}}{$name}||0; } else { - $self->logger("$YamlName specified with just a number in removeParagraphLineBreaks ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}") if $is_t_switch_active; - ${$self}{removeParagraphLineBreaks} = ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}; + if(defined ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}){ + $self->logger("$YamlName specified with just a number in removeParagraphLineBreaks ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}") if $is_t_switch_active; + ${$self}{removeParagraphLineBreaks} = ${$masterSettings{modifyLineBreaks}{removeParagraphLineBreaks}}{$YamlName}; + } } return; } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm index 6cca3c26695..9a2f7187531 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Heading.pm @@ -86,7 +86,7 @@ sub construct_headings_levels{ # make the stars escaped correctly $headingsAtThisLevel =~ s/\*/\\\*/g; push(@headingsRegexpArray,$headingsAtThisLevel); - $self->logger("Heading level regexp for level $i will contain: $headingsAtThisLevel"); + $self->logger("Heading level regexp for level $i will contain: $headingsAtThisLevel") if $is_t_switch_active; } } } @@ -99,7 +99,7 @@ sub find_heading{ my $self = shift; # otherwise loop through the headings regexp - $self->logger("Searching for special begin/end (see specialBeginEnd)"); + $self->logger("Searching for headings ") if $is_t_switch_active; # 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 diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm index 04753f81a87..5e4040d5cef 100755 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/IfElseFi.pm @@ -22,13 +22,15 @@ use LatexIndent::Switches qw/$is_m_switch_active $is_t_switch_active $is_tt_swit 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 @EXPORT_OK = qw/find_ifelsefi construct_ifelsefi_regexp/; our $ifElseFiCounter; +our $ifElseFiRegExp; # 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/ + +sub construct_ifelsefi_regexp{ + $ifElseFiRegExp = qr/ ( \\ (@?if[a-zA-Z@]*?) @@ -36,7 +38,7 @@ our $ifElseFiRegExp = qr/ (\R*) ) # begin statement, e.g \ifnum, \ifodd ( - \\(?!if)|[0-9]|\R|\h|\#|!-! # up until a \\, linebreak # or !-!, which is + \\(?!if)|[0-9]|\R|\h|\#|!-!|$trailingCommentRegExp # up until a \\, linebreak # or !-!, which is ) # part of the tokens used for latexindent ( (?: @@ -50,63 +52,6 @@ our $ifElseFiRegExp = qr/ (\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{ @@ -139,9 +84,7 @@ sub find_ifelsefi{ # after end statements EndFinishesWithLineBreak=>"FiFinishesWithLineBreak", }, - elsePresent=>0, modifyLineBreaksYamlName=>"ifElseFi", - additionalAssignments=>["ElseStartsOnOwnLine","ElseFinishesWithLineBreak"], endImmediatelyFollowedByComment=>$9?0:($11?1:0), horizontalTrailingSpace=>$8?$8:q(), ); @@ -154,6 +97,19 @@ sub find_ifelsefi{ return; } +sub post_indentation_check{ + # needed to remove leading horizontal space before \else + my $self = shift; + if(${$self}{body} =~ m/^\h*\\else/sm + and + !(${$self}{body} =~ m/^\h*\\else/s and ${$self}{linebreaksAtEnd}{begin}==0) + ){ + $self->logger("Adding surrounding indentation to \\else statement ('${$self}{surroundingIndentation}')") if $is_t_switch_active; + ${$self}{body} =~ s/^\h*\\else/${$self}{surroundingIndentation}\\else/sm; + } + return; +} + sub tasks_particular_to_each_object{ my $self = shift; @@ -163,20 +119,50 @@ sub tasks_particular_to_each_object{ # 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 commands and special code blocks + $self->find_commands_or_key_equals_values_braces_and_special; - # search for arguments - $self->find_opt_mand_arguments; +} - # search for ifElseFi blocks - $self->find_ifelsefi; +sub indent_begin{ + my $self = shift; + # 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} .= " "; + } +} - # search for special begin/end - $self->find_special; +sub wrap_up_statement{ + my $self = shift; + # 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}." "; + } + $self->logger("Finished indenting ${$self}{name}",'heading') if $is_t_switch_active; + return $self; } + sub create_unique_id{ my $self = shift; @@ -186,91 +172,5 @@ sub create_unique_id{ 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 index f0cf33aa23f..c9d05269d92 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Indent.pm @@ -19,9 +19,11 @@ 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 LatexIndent::GetYamlSettings qw/%masterSettings/; +use Text::Tabs; 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 @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 post_indentation_check/; our %familyTree; sub indent{ @@ -152,13 +154,15 @@ sub indent_body{ } } + # some objects need a post-indentation check, e.g ifElseFi + $self->post_indentation_check; # 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); + if($is_m_switch_active and defined ${$self}{linebreaksAtEnd}{body} and ${$self}{linebreaksAtEnd}{body}==1 and ${$self}{body} !~ m/\R$/ and ${$self}{body} ne ''){ + $self->logger("Adding a linebreak at end of 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"; } @@ -167,6 +171,10 @@ sub indent_body{ return $self; } +sub post_indentation_check{ + return; +} + sub check_for_blank_lines_at_beginning{ # some objects need this routine return; @@ -221,9 +229,26 @@ sub final_indentation_check{ $after = "TAB"x$numberOfTABS.$after; $self->logger("Indentation after: '$after'") if($is_t_switch_active); ($indentation = $after) =~s|TAB|\t|g; + $indentation; /xsmeg; + return unless($masterSettings{maximumIndentation} =~ m/^\h+$/); + + # maximum indentation check + $self->logger("Maximum indentation check",'heading') if($is_t_switch_active); + + # replace any leading tabs with spaces, and update the body + my @expanded_lines = expand(${$self}{body}); + ${$self}{body} = join("",@expanded_lines); + + # grab the maximum indentation + my $maximumIndentation = $masterSettings{maximumIndentation}; + my $maximumIndentationLength = length($maximumIndentation)+1; + + # replace any leading space that is greater than the + # specified maximum indentation with the maximum indentation + ${$self}{body} =~ s/^\h{$maximumIndentationLength,}/$maximumIndentation/smg; } sub indent_children_recursively{ @@ -297,25 +322,32 @@ sub indent_children_recursively{ # line break checks before <begin statement> if(defined ${$child}{BeginStartsOnOwnLine}){ my $BeginStringLogFile = ${$child}{aliases}{BeginStartsOnOwnLine}||"BeginStartsOnOwnLine"; + + # if the child ID is not the first character and BeginStartsOnOwnLine>=1 + # then we will need to add a line break (==1), a comment (==2) or another blank line (==3) if(${$child}{BeginStartsOnOwnLine}>=1 and !$IDFirstNonWhiteSpaceCharacter){ # by default, assume that no trailing comment token is needed - my $trailingCommentToken = q(); + my $trailingCharacterToken = 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; + $trailingCharacterToken = "%".$self->add_comment_symbol; + } elsif (${$child}{BeginStartsOnOwnLine}==3){ + $self->logger("Adding a blank line at the end of the line that ${$child}{begin} is on, then a linebreak ($BeginStringLogFile == 3)") if $is_t_switch_active; + $trailingCharacterToken = "\n".(${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:q()); } 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}{begin} = "$trailingCharacterToken\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){ + # finally, if BeginStartsOnOwnLine == -1 then we might need to *remove* a blank line(s) # 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){ diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm index 1166282895d..4861cb9f82c 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Item.pm @@ -37,7 +37,7 @@ sub construct_list_of_items{ } # detail items in the log - $self->logger("List of items: $listOfItems (see itemNames)",'heading'); + $self->logger("List of items: $listOfItems (see itemNames)",'heading') if $is_t_switch_active; $itemRegExp = qr/ ( @@ -127,11 +127,8 @@ sub tasks_particular_to_each_object{ # 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; + # search for commands and special code blocks + $self->find_commands_or_key_equals_values_braces_and_special; } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm index fb7cb37ed00..128034a2881 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/LogFile.pm @@ -63,7 +63,7 @@ usage: latexindent.pl [options] [file][.tex|.sty|.cls|.bib|...] displays the version number and date of release -h, --help help (see the documentation for detailed instructions and examples) - -o, --outputfile + -o, --outputfile=<name-of-output-file> output to another file; sample usage: latexindent.pl -o outputfile.tex myfile.tex latexindent.pl -o=outputfile.tex myfile.tex @@ -79,6 +79,10 @@ usage: latexindent.pl [options] [file][.tex|.sty|.cls|.bib|...] latexindent.pl -l some.yaml myfile.tex latexindent.pl -l=another.yaml myfile.tex latexindent.pl -l=some.yaml,another.yaml myfile.tex + -y, --yaml=<yaml settings> + specify YAML settings; sample usage: + latexindent.pl -y="defaultIndent:' '" myfile.tex + latexindent.pl -y="defaultIndent:' ',maximumIndentation:' '" myfile.tex -d, --onlydefault ONLY use defaultSettings.yaml, ignore ALL (yaml) user files -g, --logfile=<name of log file> @@ -87,7 +91,7 @@ usage: latexindent.pl [options] [file][.tex|.sty|.cls|.bib|...] 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 + trailing comments and blank lines can also be added using this feature ENDQUOTE ; exit(2); @@ -106,6 +110,7 @@ ENDQUOTE $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("-y|--yaml: YAML settings specified via command line") if($switches{yaml}); $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}); diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm index 3f0148d4670..d527f5d7986 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/ModifyLineBreaks.pm @@ -35,6 +35,11 @@ sub modify_line_breaks_body{ if(defined ${$self}{BodyStartsOnOwnLine}){ my $BodyStringLogFile = ${$self}{aliases}{BodyStartsOnOwnLine}||"BodyStartsOnOwnLine"; if(${$self}{BodyStartsOnOwnLine}>=1 and !${$self}{linebreaksAtEnd}{begin}){ + # if the <begin> statement doesn't finish with a line break, + # then we have different actions based upon the value of BodyStartsOnOwnLine: + # BodyStartsOnOwnLine == 1 just add a new line + # BodyStartsOnOwnLine == 2 add a comment, and then new line + # BodyStartsOnOwnLine == 3 add a blank line, and then new line 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; @@ -47,7 +52,7 @@ sub modify_line_breaks_body{ 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; + $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"; @@ -57,6 +62,14 @@ sub modify_line_breaks_body{ } 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}==3){ + my $trailingCharacterToken = q(); + $self->logger("Adding a blank line at the end of begin ${$self}{begin} followed by a linebreak ($BodyStringLogFile == 3)") if $is_t_switch_active; + ${$self}{begin} =~ s/\h*$//; + ${$self}{begin} .= (${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:"\n")."\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}==-1 and ${$self}{linebreaksAtEnd}{begin}){ # remove line break *after* begin, if appropriate @@ -80,14 +93,22 @@ sub modify_line_breaks_end{ 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 + # if the <body> statement doesn't finish with a line break, + # then we have different actions based upon the value of EndStartsOnOwnLine: + # EndStartsOnOwnLine == 1 just add a new line + # EndStartsOnOwnLine == 2 add a comment, and then new line + # EndStartsOnOwnLine == 3 add a blank line, and then new line $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(); + # by default, assume that no trailing character token is needed + my $trailingCharacterToken = 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; + $trailingCharacterToken = "%".$self->add_comment_symbol; + ${$self}{body} =~ s/\h*$//s; + } elsif (${$self}{EndStartsOnOwnLine}==3) { + $self->logger("Adding a blank line immediately after body of ${$self}{name} ($EndStringLogFile==3)") if $is_t_switch_active; + $trailingCharacterToken = "\n".(${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:q()); ${$self}{body} =~ s/\h*$//s; } @@ -95,7 +116,7 @@ sub modify_line_breaks_end{ if(${$self}{body} =~ m/^\h*$/s and ${$self}{BodyStartsOnOwnLine} >=1 ){ ${$self}{linebreaksAtEnd}{body} = 0; } else { - ${$self}{body} .= "$trailingCommentToken\n"; + ${$self}{body} .= "$trailingCharacterToken\n"; ${$self}{linebreaksAtEnd}{body} = 1; } } elsif (${$self}{EndStartsOnOwnLine}==-1 and ${$self}{linebreaksAtEnd}{body}){ @@ -117,9 +138,14 @@ sub modify_line_breaks_end{ if(defined ${$self}{EndFinishesWithLineBreak} and ${$self}{EndFinishesWithLineBreak}>=1 and !${$self}{linebreaksAtEnd}{end}){ + # if the <end> statement doesn't finish with a line break, + # then we have different actions based upon the value of EndFinishesWithLineBreak: + # EndFinishesWithLineBreak == 1 just add a new line + # EndFinishesWithLineBreak == 2 add a comment, and then new line + # EndFinishesWithLineBreak == 3 add a blank line, and then new line 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->logger("Adding a linebreak at the end of ${$self}{end} ($EndStringLogFile==1)") if $is_t_switch_active; ${$self}{linebreaksAtEnd}{end} = 1; # modified end statement @@ -136,7 +162,13 @@ sub modify_line_breaks_end{ ${$self}{replacementText} .= "$trailingCommentToken\n"; ${$self}{linebreaksAtEnd}{end} = 1; } - } + } elsif(${$self}{EndFinishesWithLineBreak}==3){ + $self->logger("Adding a blank line at the end of ${$self}{end} ($EndStringLogFile==3)") if $is_t_switch_active; + ${$self}{linebreaksAtEnd}{end} = 1; + + # modified end statement + ${$self}{replacementText} .= (${$masterSettings{modifyLineBreaks}}{preserveBlankLines}?$tokens{blanklines}:"\n")."\n"; + } } } @@ -211,7 +243,7 @@ sub construct_paragraph_reg_exp{ $stopAtRegExp .= "|(?:".($paragraphStopAt eq "trailingComment" ? "%" : q() ).$tokens{$paragraphStopAt}."\\d+)"; } } else { - $self->logger("The paragraph-stop regexp won't include $tokens{$paragraphStopAt} (see paragraphsStopAt)",'heading') if $is_t_switch_active ; + $self->logger("The paragraph-stop regexp won't include $tokens{$paragraphStopAt} (see paragraphsStopAt)",'heading') if ($tokens{$paragraphStopAt} and $is_t_switch_active); } } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm index a3a62dd3f56..178bfe4ff7b 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Preamble.pm @@ -17,6 +17,7 @@ package LatexIndent::Preamble; use strict; use warnings; use LatexIndent::Tokens qw/%tokens/; +use LatexIndent::Switches qw/$is_t_switch_active/; use LatexIndent::GetYamlSettings qw/%masterSettings/; our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 our $preambleCounter; @@ -33,7 +34,7 @@ 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->logger("Custom replacement text routine for preamble ${$self}{name}") if $is_t_switch_active; ${$self}{replacementText} = ${$self}{id}.${$self}{afterbit}; delete ${$self}{afterbit}; } @@ -52,12 +53,19 @@ sub tasks_particular_to_each_object{ # search for ifElseFi blocks $self->find_ifelsefi; - # search for commands with arguments - $self->find_commands_or_key_equals_values_braces if(!$masterSettings{preambleCommandsBeforeEnvironments}); + if(${$masterSettings{specialBeginEnd}}{specialBeforeCommand}){ + # search for special begin/end + $self->find_special; - # search for special begin/end - $self->find_special; + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces if(!$masterSettings{preambleCommandsBeforeEnvironments}); + } else { + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces if(!$masterSettings{preambleCommandsBeforeEnvironments}); + # search for special begin/end + $self->find_special; + } } diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm index d278d80e75c..d5a751f9e0e 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Special.pm @@ -34,15 +34,17 @@ sub construct_special_begin{ # 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}); + if(ref($BeginEnd) eq "HASH"){ + # 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}){ + if( (ref($BeginEnd) eq "HASH") and ${$BeginEnd}{lookForThis}){ # the beginning parts $specialBegins .= ($specialBegins eq ""?q():"|").${$BeginEnd}{begin}; @@ -116,10 +118,10 @@ sub find_special{ while( my ($specialName,$BeginEnd)= each %{$masterSettings{specialBeginEnd}}){ # log file - if(${$BeginEnd}{lookForThis}){ + if((ref($BeginEnd) eq "HASH") and ${$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 ; + $self->logger("Not looking for $specialName (see lookForThis)",'heading') if ($is_t_switch_active and (ref($BeginEnd) eq "HASH")); next; } @@ -171,6 +173,19 @@ sub find_special{ } } +sub tasks_particular_to_each_object{ + my $self = shift; + + return unless(${$masterSettings{specialBeginEnd}}{specialBeforeCommand}); + + # search for commands with arguments + $self->find_commands_or_key_equals_values_braces; + + # search for ifElseFi blocks + $self->find_ifelsefi; + +} + sub create_unique_id{ my $self = shift; diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm index e50c66d25d0..a106a09dcb1 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Tokens.pm @@ -32,6 +32,7 @@ our %tokens = ( optionalArguments=>$beginningToken."OPTIONAL-ARGUMENT", mandatoryArguments=>$beginningToken."MANDATORY-ARGUMENT", ifElseFi=>$ifelsefiSpecial.$beginningToken."IFELSEFI", + else=>$beginningToken."ELSE", items=>$beginningToken."ITEMS", keyEqualsValuesBracesBrackets=>$beginningToken."KEY-VALUE-BRACES", namedGroupingBracesBrackets=>$beginningToken."GROUPING-BRACES", diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm index ba6b698175e..909b33cfc1b 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Verbatim.pm @@ -146,7 +146,7 @@ sub find_verbatim_commands{ # 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('looking for VERBATIM commands (see verbatimCommands)','heading') if $is_t_switch_active; $self->logger(Dumper(\%{$masterSettings{verbatimCommands}})) if($is_tt_switch_active); while( my ($verbCommand,$yesno)= each %{$masterSettings{verbatimCommands}}){ if($yesno){ diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Version.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Version.pm index ec7202cf3eb..260f1f124a4 100644 --- a/Master/texmf-dist/scripts/latexindent/LatexIndent/Version.pm +++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Version.pm @@ -19,6 +19,6 @@ use warnings; use Exporter qw/import/; our @EXPORT_OK = qw/$versionNumber $versionDate/; -our $versionNumber = '3.2.2'; -our $versionDate = '2017-06-28'; +our $versionNumber = '3.3'; +our $versionDate = '2017-08-21'; 1 diff --git a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml index d91ee50010e..97c63d7e4f2 100755 --- a/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml +++ b/Master/texmf-dist/scripts/latexindent/defaultSettings.yaml @@ -1,4 +1,4 @@ -# defaultSettings.yaml for latexindent.pl, version 3.2.2, 2017-06-28 +# defaultSettings.yaml for latexindent.pl, version 3.3, 2017-08-21 # a script that aims to # beautify .tex, .sty, .cls files # @@ -200,6 +200,7 @@ specialBeginEnd: begin: '\$\$' end: '\$\$' lookForThis: 1 + specialBeforeCommand: 0 # if you want to add indentation after # a heading, such as \part, \chapter, etc @@ -235,6 +236,9 @@ indentAfterHeadings: indentAfterThisHeading: 0 level: 7 +# maximum indentation, off by default +maximumIndentation: -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 @@ -304,6 +308,8 @@ commandCodeBlocks: decoration: 1 ++: 1 --: 1 + commandNameSpecial: + @ifnextchar[: 1 # modifyLineBreaks will only be searched if the -m # switch is active diff --git a/Master/texmf-dist/scripts/latexindent/latexindent.pl b/Master/texmf-dist/scripts/latexindent/latexindent.pl index bafa1790e46..b2d9da3a032 100755 --- a/Master/texmf-dist/scripts/latexindent/latexindent.pl +++ b/Master/texmf-dist/scripts/latexindent/latexindent.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# latexindent.pl, version 3.2.2, 2017-06-28 +# latexindent.pl, version 3.3, 2017-08-21 # # 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 @@ -35,6 +35,7 @@ GetOptions ( "trace|t"=>\$switches{trace}, "ttrace|tt"=>\$switches{ttrace}, "local|l:s"=>\$switches{readLocalSettings}, + "yaml|y=s"=>\$switches{yaml}, "onlydefault|d"=>\$switches{onlyDefault}, "overwrite|w"=>\$switches{overwrite}, "outputfile|o=s"=>\$switches{outputToFile}, |