package LatexIndent::LogFile; # 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 FindBin; use File::Basename; # to get the filename and directory path use Exporter qw/import/; use Log::Log4perl qw(get_logger :levels); use Log::Log4perl::Appender::Screen; use Log::Dispatch::File; use LatexIndent::GetYamlSettings qw/%masterSettings/; use LatexIndent::Switches qw/%switches/; use LatexIndent::Version qw/$versionNumber $versionDate/; our @EXPORT_OK = qw/processSwitches $logger/; our @logFileNotes; our $logger = get_logger("Document"); # log file methods, using log4perl; references # pattern layout: http://search.cpan.org/~mschilli/Log-Log4perl-1.32/lib/Log/Log4perl/Layout/PatternLayout.pm # multiple appenders: https://stackoverflow.com/questions/8620347/perl-log4perl-printing-and-logging-at-the-same-time-in-a-line?rq=1 # getting started: https://www.perl.com/pub/2002/09/11/log4perl.html sub processSwitches{ # -v switch is just to show the version number if($switches{version}) { print $versionNumber,", ",$versionDate,"\n"; exit(2); } if(scalar(@ARGV) < 1 or $switches{showhelp}) { print < output to another file; sample usage: latexindent.pl -o outputfile.tex myfile.tex latexindent.pl -o=outputfile.tex myfile.tex -w, --overwrite overwrite the current file; a backup will be made, but still be careful -s, --silent silent mode: no output will be given to the terminal -t, --trace tracing mode: verbose information given to the log file -l, --local[=myyaml.yaml] use localSettings.yaml (assuming it exists in the directory of your file, or in the current working directory); alternatively, use myyaml.yaml, if it exists; sample usage: 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= 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= used to specify the name of logfile (default is indent.log) -c, --cruft= 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 and blank lines can also be added using this feature -r,--replacement replacement mode, allows you to replace strings and regular expressions verbatim blocks not respected -rv,--replacementrespectverb replacement mode, allows you to replace strings and regular expressions while respecting verbatim code blocks -rr,--onlyreplacement *only* replacement mode, no indentation verbatim blocks not respected ENDQUOTE ; exit(2); } # if we've made it this far, the processing of switches and logging begins my $self = shift; ($switches{trace}||$switches{ttrace}) ? $logger->level($TRACE): $logger->level($INFO); # cruft directory ${$self}{cruftDirectory} = $switches{cruftDirectory}||(dirname ${$self}{fileName}); die "Could not find directory ${$self}{cruftDirectory}\nExiting, no indentation done." if(!(-d ${$self}{cruftDirectory})); my $logfileName = ($switches{cruftDirectory} ? ${$self}{cruftDirectory}."/" : '').($switches{logFileName}||"indent.log"); # layout of the logfile information, for example # # 2017/09/16 11:59:09 INFO: message # 2017/09/16 12:23:53 INFO: LogFile.pm:156 LatexIndent::LogFile::processSwitches - message # reference: https://stackoverflow.com/questions/46262844/log4perl-grouping-messages/46309392#46309392 Log::Log4perl::Layout::PatternLayout::add_global_cspec( 'A', sub { if($_[1] =~ /^\*/){ $_[1]=~s/^\*//; if($_[1]=~m/\R/s){ my $indentation = ' '.(' ' x length $_[3]); $_[1] =~ s/\R/\n$indentation/gs; } return "$_[3]: ".$_[1]; } else { my $indentation = ' '.(' ' x length $_[3]); $_[1] =~ s/\R/\n$indentation/gs if($_[1]=~m/\R/s); return $indentation.$_[1]; } }); my $layout = Log::Log4perl::Layout::PatternLayout->new("%A%n"); # details for the Log4perl logging my $appender = Log::Log4perl::Appender->new( "Log::Dispatch::File", filename => $logfileName, mode => "write", utf8 => 1, ); # add the layout $appender->layout($layout); # adjust the logger object $logger->add_appender($appender); # appender object for output to screen my $appender_screen = q(); # output to screen, if appropriate if($switches{screenlog}){ $appender_screen = Log::Log4perl::Appender->new( "Log::Log4perl::Appender::Screen", stderr => 1, utf8 => 1, ); $appender_screen->layout($layout); $logger->add_appender($appender_screen); } # details of the script to log file $logger->info("*$FindBin::Script version $versionNumber, $versionDate, a script to indent .tex files"); $logger->info("$FindBin::Script lives here: $FindBin::RealBin/"); my $time = localtime(); $logger->info($time); if (${$self}{fileName} ne "-"){ $logger->info("Filename: ${$self}{fileName}"); } else { $logger->info("Reading input from STDIN"); if (-t STDIN) { my $buttonText = ($FindBin::Script eq 'latexindent.exe') ? 'CTRL+Z followed by ENTER':'CTRL+D'; print STDERR "Please enter text to be indented: (press $buttonText when finished)\n"; } } # log the switches from the user $logger->info("*Processing switches:"); # check on the trace mode switch (should be turned on if ttrace mode active) $switches{trace} = $switches{ttrace} ? 1 : $switches{trace}; # output details of switches $logger->info("-sl|--screenlog: log file will also be output to the screen") if($switches{screenlog}); $logger->info("-t|--trace: Trace mode active (you have used either -t or --trace)") if($switches{trace} and !$switches{ttrace}); $logger->info("-tt|--ttrace: TTrace mode active (you have used either -tt or --ttrace)") if($switches{ttrace}); $logger->info("-s|--silent: Silent mode active (you have used either -s or --silent)") if($switches{silentMode}); $logger->info("-d|--onlydefault: Only defaultSettings.yaml will be used (you have used either -d or --onlydefault)") if($switches{onlyDefault}); $logger->info("-w|--overwrite: Overwrite mode active, will make a back up of ${$self}{fileName} first") if($switches{overwrite}); $logger->info("-l|--localSettings: Read localSettings YAML file") if($switches{readLocalSettings}); $logger->info("-y|--yaml: YAML settings specified via command line") if($switches{yaml}); $logger->info("-o|--outputfile: output to file") if($switches{outputToFile}); $logger->info("-m|--modifylinebreaks: modify line breaks") if($switches{modifyLineBreaks}); $logger->info("-g|--logfile: logfile name") if($switches{logFileName}); $logger->info("-c|--cruft: cruft directory") if($switches{cruftDirectory}); $logger->info("-r|--replacement: replacement mode") if($switches{replacement}); $logger->info("-rr|--onlyreplacement: *only* replacement mode, no indentation") if($switches{onlyreplacement}); # check if overwrite and outputfile are active similtaneously if($switches{overwrite} and $switches{outputToFile}){ $logger->info("Options check, -w and -o specified\nYou have called latexindent.pl with both -o and -w\noutput to file) will take priority, and -w (over write) will be ignored"); $switches{overwrite}=0; } $logger->info("*Directory for backup files and $logfileName: ${$self}{cruftDirectory}"); # output location of modules if($FindBin::Script eq 'latexindent.pl' or ($FindBin::Script eq 'latexindent.exe' and $switches{trace} )) { my @listOfModules = ('FindBin', 'YAML::Tiny', 'File::Copy', 'File::Basename', 'Getopt::Long','File::HomeDir','Unicode::GCString','Log::Log4perl'); $logger->info("*Perl modules are being loaded from the following directories:"); foreach my $moduleName (@listOfModules) { (my $file = $moduleName) =~ s|::|/|g; $logger->info($INC{$file .'.pm'}); } $logger->info("*Latex Indent perl modules are being loaded from, for example:"); (my $file = 'LatexIndent::Document') =~ s|::|/|g; $logger->info($INC{$file .'.pm'}); } # read the YAML settings $self->yaml_read_settings; # the user may have specified their own settings for the rest of the log file, # for example: # # logFilePreferences: # PatternLayout: # default: "%p: %m{indent}%n" # trace: "%p: %m{indent}%n" # ttrace: "%d %p: %F{1}:%L %M - %m{indent}%n" # # e.g, default mode: # 2017/09/16 11:59:09 INFO: message # or trace mode: # 2017/09/16 11:59:09 INFO: message # or in trace mode: # 2017/09/16 12:23:53 INFO: LogFile.pm:156 LatexIndent::LogFile::processSwitches - message my $pattern = q(); if($switches{ttrace}){ $pattern = ${${$masterSettings{logFilePreferences}}{PatternLayout}}{ttrace}; } elsif($switches{trace}){ $pattern = ${${$masterSettings{logFilePreferences}}{PatternLayout}}{trace}; } else { $pattern = ${${$masterSettings{logFilePreferences}}{PatternLayout}}{default}; } $layout = Log::Log4perl::Layout::PatternLayout->new($pattern); $appender->layout($layout); $appender_screen->layout($layout) if $switches{screenlog}; return; } 1;