diff options
Diffstat (limited to 'support/latexindent/LatexIndent')
-rw-r--r-- | support/latexindent/LatexIndent/Document.pm | 50 | ||||
-rw-r--r-- | support/latexindent/LatexIndent/GetYamlSettings.pm | 118 | ||||
-rw-r--r-- | support/latexindent/LatexIndent/Sentence.pm | 42 | ||||
-rw-r--r-- | support/latexindent/LatexIndent/TrailingComments.pm | 12 | ||||
-rw-r--r-- | support/latexindent/LatexIndent/Version.pm | 4 | ||||
-rw-r--r-- | support/latexindent/LatexIndent/Wrap.pm | 354 |
6 files changed, 517 insertions, 63 deletions
diff --git a/support/latexindent/LatexIndent/Document.pm b/support/latexindent/LatexIndent/Document.pm index 6a45320fe7..8982509445 100644 --- a/support/latexindent/LatexIndent/Document.pm +++ b/support/latexindent/LatexIndent/Document.pm @@ -37,7 +37,7 @@ use LatexIndent::BlankLines qw/protect_blank_lines unprotect_blank_lines condens use LatexIndent::ModifyLineBreaks qw/modify_line_breaks_body modify_line_breaks_end modify_line_breaks_end_after remove_line_breaks_begin adjust_line_breaks_end_parent verbatim_modify_line_breaks/; use LatexIndent::Sentence qw/one_sentence_per_line/; -use LatexIndent::Wrap qw/text_wrap/; +use LatexIndent::Wrap qw/text_wrap text_wrap_comment_blocks/; 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/; @@ -297,6 +297,31 @@ sub process_body_of_text { $logger->info('*Phase 4: final indentation check'); $self->final_indentation_check; + # one sentence per line: sentences are objects, as of V3.5.1 + if ( $is_m_switch_active + and ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{manipulateSentences} + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' ) + { + $logger->trace("*one-sentence-per-line text wrapping routine, textWrapOptions:when set to 'after'") + if $is_tt_switch_active; + $self->one_sentence_per_line( textWrap => 1 ); + } + + # option for text wrap + if ( $is_m_switch_active + and !${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{manipulateSentences} + and !${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{textWrapSentences} + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns} != 0 + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' ) + { + $self->text_wrap(); + } + + # option for comment text wrap + $self->text_wrap_comment_blocks() + if ($is_m_switch_active + and ${ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{comments} }{wrap} + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' ); return; } @@ -304,8 +329,10 @@ sub find_objects { my $self = shift; # one sentence per line: sentences are objects, as of V3.5.1 - $self->one_sentence_per_line - if ( $is_m_switch_active and ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{manipulateSentences} ); + $self->one_sentence_per_line( + textWrap => ( ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'before' ) ) + if ( $is_m_switch_active + and ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{manipulateSentences} ); # text wrapping # @@ -319,7 +346,8 @@ sub find_objects { if ( $is_m_switch_active and !${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{manipulateSentences} and !${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{textWrapSentences} - and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns} != 0 ) + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns} != 0 + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'before' ) { $self->text_wrap(); @@ -327,6 +355,12 @@ sub find_objects { $self->verbatim_modify_line_breaks( when => "afterTextWrap" ); } + # option for comment text wrap + $self->text_wrap_comment_blocks() + if ($is_m_switch_active + and ${ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{comments} }{wrap} + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'before' ); + # search for environments $logger->trace('*looking for ENVIRONMENTS') if $is_t_switch_active; $self->find_environments if ${$self}{body} =~ m/$environmentBasicRegExp/s; @@ -496,7 +530,13 @@ sub tasks_common_to_each_object { $self->check_for_hidden_children if ${$self}{body} =~ m/$tokens{beginOfToken}/; # double back slash poly-switch check - $self->double_back_slash_else if ( $is_m_switch_active and ${$self}{lookForAlignDelims} ); + $self->double_back_slash_else + if ( + $is_m_switch_active + and ( ${$self}{lookForAlignDelims} + or ( defined ${$self}{DBSStartsOnOwnLine} and ${$self}{DBSStartsOnOwnLine} != 0 ) + or ( defined ${$self}{DBSFinishesWithLineBreak} and ${$self}{DBSFinishesWithLineBreak} != 0 ) ) + ); # some objects can format their body to align at the & character $self->align_at_ampersand if ( ${$self}{lookForAlignDelims} and !${$self}{measureHiddenChildren} ); diff --git a/support/latexindent/LatexIndent/GetYamlSettings.pm b/support/latexindent/LatexIndent/GetYamlSettings.pm index 23f5a70d85..a5931d17f7 100644 --- a/support/latexindent/LatexIndent/GetYamlSettings.pm +++ b/support/latexindent/LatexIndent/GetYamlSettings.pm @@ -117,16 +117,75 @@ sub yaml_read_settings { # we'll need the home directory a lot in what follows my $homeDir = File::HomeDir->my_home; - $logger->info("*YAML settings read: indentconfig.yaml or .indentconfig.yaml") unless $switches{onlyDefault}; + $logger->info("*YAML reading settings") unless $switches{onlyDefault}; + + my $indentconfig = undef; + if ( defined $ENV{LATEXINDENT_CONFIG} && !$switches{onlyDefault} ) { + if ( -f $ENV{LATEXINDENT_CONFIG} ) { + $indentconfig = $ENV{LATEXINDENT_CONFIG}; + $logger->info('The $LATEXINDENT_CONFIG variable was detected.'); + $logger->info( 'The value of $LATEXINDENT_CONFIG is: "' . $ENV{LATEXINDENT_CONFIG} . '"' ); + } + else { + $logger->warn('*The $LATEXINDENT_CONFIG variable is assigned, but does not point to a file!'); + $logger->warn( 'The value of $LATEXINDENT_CONFIG is: "' . $ENV{LATEXINDENT_CONFIG} . '"' ); + } + } + if ( !defined $indentconfig && !$switches{onlyDefault} ) { + +# see all possible values of $^O here: https://perldoc.perl.org/perlport#Unix and https://perldoc.perl.org/perlport#DOS-and-Derivatives + if ( $^O eq "linux" ) { + if ( defined $ENV{XDG_CONFIG_HOME} && -f "$ENV{XDG_CONFIG_HOME}/latexindent/indentconfig.yaml" ) { + $indentconfig = "$ENV{XDG_CONFIG_HOME}/latexindent/indentconfig.yaml"; + $logger->info( 'The $XDG_CONFIG_HOME variable and the config file in "' + . "$ENV{XDG_CONFIG_HOME}/latexindent/indentconfig.yaml" + . '" were recognized' ); + $logger->info( 'The value of $XDG_CONFIG_HOME is: "' . $ENV{XDG_CONFIG_HOME} . '"' ); + } + elsif ( -f "$homeDir/.config/latexindent/indentconfig.yaml" ) { + $indentconfig = "$homeDir/.config/latexindent/indentconfig.yaml"; + $logger->info( + 'The config file in "' . "$homeDir/.config/latexindent/indentconfig.yaml" . '" was recognized' ); + } + } + elsif ( $^O eq "darwin" ) { + if ( -f "$homeDir/Library/Preferences/latexindent/indentconfig.yaml" ) { + $indentconfig = "$homeDir/Library/Preferences/latexindent/indentconfig.yaml"; + $logger->info( 'The config file in "' + . "$homeDir/Library/Preferences/latexindent/indentconfig.yaml" + . '" was recognized' ); + } + } + elsif ( $^O eq "MSWin32" || $^O eq "cygwin" ) { + if ( defined $ENV{LOCALAPPDATA} && -f "$ENV{LOCALAPPDATA}/latexindent/indentconfig.yaml" ) { + $indentconfig = "$ENV{LOCALAPPDATA}/latexindent/indentconfig.yaml"; + $logger->info( 'The $LOCALAPPDATA variable and the config file in "' + . "$ENV{LOCALAPPDATA}" + . '\latexindent\indentconfig.yaml" were recognized' ); + $logger->info( 'The value of $LOCALAPPDATA is: "' . $ENV{LOCALAPPDATA} . '"' ); + } + elsif ( -f "$homeDir/AppData/Local/latexindent/indentconfig.yaml" ) { + $indentconfig = "$homeDir/AppData/Local/latexindent/indentconfig.yaml"; + $logger->info( 'The config file in "' + . "$homeDir" + . '\AppData\Local\latexindent\indentconfig.yaml" was recognized' ); + } + } - # get information about user settings- first check if indentconfig.yaml exists - my $indentconfig = "$homeDir/indentconfig.yaml"; + # if $indentconfig is still not defined, fallback to the location in $homeDir + if ( !defined $indentconfig ) { - # if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml - $indentconfig = "$homeDir/.indentconfig.yaml" if ( !-e $indentconfig ); + # if all of these don't exist check home directly, with the non hidden file + $indentconfig = ( -f "$homeDir/indentconfig.yaml" ) ? "$homeDir/indentconfig.yaml" : undef; + + # if indentconfig.yaml doesn't exist, check for the hidden file, .indentconfig.yaml + $indentconfig = ( -f "$homeDir/.indentconfig.yaml" ) ? "$homeDir/.indentconfig.yaml" : undef; + $logger->info( 'The config file in "' . "$indentconfig" . '" was recognized' ) if defined $indentconfig; + } + } # messages for indentconfig.yaml and/or .indentconfig.yaml - if ( -e $indentconfig and !$switches{onlyDefault} ) { + if ( defined $indentconfig && -f $indentconfig && !$switches{onlyDefault} ) { # read the absolute paths from indentconfig.yaml $userSettings = YAML::Tiny->read("$indentconfig"); @@ -135,19 +194,6 @@ sub yaml_read_settings { if ( $userSettings and ( ref( $userSettings->[0] ) eq 'HASH' ) and $userSettings->[0]->{paths} ) { $logger->info("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" ) - { - $logger->info("$homeDir/.indentconfig.yaml has been found, but $indentconfig takes priority"); - } - elsif ( -e File::HomeDir->my_home . "/indentconfig.yaml" ) { - $logger->info("(Alternatively $homeDir/.indentconfig.yaml can be used)"); - } - elsif ( -e File::HomeDir->my_home . "/.indentconfig.yaml" ) { - $logger->info("(Alternatively $homeDir/indentconfig.yaml can be used)"); - } - # output the contents of indentconfig to the log file $logger->info( Dump \%{ $userSettings->[0] } ); @@ -190,7 +236,8 @@ sub yaml_read_settings { else { if ( $switches{onlyDefault} ) { $logger->info("*-d switch active: only default settings requested"); - $logger->info("not reading USER settings from $indentconfig") if ( -e $indentconfig ); + $logger->info("not reading USER settings from $indentconfig") + if ( defined $indentconfig && -e $indentconfig ); $logger->info("Ignoring the -l switch: $switches{readLocalSettings} (you used the -d switch)") if ( $switches{readLocalSettings} ); $logger->info("Ignoring the -y switch: $switches{yaml} (you used the -d switch)") if ( $switches{yaml} ); @@ -198,9 +245,9 @@ sub yaml_read_settings { $switches{yaml} = 0; } else { - # give the user instructions on where to put indentconfig.yaml or .indentconfig.yaml + # give the user instructions on where to put the config file $logger->info( - "Home directory is $homeDir (didn't find either indentconfig.yaml or .indentconfig.yaml)\nTo specify user settings you would put indentconfig.yaml here: $homeDir/indentconfig.yaml\nAlternatively, you can use the hidden file .indentconfig.yaml as: $homeDir/.indentconfig.yaml" + "Home directory is $homeDir (didn't find a config file, see all posible locations here: https://latexindentpl.readthedocs.io/en/latest/sec-appendices.html#indentconfig-options)" ); } } @@ -693,6 +740,25 @@ sub yaml_read_settings { } + # the following are incompatible: + # + # modifyLineBreaks: + # oneSentencePerLine: + # manipulateSentences: 1 + # textWrapSentences: 1 + # sentenceIndent: " " <!------ + # textWrapOptions: + # columns: 100 + # when: after <!------ + # + if ( $is_m_switch_active + and ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' + and ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentenceIndent} =~ m/\h+/ ) + { + $logger->warn("*one-sentence-per-line *ignoring* sentenceIndent, as text wrapping set to 'after'"); + ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentenceIndent} = q(); + } + # some users may wish to see showAmalgamatedSettings # which details the overall state of the settings modified # from the default in various user files @@ -887,8 +953,12 @@ sub yaml_modify_line_breaks_settings { 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" ) ); + push( + @toBeAssignedTo, + ( "BeginStartsOnOwnLine", "BodyStartsOnOwnLine", "EndStartsOnOwnLine", "EndFinishesWithLineBreak", + "DBSStartsOnOwnLine", "DBSFinishesWithLineBreak" + ) + ); # we can efficiently loop through the following foreach (@toBeAssignedTo) { diff --git a/support/latexindent/LatexIndent/Sentence.pm b/support/latexindent/LatexIndent/Sentence.pm index cee8b559ab..3447d975c3 100644 --- a/support/latexindent/LatexIndent/Sentence.pm +++ b/support/latexindent/LatexIndent/Sentence.pm @@ -32,15 +32,16 @@ our @EXPORT_OK = qw/one_sentence_per_line/; our $sentenceCounter; sub one_sentence_per_line { - my $self = shift; + my $self = shift; + my %input = @_; $logger->trace( "*One sentence per line regular expression construction: (see oneSentencePerLine: manipulateSentences)") if $is_t_switch_active; + # # sentences FOLLOW - # sentences FOLLOW - # sentences FOLLOW + # my $sentencesFollow = q(); while ( my ( $sentencesFollowEachPart, $yesNo ) @@ -105,9 +106,9 @@ sub one_sentence_per_line { $logger->trace("Sentences follow regexp:") if $is_tt_switch_active; $logger->trace($sentencesFollow) if $is_tt_switch_active; + # # sentences BEGIN with - # sentences BEGIN with - # sentences BEGIN with + # my $sentencesBeginWith = q(); while ( my ( $sentencesBeginWithEachPart, $yesNo ) @@ -136,9 +137,9 @@ sub one_sentence_per_line { } $sentencesBeginWith = qr/$sentencesBeginWith/; + # # sentences END with - # sentences END with - # sentences END with + # ${ ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentencesEndWith} }{basicFullStop} = 0 if ${ ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentencesEndWith} }{betterFullStop}; my $sentencesEndWith = q(); @@ -181,9 +182,9 @@ sub one_sentence_per_line { } $sentencesEndWith = qr/$sentencesEndWith/; + # # the OVERALL sentence regexp - # the OVERALL sentence regexp - # the OVERALL sentence regexp + # $logger->trace("Overall sentences end with regexp:") if $is_tt_switch_active; $logger->trace($sentencesEndWith) if $is_tt_switch_active; @@ -268,12 +269,26 @@ sub one_sentence_per_line { $replacementText = ${@{${$self}{children}}[-1]}{replacementText}; } else { $sentenceCounter++; - push(@sentenceStorage,{id=>$tokens{sentence}.$sentenceCounter.$tokens{endOfToken},value=>$middle.$end}); + push(@sentenceStorage,{id=>$tokens{sentence}.$sentenceCounter.$tokens{endOfToken},value=>$middle.$end,leadingHorizontalSpace=>$h_space,follows=>$beginning}); $replacementText = $beginning.$h_space.$tokens{sentence}.$sentenceCounter.$tokens{endOfToken}.$trailingComments.$trailing.($lineBreaksAtEnd ? q() : "\n"); }; $replacementText; /xsge; + # + # remove spaces between trailing comments + # + # + # from: + # + # % first comment %second comment + # ^ + # into: + # + # % first comment%second comment + # + ${$self}{body} =~ s/($trailingCommentRegExp)\h($trailingCommentRegExp)/$1$2/sg; + if ( ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentenceIndent} !~ m/\h+/ ) { # loop back through the sentenceStorage and replace with the sentence, adjusting line breaks @@ -288,6 +303,8 @@ sub one_sentence_per_line { body => $sentenceStorageValue, name => "sentence", modifyLineBreaksYamlName => "sentence", + leadingHorizontalSpace => ${$sentence}{leadingHorizontalSpace}, + follows => ${$sentence}{follows}, ); # text wrapping @@ -302,7 +319,7 @@ sub one_sentence_per_line { ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{textWrapSentences} = 0; } else { - $sentenceObj->text_wrap; + $sentenceObj->text_wrap if $input{textWrap}; } # indentation of sentences @@ -316,7 +333,7 @@ sub one_sentence_per_line { my $bodyFirstLine = $1; my $remainingBody = $2; my $indentation = ${ $mainSettings{modifyLineBreaks}{oneSentencePerLine} }{sentenceIndent}; - $logger->trace("first line of sencent: $bodyFirstLine") if $is_tt_switch_active; + $logger->trace("first line of sentence: $bodyFirstLine") if $is_tt_switch_active; $logger->trace("remaining body (before indentation):\n'$remainingBody'") if ($is_tt_switch_active); # add the indentation to all the body except first line @@ -326,6 +343,7 @@ sub one_sentence_per_line { # put the body back together ${$sentenceObj}{body} = $bodyFirstLine . "\n" . $remainingBody; } + $sentenceStorageValue = ${$sentenceObj}{body}; } diff --git a/support/latexindent/LatexIndent/TrailingComments.pm b/support/latexindent/LatexIndent/TrailingComments.pm index 4ddfe8eb1a..71b1027a1b 100644 --- a/support/latexindent/LatexIndent/TrailingComments.pm +++ b/support/latexindent/LatexIndent/TrailingComments.pm @@ -24,7 +24,7 @@ use LatexIndent::LogFile qw/$logger/; 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/; + = qw/remove_trailing_comments put_trailing_comments_back_in $trailingCommentRegExp add_comment_symbol construct_trailing_comment_regexp @trailingComments/; our @trailingComments; our $commentCounter = 0; our $trailingCommentRegExp; @@ -39,13 +39,17 @@ sub add_comment_symbol { # add a trailing comment token after, for example, a square brace [ # or a curly brace { when, for example, BeginStartsOnOwnLine == 2 - my $self = shift; + my $self = shift; + my %input = @_; + + my $commentValue = ( defined $input{value} ? $input{value} : q() ); # increment the comment counter $commentCounter++; # store the comment -- without this, it won't get processed correctly at the end - push( @trailingComments, { id => $tokens{trailingComment} . $commentCounter . $tokens{endOfToken}, value => q() } ); + push( @trailingComments, + { id => $tokens{trailingComment} . $commentCounter . $tokens{endOfToken}, value => $commentValue } ); # log file info $logger->trace("*Updating trailing comment array") if $is_t_switch_active; @@ -145,8 +149,6 @@ sub put_trailing_comments_back_in { $logger->trace("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; - #####if(${$self}{body} =~ m/%$trailingcommentID\h*[^%]+?$/mx){ - ##### $logger->trace("Comment not at end of line $trailingcommentID, moving it to end of line") if $is_t_switch_active; } else { ${$self}{body} =~ s/%$trailingcommentID/%$trailingcommentValue/; diff --git a/support/latexindent/LatexIndent/Version.pm b/support/latexindent/LatexIndent/Version.pm index 9773c55fcd..090879ef0d 100644 --- a/support/latexindent/LatexIndent/Version.pm +++ b/support/latexindent/LatexIndent/Version.pm @@ -20,6 +20,6 @@ use warnings; use Exporter qw/import/; our @EXPORT_OK = qw/$versionNumber $versionDate/; -our $versionNumber = '3.19.1'; -our $versionDate = '2022-12-04'; +our $versionNumber = '3.20'; +our $versionDate = '2023-01-01'; 1 diff --git a/support/latexindent/LatexIndent/Wrap.pm b/support/latexindent/LatexIndent/Wrap.pm index 7f3d026a4e..8af51ed176 100644 --- a/support/latexindent/LatexIndent/Wrap.pm +++ b/support/latexindent/LatexIndent/Wrap.pm @@ -20,14 +20,14 @@ use warnings; use Text::Wrap; use LatexIndent::Tokens qw/%tokens/; use LatexIndent::AlignmentAtAmpersand qw/get_column_width/; -use LatexIndent::TrailingComments qw/$trailingCommentRegExp/; +use LatexIndent::TrailingComments qw/$trailingCommentRegExp @trailingComments/; use LatexIndent::GetYamlSettings qw/%mainSettings/; use LatexIndent::Switches qw/$is_t_switch_active $is_tt_switch_active $is_m_switch_active/; use LatexIndent::LogFile qw/$logger/; use LatexIndent::Verbatim qw/%verbatimStorage/; use Exporter qw/import/; -our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 -our @EXPORT_OK = qw/text_wrap/; +our @ISA = "LatexIndent::Document"; # class inheritance, Programming Perl, pg 321 +our @EXPORT_OK = qw/text_wrap text_wrap_comment_blocks/; our $sentenceCounter; sub text_wrap { @@ -35,13 +35,15 @@ sub text_wrap { $logger->trace("*Text wrap regular expression construction: (see textWrapOptions: )") if $is_t_switch_active; + # # textWrap Blocks FOLLOW - # textWrap Blocks FOLLOW - # textWrap Blocks FOLLOW + # my $blocksFollow = q(); my $blocksFollowHash = \%{ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{blocksFollow} }; foreach my $blocksFollowEachPart ( sort keys %{$blocksFollowHash} ) { + last if ${$self}{modifyLineBreaksYamlName} eq 'sentence'; + my $yesNo = $blocksFollowHash->{$blocksFollowEachPart}; if ($yesNo) { if ( $blocksFollowEachPart eq "par" ) { @@ -118,16 +120,19 @@ sub text_wrap { # followed by 0 or more h-space and line breaks $blocksFollow = ( $blocksFollow eq '' ? q() : qr/(?:$blocksFollow)(?:\h|\R)*/sx ); - $logger->trace("textWrap blocks follow regexp:") if $is_tt_switch_active; + $logger->trace("textWrap blocks follow regexp:") + if ( $is_tt_switch_active and ${$self}{modifyLineBreaksYamlName} ne 'sentence' ); $logger->trace($blocksFollow) if $is_tt_switch_active; + # # textWrap Blocks BEGIN with - # textWrap Blocks BEGIN with - # textWrap Blocks BEGIN with + # my $blocksBeginWith = q(); my $blocksBeginWithHash = \%{ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{blocksBeginWith} }; foreach my $blocksBeginWithEachPart ( sort keys %{$blocksBeginWithHash} ) { + last if ${$self}{modifyLineBreaksYamlName} eq 'sentence'; + my $yesNo = $blocksBeginWithHash->{$blocksBeginWithEachPart}; if ($yesNo) { if ( $blocksBeginWithEachPart eq "A-Z" ) { @@ -156,13 +161,15 @@ sub text_wrap { } $blocksBeginWith = qr/$blocksBeginWith/; + # # textWrap Blocks END with - # textWrap Blocks END with - # textWrap Blocks END with + # my $blocksEndBefore = q(); my $blocksEndBeforeHash = \%{ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{blocksEndBefore} }; foreach my $blocksEndBeforeEachPart ( sort keys %{$blocksEndBeforeHash} ) { + last if ${$self}{modifyLineBreaksYamlName} eq 'sentence'; + my $yesNo = $blocksEndBeforeHash->{$blocksEndBeforeEachPart}; if ($yesNo) { if ( $blocksEndBeforeEachPart eq "other" ) { @@ -191,14 +198,17 @@ sub text_wrap { } $blocksEndBefore = qr/$blocksEndBefore/; + # # the OVERALL textWrap Blocks regexp - # the OVERALL textWrap Blocks regexp - # the OVERALL textWrap Blocks regexp - $logger->trace("Overall textWrap Blocks end with regexp:") if $is_tt_switch_active; + # + $logger->trace("Overall textWrap Blocks end with regexp:") + if ( $is_tt_switch_active and ${$self}{modifyLineBreaksYamlName} ne 'sentence' ); $logger->trace($blocksEndBefore) if $is_tt_switch_active; # store the text wrap blocks my @textWrapBlockStorage = split( /($blocksFollow)/, ${$self}{body} ); + @textWrapBlockStorage = split( /(\s*$blocksFollow)/, ${$self}{body} ) + if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after'; # sentences need special treatment if ( ${$self}{modifyLineBreaksYamlName} eq 'sentence' ) { @@ -209,8 +219,9 @@ sub text_wrap { my $columns = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns}; # vital Text::Wrap options - $Text::Wrap::columns = $columns; - $Text::Wrap::huge = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{huge}; + $Text::Wrap::columns = $columns; + $Text::Wrap::huge = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{huge}; + $Text::Wrap::unexpand = 0; # all other Text::Wrap options not usually needed/helpful, but available $Text::Wrap::separator = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{separator} @@ -222,17 +233,123 @@ sub text_wrap { $Text::Wrap::tabstop = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{tabstop} if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{tabstop}; + # only needed if when:after + my $subsequentSpace = q(); + # clear the body, which will be updated with newly wrapped body ${$self}{body} = q(); + # text wrap block loop counter + my $textWrapBlockCount = -1; + # loop back through the text wrap block storage foreach my $textWrapBlockStorageValue (@textWrapBlockStorage) { + + # increment text wrap block loop counter + $textWrapBlockCount++; + if ( $textWrapBlockStorageValue =~ m/^\s*$blocksBeginWith/s or ${$self}{modifyLineBreaksYamlName} eq 'sentence' ) { +# text wrap AFTER indentation needs to turn, for example (with columns: 100), +# +# before: +# +# \begin{abstract} +# This is a very long sentence that should be wrapped at some point, which is the case but is is is is line width is not respected because of the indentation. +# \end{abstract} +# +# after: +# +# \begin{abstract} +# This is a very long sentence that should be wrapped at some point, which is the case but is is +# is is line width is not respected because of the indentation. +# \end{abstract} +# ----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| +# 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 +# +# note: it respects the column width AND indentation +# +# see also: test-cases/text-wrap/issue-359*.tex +# + if ( ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' ) { + + # reset columns + $Text::Wrap::columns = $columns; + + # reset subsequent Space + $subsequentSpace = q(); + + my $numberOfTABS = 0; + + # measure leading horizontal space + if ( ${$self}{modifyLineBreaksYamlName} eq 'sentence' ) { + my $thingToMeasure = ( split( /\R/, ${$self}{follows} ) )[-1]; + + $subsequentSpace + = ( ${$self}{follows} ? " " x length($thingToMeasure) : q() ); + + # possible tab adjustments + $thingToMeasure = q() if ( not defined $thingToMeasure ); + $numberOfTABS = () = $thingToMeasure =~ m/\t/g; + for ( my $i = 1; $i <= $numberOfTABS; $i++ ) { + $subsequentSpace =~ s/ / /; + } + } + else { + # note, in the above we have defined + # + # @textWrapBlockStorage = split( /(\s*$blocksFollow)/, ${$self}{body} ) + # + # so that both the *match* AND the *block* are stored, so + # + # ( split( /\R/, $textWrapBlockStorage[ $textWrapBlockCount - 1 ] ) )[-1] + # + # represents the *match* + # + + # scenarios such as + # + # % comment goes here + # text that isn't commented + # + # means that the *match* doesn't contain a linebreak + # + if ( scalar( split( /\R/, $textWrapBlockStorage[ $textWrapBlockCount - 1 ] ) ) == 1 + and ( split( /\R/, $textWrapBlockStorage[ $textWrapBlockCount - 1 ] ) )[-1] + =~ m/$trailingCommentRegExp/ ) + { + $subsequentSpace = q(); + } + else { + my $thingToMeasure = ( split( /\R/, $textWrapBlockStorage[ $textWrapBlockCount - 1 ] ) )[-1]; + + $subsequentSpace = ( + $textWrapBlockCount == 0 + ? q() + : " " x length($thingToMeasure) + ); + + # possible tab adjustments + $numberOfTABS = () = $thingToMeasure =~ m/\t/g; + for ( my $i = 1; $i <= $numberOfTABS; $i++ ) { + $subsequentSpace =~ s/ / /; + } + } + } + $Text::Wrap::columns = $columns - length($subsequentSpace); + + # possible tab adjustments + for ( my $i = 1; $i <= $numberOfTABS; $i++ ) { + $subsequentSpace =~ s/ /\t/; + } + } + # LIMIT is one greater than the maximum number of times EXPR may be split my @textWrapBeforeEndWith = split( /($blocksEndBefore)/, $textWrapBlockStorageValue, 2 ); + @textWrapBeforeEndWith = split( /(\s*$blocksEndBefore)/, $textWrapBlockStorageValue, 2 ) + if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after'; # sentences need special treatment if ( ${$self}{modifyLineBreaksYamlName} eq 'sentence' ) { @@ -355,6 +472,75 @@ sub text_wrap { $textWrapBlockStorageValue = wrap( '', '', $textWrapBlockStorageValue ) if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns} > 0; + # if text wrap has happened *AFTER* indentation, + # then we need to add the leading indentation + # onto the lines of the text wrap block + # + # before: + # + # \begin{abstract} + # This is a very long sentence that should be wrapped at some point, which is the case but is is + # is is line width is not respected because of the indentation. + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # \end{abstract} + # + # after: + # + # \begin{abstract} + # This is a very long sentence that should be wrapped at some point, which is the case but is is + # is is line width is not respected because of the indentation. + # ^^^^ + # \end{abstract} + if ( ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{when} eq 'after' ) { + + # add leading indentation back in to the text-wrapped block + $textWrapBlockStorageValue =~ s/^/$subsequentSpace/mg; + + # remove the very first leading space, which is already handled by blocks follow + $textWrapBlockStorageValue =~ s/^\h*//s unless ${$self}{modifyLineBreaksYamlName} eq 'sentence'; + } + + # + # optionally wrap comments + # + if ( ${ ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{comments} }{wrap} + and $trailingComments ne '' ) + { + + my $commentValue = q(); + + # split the trailing comments, and put the *values* together + foreach ( split( /([0-9]+)$tokens{endOfToken}/, $trailingComments ) ) { + next unless $_ =~ m/[0-9]/; + + $commentValue .= ${ $trailingComments[ $_ - 1 ] }{value}; + } + +# leading comment space, e.g. +# +# % This is a very very long trailing comment that needs to be wrapped by latexindent to make sure the visual display is in a good shape. +# ^^^^^ +# + $commentValue =~ m/^(\h+)/s; + my $leadingCommentSpace = ( $1 ? $1 : ' ' ); + + # reset columns + $Text::Wrap::columns + = $columns - &get_column_width( ( split( /\R/, $textWrapBlockStorageValue ) )[-1] ); + $commentValue = wrap( '', '', $commentValue ); + + # the 2nd and subsequent lines need further attention + my @commentArray = ( split( /\R/, $commentValue ) ); + my $firstLine = shift(@commentArray); + my $secondCommentLineOnwards = join( " ", @commentArray ); + $secondCommentLineOnwards =~ s/\h{2,}/ /sg; + + # assemble the new trailing comments, which will be wrapped after this routine as a comment block + $trailingComments = "%" . $self->add_comment_symbol( value => $firstLine ); + $trailingComments .= "\n$subsequentSpace%" + . $self->add_comment_symbol( value => $leadingCommentSpace . $secondCommentLineOnwards ); + } + # append trailing comments from WITHIN the block $textWrapBlockStorageValue =~ s/\R?$/$trailingComments\n/s if ( $trailingComments ne '' ); @@ -383,4 +569,142 @@ sub text_wrap { } +sub text_wrap_comment_blocks { + + my $self = shift; + + # call the text wrapping routine + my $columns = ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{columns}; + + # + # text wrap comment blocks + # + # + # from: + # + # % first comment + # % second comment + # % third comment + # % fourth comment + # % fifth comment + # + # into: + # + # % first comment second comment + # % third comment fourth comment + # % fifth comment + # + ${$self}{body} =~ s&((?:^\h*$trailingCommentRegExp\R)+)& + my @commentBlocks = $1; + my $trailingComments = q(); + + # loop through comment blocks + foreach my $commentBlock (@commentBlocks){ + + my $leadingHorizontalSpace = ($commentBlock =~ m|^(\h*\t*)|s? $1 : q()); + my $numberOfTABS = () = $leadingHorizontalSpace =~ m/\t/g; + $leadingHorizontalSpace =~ s/\t/ /g; + + my $commentValue = q(); + $trailingComments = q(); + + # split the trailing comments, and put the *values* together + foreach (split(/([0-9]+)$tokens{endOfToken}/,$commentBlock)){ + next unless $_ =~ m/[0-9]/; + + $commentValue .= " ".${$trailingComments[$_-1]}{value}; + } + + # very first space + $commentValue =~ s|^\h||s; + + # leading space + $commentValue =~ s|^(\h*)||s; + my $leadingSpace = (${${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{comments}}{inheritLeadingSpace}? $1: ' ' ); + + $commentValue =~ s/\h{2,}/ /sg if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{multipleSpacesToSingle}; + + # reset columns + $Text::Wrap::columns = $columns - length($leadingHorizontalSpace)-length($leadingSpace); + # ^^ + # for the space added after comment symbol below + + # tab adjustment + for (my $i=1; $i<=$numberOfTABS;$i++){ + $leadingHorizontalSpace =~ s/ /\t/; + } + + # wrap the comments + $commentValue = wrap( '', '', $commentValue ); + + # put them into storage + $trailingComments .= $leadingHorizontalSpace."%".$self->add_comment_symbol(value=>$leadingSpace.$_)."\n" foreach (split( /\R/, $commentValue ) ); + + } + $trailingComments; + &xemg; + + # + # text wrap multiple comments on a line + # + # from: + # + # % fifth comment% fourth comment% third comment% second comment% first comment + # + # into: + # + # % first comment second comment + # % third comment fourth comment + # % fifth comment + # + ${$self}{body} =~ s&((?:$trailingCommentRegExp\h*)+)& + my @commentBlocks = $1; + my $trailingComments = q(); + + # loop through comment blocks + foreach my $commentBlock (@commentBlocks){ + + my $leadingHorizontalSpace = ($commentBlock =~ m|^(\h*\t*)|s? $1 : q()); + my $numberOfTABS = () = $leadingHorizontalSpace =~ m/\t/g; + $leadingHorizontalSpace =~ s/\t/ /g; + + my $commentValue = q(); + $trailingComments = q(); + + # split the trailing comments, and put the *values* together + foreach (split(/([0-9]+)$tokens{endOfToken}/,$commentBlock)){ + next unless $_ =~ m/[0-9]/; + + $commentValue .= " ".${$trailingComments[$_-1]}{value}; + } + + # very first space + $commentValue =~ s|^\h||s; + + # leading space + $commentValue =~ s|^(\h*)||s; + my $leadingSpace = (${${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{comments}}{inheritLeadingSpace}? $1: ' ' ); + + $commentValue =~ s/\h{2,}/ /sg if ${ $mainSettings{modifyLineBreaks}{textWrapOptions} }{multipleSpacesToSingle}; + + # reset columns + $Text::Wrap::columns = $columns - length($leadingHorizontalSpace)-length($leadingSpace); + # ^^ + # for the space added after comment symbol below + + # tab adjustment + for (my $i=1; $i<=$numberOfTABS;$i++){ + $leadingHorizontalSpace =~ s/ /\t/; + } + + # wrap the comments + $commentValue = wrap( '', '', $commentValue ); + + # put them into storage + $trailingComments .= $leadingHorizontalSpace."%".$self->add_comment_symbol(value=>$leadingSpace.$_)."\n" foreach (split( /\R/, $commentValue ) ); + + } + $trailingComments; + &xemg; +} 1; |