summaryrefslogtreecommitdiff
path: root/support/latexindent/LatexIndent
diff options
context:
space:
mode:
Diffstat (limited to 'support/latexindent/LatexIndent')
-rw-r--r--support/latexindent/LatexIndent/Document.pm50
-rw-r--r--support/latexindent/LatexIndent/GetYamlSettings.pm118
-rw-r--r--support/latexindent/LatexIndent/Sentence.pm42
-rw-r--r--support/latexindent/LatexIndent/TrailingComments.pm12
-rw-r--r--support/latexindent/LatexIndent/Version.pm4
-rw-r--r--support/latexindent/LatexIndent/Wrap.pm354
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;