From bac237f29f6ca325050af70f4720d1af61c45bbe Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 29 Dec 2015 00:15:33 +0000 Subject: latexdiff (26dec15) git-svn-id: svn://tug.org/texlive/trunk@39223 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/scripts/latexdiff/latexdiff-vc.pl | 112 +++--- Master/texmf-dist/scripts/latexdiff/latexdiff.pl | 387 +++++++++++++++------ 2 files changed, 343 insertions(+), 156 deletions(-) (limited to 'Master/texmf-dist/scripts') diff --git a/Master/texmf-dist/scripts/latexdiff/latexdiff-vc.pl b/Master/texmf-dist/scripts/latexdiff/latexdiff-vc.pl index 7d954c15ec2..c8d6d3b7c5b 100755 --- a/Master/texmf-dist/scripts/latexdiff/latexdiff-vc.pl +++ b/Master/texmf-dist/scripts/latexdiff/latexdiff-vc.pl @@ -25,6 +25,13 @@ # # Detailed usage information at the end of the file # +# TODO/IDEAS: - option to call external pre-processing codes +# +# version 1.1.1: +# - better detection of RCS system +# - undocumented option --debug/--nodebug to override default setting for debug mode (Default: 0)# +# - bug fix: --flatten option combined with --pdf caused confusion of old and new file +# # version 1.1.0: # # - with option --flatten and version control option, checkout the whole tree into a temporary directory @@ -53,10 +60,13 @@ use strict ; use warnings ; my $versionstring=< \@revs, 'only-changes' => \$onlychanges, 'flatten:s' => \$flatten, 'version' => \$version, - 'help|h' => \$help); + 'help|h' => \$help, + 'debug!' => \$debug); + +##print STDERR "DEBUG 1:revs($#revs): " . join(":",@revs) . "\n"; +##print STDERR "DEBUG 1:ARGV($#ARGV): " . join(":",@ARGV) . "\n"; $extracomp = join(" ",grep(/BAR/,@ARGV)); # special latexdiff options requiring additional compilation @@ -125,12 +139,12 @@ if ( $git ) { # check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -r option if ( @revs && ( -f $revs[$#revs] || $revs[$#revs] =~ /^-/ ) ) { - unshift @ARGV,$revs[$#revs]; + push @ARGV,$revs[$#revs]; $revs[$#revs]=""; } # check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -d option if ( defined($dir) && ( -f $dir || $dir =~ /^-/ ) ) { - unshift @ARGV,$dir; + push @ARGV,$dir; $dir=""; } # check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty --flatten option @@ -139,8 +153,7 @@ if ( defined($flatten) && ( -f $flatten || $flatten =~ /^-/ ) ) { $flatten=""; } - -#print "DEBUG: latexdiff-vc command line: ", join(" ",@ARGV), "\n"; +print "DEBUG: PDF $pdf latexdiff-vc command line: ", join(" ",@ARGV), "\n" if $debug; $file2=pop @ARGV; ( defined($file2) && $file2 =~ /\.(tex|bbl|flt)$/ ) or pod2usage("Must specify at least one tex, bbl or flt file"); @@ -158,7 +171,7 @@ if (! $vc && scalar(@revs)>0 ) { $vc="GIT"; } elsif ( $0 =~ /-hg$/ ) { $vc="HG"; - } elsif ( -e "$file2,v" ) { + } elsif ( -e "$file2,v" || -d "RCS" ) { print STDERR "Guess you are using RCS ...\n"; $vc="RCS"; } elsif ( -d ".svn" ) { @@ -192,7 +205,7 @@ if ( scalar(@revs)>0 ) { $diffcmd = "rcsdiff -u -r"; $patchcmd = "patch -R -p0"; } elsif ( $vc eq "SVN" ) { - $diffcmd = "svn diff -r "; + $diffcmd = "svn diff --internal-diff -r "; $patchcmd = "patch -R -p0"; } elsif ( $vc eq "GIT" ) { $diffcmd = "git diff -r --relative --no-prefix "; @@ -231,7 +244,7 @@ if ( defined($flatten) ) { # impose ZLABEL subtype if --only-changes option if ( $onlychanges ) { - push @ldoptions, "-s", "ZLABEL" ; + push @ldoptions, "-s", "ZLABEL","-f","IDENTICAL" ; } if ( scalar(@revs) == 0 ) { @@ -244,7 +257,7 @@ if ( scalar(@revs) == 0 ) { if ( $flatten ) { pod2usage("Only one root file must be given if --flatten option is used with version control") if @files != 1; $tempdir='.' if ( $flatten eq "keep-intermediate" ); - print "flatten tempdir |$tempdir|"; + print "flatten tempdir |$tempdir|\n"; if ( $vc eq "SVN" ) { my (@infoout)=`svn info`; my (@urlline) = grep(/^URL:/, @infoout); @@ -277,7 +290,6 @@ if ( ($vc eq "SVN" || $vc eq "CVS") && scalar(@revs)) { length($revs[0]) > 0 or $revs[0]="HEAD"; } -#exit ; # cycle through all files @@ -352,7 +364,7 @@ while ( $infile=$file2=shift @files ) { die "Abort ... " ; } } - print "Running $latexdiff\n"; + print "Running: $latexdiff $options \"$file1\" \"$file2\" > \"$diff\"\n"; unless ( system("$latexdiff $options \"$file1\" \"$file2\" > \"$diff\"") == 0 ) { print STDERR "Something went wrong in $latexdiff. Deleting $diff and abort\n" ; unlink $diff ; exit(5) }; @@ -384,44 +396,44 @@ foreach $diff ( @difffiles ) { } if ( $pdf | $postscript ) { - print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n"; - - if ( system("grep -q \'^[^%]*\\\\bibliography\' \"$diff\"") == 0 ) { - system("$latexcmd --interaction=batchmode \"$diff\"; bibtex \"$diffbase\";"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } + print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n" if $debug; - # if special needs, as CHANGEBAR - if ( $extracomp ) { - # print "Extracomp\n"; - system("$latexcmd --interaction=batchmode \"$diff\";"); - } - - # final compilation - system("$latexcmd --interaction=batchmode \"$diff\";"); # needed if cross-refs - system("$latexcmd \"$diff\";"); # final, with possible error messages - - if ( $postscript ) { - my $dvi="$diffbase.dvi"; - my $ps="$diffbase.ps"; - my $ppoption=""; + if ( system("grep -q \'^[^%]*\\\\bibliography{\' \"$diff\"") == 0 ) { + system("$latexcmd --interaction=batchmode \"$diff\"; bibtex \"$diffbase\";"); + push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; + } - if ( $onlychanges ) { - $ppoption="-pp ".join(",",findchangedpages("$diffbase.aux")); + # if special needs, as CHANGEBAR + if ( $extracomp ) { + # print "Extracomp\n"; + system("$latexcmd --interaction=batchmode \"$diff\";"); } - system("dvips $ppoption -o $ps $dvi"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; - print "Generated postscript file $ps\n"; - } - elsif ( $pdf ) { - if ( $onlychanges ) { - my @pages=findchangedpages("$diffbase.aux"); - system ("pdftk \"$diffbase.pdf\" cat " . join(" ",@pages) . " output \"$diffbase-changedpage.pdf\"")==0 or - die ("Could not execute . Return code: $?"); - move("$diffbase-changedpage.pdf","$diffbase.pdf"); + + # final compilation + system("$latexcmd --interaction=batchmode \"$diff\";"); # needed if cross-refs + system("$latexcmd \"$diff\";"); # final, with possible error messages + + if ( $postscript ) { + my $dvi="$diffbase.dvi"; + my $ps="$diffbase.ps"; + my $ppoption=""; + + if ( $onlychanges ) { + $ppoption="-pp ".join(",",findchangedpages("$diffbase.aux")); + } + system("dvips $ppoption -o $ps $dvi"); + push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; + print "Generated postscript file $ps\n"; + } elsif ( $pdf ) { + if ( $onlychanges ) { + my @pages=findchangedpages("$diffbase.aux"); + ### print ("Running pdftk \"$diffbase.pdf\" cat " . join(" ",@pages) . " output \"$diffbase-changedpage.pdf\"\n") or + system ("pdftk \"$diffbase.pdf\" cat " . join(" ",@pages) . " output \"$diffbase-changedpage.pdf\"")==0 or + die ("Could not execute . Return code: $?"); + move("$diffbase-changedpage.pdf","$diffbase.pdf"); + } + push @ptmpfiles, "$diffbase.aux","$diffbase.log"; } - push @ptmpfiles, "$diffbase.aux","$diffbase.log"; - } } unlink @ptmpfiles; chdir $cwd; @@ -464,6 +476,7 @@ sub checkout_dir { if ( $vc eq "SVN" ) { system("svn checkout -r $rev $rootdir $dirname")==0 or die "Something went wrong in executing: svn checkout -r $rev $rootdir $dirname"; } elsif ( $vc eq "GIT" ) { + $rev="HEAD" if length($rev)==0; system("git archive --format=tar $rev | ( cd $dirname ; tar -xf -)")==0 or die "Something went wrong in executing: git archive --format=tar $rev | ( cd $dirname ; tar -xf -)"; } elsif ( $vc eq "HG" ) { system("hg archive --type files -r $rev $dirname")==0 or die "Something went wrong in executing: hg archive --type files -r $rev $dirname"; @@ -509,7 +522,7 @@ B [ F ] [ F ][ B<--posts =head1 DESCRIPTION I is a wrapper script that applies I to a -file, or multiple files under version control (CVS, RCS or SVN), and optionally runs the +file, or multiple files under version control (git, subversion (SVN), mercurial (hg), CVS, RCS), and optionally runs the sequence of C and C or C commands necessary to produce pdf or postscript output of the difference tex file(s). It can also be applied to a pair of files to automatise the generation of difference @@ -524,7 +537,7 @@ file in postscript or pdf format. Set the version system. If no version system is specified, latexdiff-vc will venture a guess. -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to +latexdiff-cvs, latexdiff-rcs etc are variants of latexdiff-vc which default to the respective versioning system. However, this default can still be overridden using the options above. =item B<-r>, B<-r> F or B<--revision>, B<--revision=>F @@ -633,11 +646,12 @@ or higher are required. =head1 BUG REPORTING Please submit bug reports using the issue tracker of the github repository page I, -or send them to I. Include the serial number of I +or send them to I. Include the version number of I (option C<--version>). =head1 AUTHOR +Version 1.1.1 Copyright (C) 2005-2015 Frederik Tilmann This program is free software; you can redistribute it and/or modify diff --git a/Master/texmf-dist/scripts/latexdiff/latexdiff.pl b/Master/texmf-dist/scripts/latexdiff/latexdiff.pl index 171c24be7ae..697571fd4a0 100755 --- a/Master/texmf-dist/scripts/latexdiff/latexdiff.pl +++ b/Master/texmf-dist/scripts/latexdiff/latexdiff.pl @@ -23,7 +23,14 @@ # Detailed usage information at the end of the file # # ToDo: -# DONE +# +# Version 1.1.1 +# - patch mhchem: allow ce in equations +# - flatten now also expands \input etc. in the preamble (but not \usepackage!) +# - Better support for Japanese ( contributed by github user kshramt ) +# - prevent duplicated verbatim hashes (patch contributed by github user therussianjig, issue #36) +# - disable deleted label commands (fixes issue #31) +# - introduce post-processing to reinstate most deleted environments and all needed item commands (fixes issue #1) # # Version 1.1.0 # - treat diacritics (\",\', etc) as safe commands @@ -582,7 +589,7 @@ my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); my ($versionstring)=<|\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; + my $cmdoptseq='\\\\[\w\d\*]+'.$extraspace.'(?:(?:<'.$abrat0.'>|\['.$brat0.'\]|\{'. $pat_n . '\}|\(' . $coords .'\))'.$extraspace.')*'; my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; + my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat_n . '\})*'; my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(](?:.|\n)*?\\\\[)]'; ## the current maths command cannot cope with newline within the math expression my $comment='%.*?\n'; @@ -1005,10 +1021,10 @@ push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); my ($oldfile, $newfile) = @ARGV; # check for existence of input files if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; + die "Input file $oldfile does not exist"; } if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; + die "Input file $newfile does not exist"; } @@ -1052,6 +1068,10 @@ exetime(1); if ($flatten) { $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); + # flatten preamble + $oldpreamble=flatten($oldpreamble,$oldpreamble,$oldfile,$encoding); + $newpreamble=flatten($newpreamble,$newpreamble,$newfile,$encoding); + } @@ -1179,7 +1199,7 @@ if (defined $packages{"glossaries"} ) { } } -if (defined $packages{"chemformula"} ) { +if (defined $packages{"chemformula"} or defined $packages{"chemmacros"} ) { print STDERR "chemformula package detected.\n" if $verbose ; init_regex_arr_ext(\@SAFECMDLIST,'ch'); push(@UNSAFEMATHCMD,'ch'); @@ -1191,7 +1211,7 @@ if (defined $packages{"chemformula"} ) { if (defined $packages{"mhchem"} ) { print STDERR "mhchem package detected.\n" if $verbose ; init_regex_arr_ext(\@SAFECMDLIST,'ce'); - push(@UNSAFEMATHCMD,'cee'); + push(@UNSAFEMATHCMD,'ce','cee'); # The next command would be needed to allow highlighting the interior of \cee commands in math environments # but the redefinitions in chemformula are too deep to make this viable # push(@MATHTEXTCMDLIST,'cee'); @@ -1235,6 +1255,11 @@ foreach $mboxcmd ( @MBOXCMDLIST ) { init_regex_arr_ext(\@SAFECMDLIST, $mboxcmd); } +# check if \label is in SAFECMDLIST, and if yes replace "label" in $LABELCMD by something that never matches (we hope!) +if ( iscmd("label",\@SAFECMDLIST,\@SAFECMDEXCL) ) { + $LABELCMD=~ s/label/NEVERMATCHLABEL/; +} + print STDERR "Preprocessing body. " if $verbose; @@ -1249,14 +1274,14 @@ if ( $debug ) { print RAWDIFF $diffbo; close(RAWDIFF); } -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; +print STDERR "(",exetime()," s)\n","Postprocessing body. \n" if $verbose; postprocess($diffbo); $diffall =join("\n",@diffpreamble) ; # add visible labels if (defined($visiblelabel)) { # Give information right after \begin{document} (or at the beginning of the text for files without preamble ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or + ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat_n)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; } @@ -1347,18 +1372,24 @@ sub read_file_with_encoding { # %packages=list_packages($preamble) # scans the arguments for \documentclass,\RequirePackage and \usepackage statements and constructs a hash # whose keys are the included packages, and whose values are the associated optional arguments +# if argument of \usepackage or \RequirePackage is comma separated list, treat as different packages sub list_packages { my ($preamble)=@_; my %packages=(); + my $pkg; # remove comments $preamble=~s/(?[$i] }; # store pure text blocks - if ($token =~ /$wpat/ || ( $token =~/^\\((?:[`'^"~=.]|[\w\d@\*]+))((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*)/o + if ($token =~ /$wpat/ || ( $token =~/^\\((?:[`'^"~=.]|[\w\d@\*]+))((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat_n\})*)/o && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { # we have text or a command which can be treated as text @@ -1910,7 +1941,7 @@ sub extractcommands { # $2: \cmd # $3: last argument # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) + if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat_n\})*${extraspace}\{)($pat_n)(\}\s*)$/so ) && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { # push(@$retval,[ $2,$index,$1,$3,$4 ]); ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; @@ -2062,8 +2093,8 @@ sub marktags { # $2: cmd # $3: last argument # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) + ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat_n\})*\{)($pat_n)(\}\s*)$/so ) + if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat_n\})*${extraspace}\{)($pat_n)(\}\s*)$/so ) && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above @@ -2097,7 +2128,6 @@ sub marktags { # "" local @SAFECMDLIST=(".*"); local @SAFECMDEXCL=('\\','\\\\',@UNSAFEMATHCMD); - ### print STDERR "DEBUG: Command $command argtext ",join(",",@argtext),"\n" if $debug; push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext ,$closingbracket); } else { @@ -2111,6 +2141,7 @@ sub marktags { push (@$retval,$opencmd) if $cmd==-1 ; push (@$retval,$close,$opencmd) if $cmd==0 ; $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line + ### print STDERR "MARKTAGS: Add command |$word|\n"; push (@$retval,$word); $cmd=1; } @@ -2127,7 +2158,7 @@ sub marktags { ###print STDERR "DEBUG Mboxsafecmd detected:$word:\n" if $debug ; push(@$retval,"\\mbox{$AUXCMD\n\\" . $1 . $2 . $3 ."}$AUXCMD\n" ); } else { - # $word is a normal word or a safe command (not in MBOXCMDLIST + # $word is a normal word or a safe command (not in MBOXCMDLIST) push (@$retval,$word); } $cmd=0; @@ -2140,6 +2171,53 @@ sub marktags { return @$retval; } +#used in preprocess +sub take_comments_and_enter_from_frac() { + ###*************take the \n and % between frac and {}*********** + ###notice all of the substitution are made none global + while( m/\\begin{($MATHENV|$MATHARRENV|SQUAREBRACKET)}(.*?)\\frac(([\s]*%[^\n]*?)*[\r\n|\r|\n])+\{(.*?)\\end{\1}/s ) { + ### if there isn't any % or \n in the pattern $2 then there should be an \\end{...} in $2 + if( $2 !~ m/\\end{$1}/s ) { + ### take out % and \n from the next match only (none global) + s/\\begin{($MATHENV|$MATHARRENV|SQUAREBRACKET)}(.*?)\\frac(([\s]*%[^\n]*?)*[\r\n|\r|\n])+\{(.*?)\\end{\1}/\\begin{$1}$2\\frac{$5\\end{$1}/s; + } + else{ + ###there are no more % and \n in $2, we want to find the next one so we clear the begin-end from the pattern + s/\\begin{($MATHENV|$MATHARRENV|SQUAREBRACKET)}(.*?)\\end{\1}/MATHBLOCK$1$2MATHBLOCKEND/s; + } + } + ###cleaning up + while( s/MATHBLOCK($MATHENV|$MATHARRENV|SQUAREBRACKET)(.*?)MATHBLOCKEND/\\begin{$1}$2\\end{$1}/s ){} + ###*************take the \n and % between frac and {}*********** + + ###**********take the \n and % between {} and {} of the frac*************** + while( m/\\begin\{($MATHENV|$MATHARRENV|SQUAREBRACKET)\}(.*?)\\frac\{(.*?)\\end\{\1\}/s ) { + ### if there isn't any more //frac before the first //end in the pattern $2 then there should be an \\end{...} in $2 + if( $2 !~ m/\\end\{$1\}/s ) { + ### from now on CURRFRAC is the frac we are looking at + s/\\begin\{($MATHENV|$MATHARRENV|SQUAREBRACKET)\}(.*?)\\frac\{(.*?)\\end\{\1\}/\\begin\{$1\}$2CURRFRAC\{$3\\end\{$1\}/s; + while( m/\\begin\{($MATHENV|$MATHARRENV|SQUAREBRACKET)\}(.*?)CURRFRAC\{(.*?)\\end\{\1\}/s ) { + if( m/\\begin\{($MATHENV|$MATHARRENV|SQUAREBRACKET)\}(.*?)CURRFRAC\{($pat_n)\}([\s]*(%[^\n]*?)*[\r\n|\r|\n])+[\s]*\{(.*?)\\end{\1}/s ) { + s/\\begin\{($MATHENV|$MATHARRENV|SQUAREBRACKET)\}(.*?)CURRFRAC\{($pat_n)\}([\s]*(%[^\n]*?)*[\r\n|\r|\n])+[\s]*\{(.*?)\\end\{\1\}/\\begin\{$1\}$2CURRFRAC\{$3\}\{$6\\end\{$1\}/s; + } + else { # there is no comment or \n between the two brackets {}{} + ### change CURRFRAC to FRACSTART so we can change them all back to //frac{ when we finish + s/\\begin{($MATHENV|$MATHARRENV|SQUAREBRACKET)}(.*?)CURRFRAC\{(.*?)\\end{\1}/\\begin{$1}$2FRACSTART\{$3\\end{$1}/s; + } + } + } + else{ + ###there are no more frac in $2, we want to find the next one so we clear the begin-end from the pattern + s/\\begin{($MATHENV|$MATHARRENV|SQUAREBRACKET)}(.*?)\\end{\1}/MATHBLOCK$1$2MATHBLOCKEND/s; + } + + } + ###cleaning up + while( s/MATHBLOCK($MATHENV|$MATHARRENV|SQUAREBRACKET)(.*?)MATHBLOCKEND/\\begin{$1}$2\\end{$1}/s ){} + s/FRACSTART/\\frac/g; + ###***************take the \n and % between {} and {} of the frac********************* +} + # preprocess($string, ..) # carry out the following pre-processing steps for all arguments: # 1. Remove leading white-space @@ -2165,7 +2243,7 @@ sub marktags { # Returns: leading white space removed in step 1 sub preprocess { for (@_) { - # Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE + # Change \{ to \QLEFTBRACE, \} to \QRIGHTBRACE, and \& to \AMPERSAND s/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; + while (1) { + foreach $val (@arr) { + $sum += $i*$val; + $i++; + } + $hstr= "$sum"; + last unless (defined($hash->{$hstr}) && $string ne $hash->{$hstr}); + # else found a duplicate HASH need to repeat for a higher hash value } $hash->{$hstr}=$string; + ### print STDERR "Hash:$hstr: Content:$string:\n"; return($hstr); } @@ -2293,6 +2378,8 @@ sub postprocess { # second level blocks my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); + my (@textparts,@newtextparts,@liststack,$listtype,$listlast); + for (@_) { # change $'s in comments to something harmless @@ -2375,14 +2462,25 @@ sub postprocess { # Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath # (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV # will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; + $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat_n)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; + $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat_n)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; } + # Reinstate completely deleted list environments. note that items within the + # environment will still be commented out. They will be restored later + $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{($LISTENV)\}\s*?(?:\n|$DELCMDCLOSE))(.*?)(\%DIFDELCMD < \s*\\end\{\2\})/{ + ### # block within the search; replacement environment + ### "$1\\begin{$2}$AUXCMD\n". restore_item_commands($3). "\n\\end{$2}$AUXCMD\n$4"; + "$1\\begin{$2}$AUXCMD\n$3\n\\end{$2}$AUXCMD\n$4"; + }/esg; # b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement # subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; + $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat_n\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; + +# bb. disable active labels within deleted blocks (as these are not safe commands, this should normally only +# happen within deleted maths blocks + $delblock=~ s/(\\$LABELCMD(?:${extraspace})\{(?:[^{}])*\}[\t ]*)\n?/${DELCMDOPEN}$1${DELCMDCLOSE}/smg ; # c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es @@ -2430,6 +2528,36 @@ sub postprocess { pos = $begin + length($addblock); } + # Go through whole text, and by counting list environment commands, find out when we are within a list environment. + # Within those restore deleted \item commands + @textparts=split /(? 0) { + $listlast=pop(@liststack); + ($listtype eq $listlast) or warn "Invalid nesting of list environments: $listlast environment closed by \\end{$listtype}."; + } else { + warn "Invalid nesting of list environments: \\end{$listtype} encountered without matching \\begin{$listtype}."; + } + } else { + print STDERR "DEBUG: postprocess \@liststack=(",join(",",@liststack),")\n" if $debug; + if (scalar @liststack > 0 ) { + # we are within a list environment and should replace all item commands + $_=restore_item_commands($_); + } + # else: we are outside a list environment and do not need to do anything + } + $_ } @textparts; # end of map command + # replace the main text with the modified version + $_= "@newtextparts"; + + # Replace MATHMODE environments from step 1a above by the correct Math environment @@ -2449,12 +2577,12 @@ sub postprocess { s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}$AUXCMD\n((?:\s*%.[^\n]*\n)*)\\end{\1}$AUXCMD\n/$2/sg; } else { # math modes OFF,WHOLE,COARSE: Convert \MATHBLOCKmath{..} commands back to environments - s/\\MATHBLOCK($MATHENV|$MATHARRENV|SQUAREBRACKET)\{($pat6)\}/\\begin{$1}$2\\end{$1}/sg; + s/\\MATHBLOCK($MATHENV|$MATHARRENV|SQUAREBRACKET)\{($pat_n)\}/\\begin{$1}$2\\end{$1}/sg; # convert ARRAYBLOCK.. commands back to environments - s/\\ARRAYBLOCK($ARRENV)\{($pat6)\}/\\begin{$1}$2\\end{$1}/sg; + s/\\ARRAYBLOCK($ARRENV)\{($pat_n)\}/\\begin{$1}$2\\end{$1}/sg; } # Convert all PICTUREblock{..} commands back to the appropriate environments - s/\\PICTUREBLOCK($PICTUREENV)\{($pat6)\}/\\begin{$1}$2\\end{$1}/sg; + s/\\PICTUREBLOCK($PICTUREENV)\{($pat_n)\}/\\begin{$1}$2\\end{$1}/sg; #0.5: # Remove all mark up within picture environments # while ( m/\\begin\{($PICTUREENV)\}.*?\\end\{\1\}/sg ) { # $cnt=0; @@ -2463,10 +2591,10 @@ sub postprocess { # $float=$&; # $float =~ s/\\DIFaddbegin //g; # $float =~ s/\\DIFaddend //g; -# $float =~ s/\\DIFadd\{($pat6)\}/$1/g; +# $float =~ s/\\DIFadd\{($pat_n)\}/$1/g; # $float =~ s/\\DIFdelbegin //g; # $float =~ s/\\DIFdelend //g; -# $float =~ s/\\DIFdel\{($pat6)\}//g; +# $float =~ s/\\DIFdel\{($pat_n)\}//g; # $float =~ s/$DELCMDOPEN.*//g; # substr($_,$begin,$len)=$float; # pos = $begin + length($float); @@ -2529,11 +2657,15 @@ sub postprocess { # 4. Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ s/\\begin\{DOLLARDOLLAR\}(.*?)\\end\{DOLLARDOLLAR\}/\$\$$1\$\$/sg; # 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} - 1 while s/\\SUPERSCRIPT{($pat6)}/^{$1}/g ; - 1 while s/\\SUPERSCRIPTNB{($pat0)}/^$1/g ; + 1 while s/\\SUPERSCRIPT(\s*{($pat_n)})/^$1/g ; + 1 while s/\\SUPERSCRIPTNB{(\s*$pat0)}/^$1/g ; # Convert \SUBSCRIPNB{n} into _n and \SUBCRIPT{nn} into _{nnn} - 1 while s/\\SUBSCRIPT{($pat6)}/_{$1}/g ; - 1 while s/\\SUBSCRIPTNB{($pat0)}/_$1/g ; + 1 while s/\\SUBSCRIPT(\s*{($pat_n)})/_$1/g ; + 1 while s/\\SUBSCRIPTNB{(\s*$pat0)}/_$1/g ; + # Convert \SQRT{n} into \sqrt{n} and \SQRTNB{nn} into \sqrt nn + 1 while s/\\SQRT(\s*{($pat_n)})/\\sqrt$1/g ; + 1 while s/\\SQRTNB{(\s*$pat0)}/\\sqrt$1/g ; + 1 while s/(%.*)\\CRIGHTBRACE (.*)$/$1\}$2/mg ; 1 while s/(%.*)\\CLEFTBRACE (.*)$/$1\{$2/mg ; @@ -2547,6 +2679,24 @@ sub postprocess { } } +# $out = restore_item_commands($listenviron) +# short helper function for post-process, which restores deleted \item commands in its argument (as DIFAUXCMDs) +sub restore_item_commands { + my ($string)=@_ ; + my ($itemarg,@itemargs); + $string =~ s/(\%DIFDELCMD < \s*(\\$ITEMCMD)((?:<$abrat0>)?)((?:\[$brat0\])?)\s*?(?:\n|$DELCMDCLOSE))/ + # if \item has an []argument, then mark up the argument as deleted) + if (length($4)>0) { + # use substr to exclude square brackets at end points + @itemargs=splitlatex(substr($4,1,length($4)-2)); + $itemarg="[".join("",marktags("","",$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,\@itemargs))."]"; + } else { + $itemarg=""; + } + "$1$2$3$itemarg$AUXCMD\n"/sge; + return($string); +} + # @auxlines=preprocess_preamble($oldpreamble,$newpreamble); # pre-process preamble by looking for commands used in \maketitle (title, author, date etc commands) @@ -2573,7 +2723,7 @@ sub preprocess_preamble { # resue in a more complex regex $titlecmd =~ s/[\$\^]//g; # make sure to not match on comment lines: - $titlecmdpat=qr/^(?:[^%\n]|\\%)*(\\($titlecmd)$extraspace(?:\[($brat0)\])?(?:\{($pat6)\}))/ms; + $titlecmdpat=qr/^(?:[^%\n]|\\%)*(\\($titlecmd)$extraspace(?:\[($brat0)\])?(?:\{($pat_n)\}))/ms; @oldtitlecommands= ( $$oldpreambleref =~ m/$titlecmdpat/g ); @newtitlecommands= ( $$newpreambleref =~ m/$titlecmdpat/g ); @@ -2801,7 +2951,7 @@ format as new.tex but has all changes relative to old.tex marked up or commented --subtype=markstyle -s markstyle Add code to preamble for selected style for bracketing commands (e.g. to mark changes in margin) - Available styles: SAFE MARGINAL DVIPSCOL COLOR ZLABEL ONLYCHANGEDPAGE (LABEL)* + Available styles: SAFE MARGIN DVIPSCOL COLOR ZLABEL ONLYCHANGEDPAGE (LABEL)* [ Default: SAFE ] * LABEL subtype is deprecated @@ -2892,15 +3042,17 @@ format as new.tex but has all changes relative to old.tex marked up or commented --config var1=val1,var2=val2,... -c var1=val1,.. Set configuration variables. -c configfile Available variables: - MINWORDSBLOCK (integer) + ARRENV (RegEx) + COUNTERCMD (RegEx) FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) + ITEMCMD (RegEx) + LISTENV (RegEx) MATHARRENV (RegEx) MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) + MATHENV (RegEx) + MATHREPL (String) + MINWORDSBLOCK (integer) + PICTUREENV (RegEx) This option can be repeated. @@ -2911,7 +3063,7 @@ format as new.tex but has all changes relative to old.tex marked up or commented Use of the --packages option disables automatic scanning, so if for any reason package specific parsing needs to be switched off, use --packages=none. The following packages trigger special behaviour: - endfloat hyperref amsmath apacite siunitx cleveref glossaries mhchem chemformula + endfloat hyperref amsmath apacite siunitx cleveref glossaries mhchem chemformula/chemmacros [ Default: scan the preamble for \\usepackage commands to determine loaded packages.] @@ -3159,7 +3311,7 @@ B<-s markstyle> Add code to preamble for selected style for bracketing commands (e.g. to mark changes in margin). This option defines C<\DIFaddbegin>, C<\DIFaddend>, C<\DIFdelbegin> and C<\DIFdelend> commands. -Available styles: C +Available styles: C [ Default: C ] * Subtype C