summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-02-24 22:07:42 +0000
committerKarl Berry <karl@freefriends.org>2017-02-24 22:07:42 +0000
commit990e60c6ed4437e5b632b7c9acf7f2237bbda871 (patch)
tree4dc9ea04f5fa46cc8ac59faa8dd62e4f8bc6835b /Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm
parent2e70942b44a972908c3180dd7a3c68be51afc466 (diff)
latexindent (23feb17)
git-svn-id: svn://tug.org/texlive/trunk@43326 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm')
-rw-r--r--Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm335
1 files changed, 335 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm
new file mode 100644
index 00000000000..7c951ec7995
--- /dev/null
+++ b/Master/texmf-dist/scripts/latexindent/LatexIndent/Document.pm
@@ -0,0 +1,335 @@
+package LatexIndent::Document;
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# See http://www.gnu.org/licenses/.
+#
+# Chris Hughes, 2017
+#
+# For all communication, please visit: https://github.com/cmhughes/latexindent.pl
+use strict;
+use warnings;
+use Data::Dumper;
+
+# gain access to subroutines in the following modules
+use LatexIndent::Switches qw/storeSwitches %switches $is_m_switch_active $is_t_switch_active $is_tt_switch_active/;
+use LatexIndent::LogFile qw/logger output_logfile processSwitches/;
+use LatexIndent::GetYamlSettings qw/readSettings modify_line_breaks_settings get_indentation_settings_for_this_object get_every_or_custom_value get_indentation_information get_object_attribute_for_indentation_settings alignment_at_ampersand_settings/;
+use LatexIndent::FileExtension qw/file_extension_check/;
+use LatexIndent::BackUpFileProcedure qw/create_back_up_file/;
+use LatexIndent::BlankLines qw/protect_blank_lines unprotect_blank_lines condense_blank_lines/;
+use LatexIndent::ModifyLineBreaks qw/modify_line_breaks_body modify_line_breaks_end remove_line_breaks_begin adjust_line_breaks_end_parent/;
+use LatexIndent::TrailingComments qw/remove_trailing_comments put_trailing_comments_back_in add_comment_symbol construct_trailing_comment_regexp/;
+use LatexIndent::HorizontalWhiteSpace qw/remove_trailing_whitespace remove_leading_space/;
+use LatexIndent::Indent qw/indent wrap_up_statement determine_total_indentation indent_begin indent_body indent_end_statement final_indentation_check get_surrounding_indentation indent_children_recursively check_for_blank_lines_at_beginning put_blank_lines_back_in_at_beginning add_surrounding_indentation_to_begin_statement/;
+use LatexIndent::Tokens qw/token_check %tokens/;
+use LatexIndent::HiddenChildren qw/find_surrounding_indentation_for_children update_family_tree get_family_tree check_for_hidden_children/;
+use LatexIndent::AlignmentAtAmpersand qw/align_at_ampersand find_aligned_block/;
+use LatexIndent::DoubleBackSlash qw/dodge_double_backslash un_dodge_double_backslash/;
+
+# code blocks
+use LatexIndent::Verbatim qw/put_verbatim_back_in find_verbatim_environments find_noindent_block find_verbatim_commands put_verbatim_commands_back_in/;
+use LatexIndent::Environment qw/find_environments/;
+use LatexIndent::IfElseFi qw/find_ifelsefi/;
+use LatexIndent::Arguments qw/get_arguments_regexp find_opt_mand_arguments get_numbered_arg_regexp construct_arguments_regexp/;
+use LatexIndent::OptionalArgument qw/find_optional_arguments/;
+use LatexIndent::MandatoryArgument qw/find_mandatory_arguments get_mand_arg_reg_exp/;
+use LatexIndent::RoundBrackets qw/find_round_brackets/;
+use LatexIndent::Item qw/find_items construct_list_of_items/;
+use LatexIndent::Braces qw/find_commands_or_key_equals_values_braces/;
+use LatexIndent::Command qw/construct_command_regexp/;
+use LatexIndent::KeyEqualsValuesBraces qw/construct_key_equals_values_regexp/;
+use LatexIndent::NamedGroupingBracesBrackets qw/construct_grouping_braces_brackets_regexp/;
+use LatexIndent::UnNamedGroupingBracesBrackets qw/construct_unnamed_grouping_braces_brackets_regexp/;
+use LatexIndent::Special qw/find_special construct_special_begin/;
+use LatexIndent::Heading qw/find_heading construct_headings_levels/;
+use LatexIndent::FileContents qw/find_file_contents_environments_and_preamble/;
+use LatexIndent::Preamble;
+
+sub new{
+ # Create new objects, with optional key/value pairs
+ # passed as initializers.
+ #
+ # See Programming Perl, pg 319
+ my $invocant = shift;
+ my $class = ref($invocant) || $invocant;
+ my $self = {@_};
+ bless ($self,$class);
+ return $self;
+}
+
+sub latexindent{
+ my $self = shift;
+ $self->storeSwitches;
+ $self->processSwitches;
+ $self->readSettings;
+ $self->file_extension_check;
+ $self->operate_on_file;
+}
+
+sub operate_on_file{
+ my $self = shift;
+
+ $self->create_back_up_file;
+ $self->token_check;
+ $self->construct_regular_expressions;
+ $self->find_noindent_block;
+ $self->find_verbatim_commands;
+ $self->find_aligned_block;
+ $self->remove_trailing_comments;
+ $self->find_verbatim_environments;
+ $self->protect_blank_lines;
+ $self->remove_trailing_whitespace(when=>"before");
+ $self->find_file_contents_environments_and_preamble;
+ $self->dodge_double_backslash;
+ $self->remove_leading_space;
+ $self->process_body_of_text;
+ $self->remove_trailing_whitespace(when=>"after");
+ $self->condense_blank_lines;
+ $self->unprotect_blank_lines;
+ $self->un_dodge_double_backslash;
+ $self->put_verbatim_back_in;
+ $self->put_trailing_comments_back_in;
+ $self->put_verbatim_commands_back_in;
+ $self->output_indented_text;
+ $self->output_logfile;
+ return
+}
+
+sub construct_regular_expressions{
+ my $self = shift;
+ $self->construct_trailing_comment_regexp;
+ $self->construct_list_of_items;
+ $self->construct_special_begin;
+ $self->construct_headings_levels;
+ $self->construct_arguments_regexp;
+ $self->construct_command_regexp;
+ $self->construct_key_equals_values_regexp;
+ $self->construct_grouping_braces_brackets_regexp;
+ $self->construct_unnamed_grouping_braces_brackets_regexp;
+
+}
+
+sub output_indented_text{
+ my $self = shift;
+
+ # output to screen, unless silent mode
+ print ${$self}{body} unless $switches{silentMode};
+
+ $self->logger("Output routine",'heading');
+
+ # if -overwrite is active then output to original fileName
+ if($switches{overwrite}) {
+ $self->logger("Overwriting file ${$self}{fileName}");
+ open(OUTPUTFILE,">",${$self}{fileName});
+ print OUTPUTFILE ${$self}{body};
+ close(OUTPUTFILE);
+ } elsif($switches{outputToFile}) {
+ $self->logger("Outputting to file $switches{outputToFile}");
+ open(OUTPUTFILE,">",$switches{outputToFile});
+ print OUTPUTFILE ${$self}{body};
+ close(OUTPUTFILE);
+ } else {
+ $self->logger("Not outputting to file; see -w and -o switches for more options.");
+ }
+ return;
+}
+
+sub process_body_of_text{
+ my $self = shift;
+
+ # find objects recursively
+ $self->logger('Phase 1: searching for objects','heading');
+ $self->find_objects;
+
+ # find all hidden child
+ $self->logger('Phase 2: finding surrounding indentation','heading');
+ $self->find_surrounding_indentation_for_children;
+
+ # indentation recursively
+ $self->logger('Phase 3: indenting objects','heading');
+ $self->indent_children_recursively;
+
+ # final indentation check
+ $self->logger('Phase 4: final indentation check','heading');
+ $self->final_indentation_check;
+
+ return;
+}
+
+sub find_objects{
+ my $self = shift;
+
+ # search for environments
+ $self->logger('looking for ENVIRONMENTS');
+ $self->find_environments;
+
+ # search for ifElseFi blocks
+ $self->logger('looking for IFELSEFI');
+ $self->find_ifelsefi;
+
+ # search for headings (part, chapter, section, setc)
+ $self->logger('looking for HEADINGS (chapter, section, part, etc)');
+ $self->find_heading;
+
+ # search for commands with arguments
+ $self->logger('looking for COMMANDS and key = {value}');
+ $self->find_commands_or_key_equals_values_braces;
+
+ # search for special begin/end
+ $self->logger('looking for SPECIAL begin/end');
+ $self->find_special;
+
+ # if there are no children, return
+ if(${$self}{children}){
+ $self->logger("Objects have been found.",'heading');
+ } else {
+ $self->logger("No objects found.");
+ return;
+ }
+
+ # logfile information
+ $self->logger(Dumper(\%{$self}),'ttrace') if($is_tt_switch_active);
+ $self->logger("Operating on: ${$self}{name}",'heading');
+ $self->logger("Number of children:",'heading');
+ $self->logger(scalar (@{${$self}{children}}));
+
+ return;
+}
+
+sub tasks_particular_to_each_object{
+ my $self = shift;
+ $self->logger("There are no tasks particular to ${$self}{name}") if $is_t_switch_active;
+}
+
+sub get_settings_and_store_new_object{
+ my $self = shift;
+
+ # grab the object to be operated upon
+ my ($latexIndentObject) = @_;
+
+ # there are a number of tasks common to each object
+ $latexIndentObject->tasks_common_to_each_object(%{$self});
+
+ # tasks particular to each object
+ $latexIndentObject->tasks_particular_to_each_object;
+
+ # store children in special hash
+ push(@{${$self}{children}},$latexIndentObject);
+
+}
+
+sub tasks_common_to_each_object{
+ my $self = shift;
+
+ # grab the parent information
+ my %parent = @_;
+
+ # update/create the ancestor information
+ if($parent{ancestors}){
+ $self->logger("Ancestors *have* been found for ${$self}{name}") if($is_t_switch_active);
+ push(@{${$self}{ancestors}},@{$parent{ancestors}});
+ } else {
+ $self->logger("No ancestors found for ${$self}{name}") if($is_t_switch_active);
+ if(defined $parent{id} and $parent{id} ne ''){
+ $self->logger("Creating ancestors with $parent{id} as the first one") if($is_t_switch_active);
+ push(@{${$self}{ancestors}},{ancestorID=>$parent{id},ancestorIndentation=>\$parent{indentation},type=>"natural",name=>${$self}{name}});
+ }
+ }
+
+ # natural ancestors
+ ${$self}{naturalAncestors} = q();
+ if(${$self}{ancestors}){
+ ${$self}{naturalAncestors} .= "---".${$_}{ancestorID}."\n" for @{${$self}{ancestors}};
+ }
+
+ # in what follows, $self can be an environment, ifElseFi, etc
+
+ # count linebreaks in body
+ my $bodyLineBreaks = 0;
+ $bodyLineBreaks++ while(${$self}{body} =~ m/\R/sxg);
+ ${$self}{bodyLineBreaks} = $bodyLineBreaks;
+
+ # get settings for this object
+ $self->get_indentation_settings_for_this_object;
+
+ # give unique id
+ $self->create_unique_id;
+
+ # add trailing text to the id to stop, e.g LATEX-INDENT-ENVIRONMENT1 matching LATEX-INDENT-ENVIRONMENT10
+ ${$self}{id} .= $tokens{endOfToken};
+
+ # the replacement text can be just the ID, but the ID might have a line break at the end of it
+ $self->get_replacement_text;
+
+ # the above regexp, when used below, will remove the trailing linebreak in ${$self}{linebreaksAtEnd}{end}
+ # so we compensate for it here
+ $self->adjust_replacement_text_line_breaks_at_end;
+
+ # modify line breaks on body and end statements
+ $self->modify_line_breaks_body;
+
+ # modify line breaks end statements
+ $self->modify_line_breaks_end;
+
+ # check the body for current children
+ $self->check_for_hidden_children;
+
+ return;
+}
+
+sub get_replacement_text{
+ my $self = shift;
+
+ # the replacement text can be just the ID, but the ID might have a line break at the end of it
+ ${$self}{replacementText} = ${$self}{id};
+ return;
+}
+
+sub adjust_replacement_text_line_breaks_at_end{
+ my $self = shift;
+
+ # the above regexp, when used below, will remove the trailing linebreak in ${$self}{linebreaksAtEnd}{end}
+ # so we compensate for it here
+ $self->logger("Putting linebreak after replacementText for ${$self}{name}") if($is_t_switch_active);
+ if(defined ${$self}{horizontalTrailingSpace}){
+ ${$self}{replacementText} .= ${$self}{horizontalTrailingSpace} unless(!${$self}{endImmediatelyFollowedByComment} and defined ${$self}{EndFinishesWithLineBreak} and ${$self}{EndFinishesWithLineBreak}==2);
+ }
+ ${$self}{replacementText} .= "\n" if(${$self}{linebreaksAtEnd}{end});
+
+}
+
+sub count_body_line_breaks{
+ my $self = shift;
+
+ my $oldBodyLineBreaks = (defined ${$self}{bodyLineBreaks})? ${$self}{bodyLineBreaks} : 0;
+
+ # count linebreaks in body
+ my $bodyLineBreaks = 0;
+ $bodyLineBreaks++ while(${$self}{body} =~ m/\R/sxg);
+ ${$self}{bodyLineBreaks} = $bodyLineBreaks;
+ $self->logger("bodyLineBreaks ${$self}{bodyLineBreaks}") if((${$self}{bodyLineBreaks} != $oldBodyLineBreaks) and $is_t_switch_active);
+}
+
+sub wrap_up_tasks{
+ my $self = shift;
+
+ # most recent child object
+ my $child = @{${$self}{children}}[-1];
+
+ # check if the last object was the last thing in the body, and if it has adjusted linebreaks
+ $self->adjust_line_breaks_end_parent;
+
+ $self->logger(Dumper(\%{$child})) if($is_tt_switch_active);
+ $self->logger("replaced with ID: ${$child}{id}") if $is_t_switch_active;
+
+}
+
+1;