diff options
author | Karl Berry <karl@freefriends.org> | 2015-04-19 22:00:38 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-04-19 22:00:38 +0000 |
commit | 7b601b780e943de3059d5d0b619b5e45d44b1130 (patch) | |
tree | 12027dcca704189c58b6bdaf1c8c7e6f9b7eed18 /Master/texmf-dist/doc/support | |
parent | b42a24c600b1b547d19c9da07898d5496b821c16 (diff) |
latexdiff
git-svn-id: svn://tug.org/texlive/trunk@36943 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/support')
-rw-r--r-- | Master/texmf-dist/doc/support/latexdiff/Makefile | 2 | ||||
-rw-r--r-- | Master/texmf-dist/doc/support/latexdiff/README | 12 | ||||
-rw-r--r-- | Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.pdf | bin | 261188 -> 288437 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.tex | 2 | ||||
-rwxr-xr-x | Master/texmf-dist/doc/support/latexdiff/latexdiff | 562 | ||||
-rwxr-xr-x | Master/texmf-dist/doc/support/latexdiff/latexdiff-fast | 562 |
6 files changed, 854 insertions, 286 deletions
diff --git a/Master/texmf-dist/doc/support/latexdiff/Makefile b/Master/texmf-dist/doc/support/latexdiff/Makefile index 45467307879..148ead25611 100644 --- a/Master/texmf-dist/doc/support/latexdiff/Makefile +++ b/Master/texmf-dist/doc/support/latexdiff/Makefile @@ -46,7 +46,7 @@ install-latexrevise: install-latexdiff-vc: install latexdiff-vc $(INSTALLEXECPATH) - cd $(INSTALLEXECPATH); for vcs in cvs rcs svn ; do if [ -e latexdiff-$$vcs ]; then rm latexdiff-$$vcs; fi; ln -s latexdiff-vc latexdiff-$$vcs ; done + cd $(INSTALLEXECPATH); for vcs in cvs rcs svn git hg ; do if [ -e latexdiff-$$vcs ]; then rm latexdiff-$$vcs; fi; ln -s latexdiff-vc latexdiff-$$vcs ; done test-ext: @echo "latexdiff example/example-draft.tex example/example-rev.tex (system Algorithm::Diff)" diff --git a/Master/texmf-dist/doc/support/latexdiff/README b/Master/texmf-dist/doc/support/latexdiff/README index e9e189350e0..911b585deec 100644 --- a/Master/texmf-dist/doc/support/latexdiff/README +++ b/Master/texmf-dist/doc/support/latexdiff/README @@ -12,10 +12,10 @@ latexrevise, which accepts or rejects all changes. Manual editing of the difference file can be used to override this default behaviour and accept or reject selected changes only. -The author is F Tilmann (ftilmann@users.berlios.de). +The author is F Tilmann. -Project webpage: http://latexdiff.berlios.de/ -CTAN page: http://www.ctan.org/tex-archive/support/latexdiff +Project webpage: https://github.com/ftilmann/latexdiff/ +CTAN page: http://www.ctan.org/pkg/latexdiff REQUIREMENTS @@ -45,8 +45,8 @@ The basic installation procedure is almost trivial: 2. Copy latexdiff.1 and latexrevise.1 into the correct man directory -3. Optionally create soft links latexdiff-cvs latexdiff-rcs, and - latexdiff-svn for latexdiff-vc. +3. Optionally create soft links latexdiff-cvs latexdiff-rcs, latexdiff-git + latexdiff-svn and latexdiff-hg for latexdiff-vc. The attached trivial Makefile contains example commands to carry out above steps as root for a typical UNIX installation. Type @@ -91,7 +91,7 @@ latexdiff.spec (Author: T. Doerges) spec file for RPM generation latexchanges (Author: Jan-Ake Larsson) Wrapper script for applying latexdiff with numbered documen version (see contrib/README.latexchanges for a more detailed description) -Cntributions by the following authors were incorporated into the latexdiff code, or inspired me to +Contributions by the following authors were incorporated into the latexdiff code, or inspired me to extend latexdiff in a similar way: J. Paisley, N. Becker, K. Huebner LICENSE (also see file COPYING) diff --git a/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.pdf b/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.pdf Binary files differindex a3d640adfe2..f30d1869c86 100644 --- a/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.pdf +++ b/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.pdf diff --git a/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.tex b/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.tex index b6bb37effe6..2adffccd99a 100644 --- a/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.tex +++ b/Master/texmf-dist/doc/support/latexdiff/doc/latexdiff-man.tex @@ -6,7 +6,7 @@ %\setlength{\textwidth}{6.5in} %\setlength{\oddsidemargin}{0.0in} \title{Marking up differences between latex files with {\em latexdiff}} -\author{F.J. Tilmann\thanks{tilmann@gfz-potsdam.de,ftilmann@users.berlios.de}} +\author{F.J. Tilmann\thanks{tilmann@gfz-potsdam.de}} \date{\today} \begin{document} diff --git a/Master/texmf-dist/doc/support/latexdiff/latexdiff b/Master/texmf-dist/doc/support/latexdiff/latexdiff index 717a0933a2f..bb75ce4ac85 100755 --- a/Master/texmf-dist/doc/support/latexdiff/latexdiff +++ b/Master/texmf-dist/doc/support/latexdiff/latexdiff @@ -23,6 +23,19 @@ # Detailed usage information at the end of the file # # ToDo: +# DONE +# +# Version 1.1.0 +# - treat diacritics (\",\', etc) as safe commands +# - treat \_ and \& correctly as safe commands, even if used without spacing to the next word +# - Add a BOLD markup type that sets added text in bold face (Contribution by Victor Zabalza via pull request ) +# - add append-mboxsafecmd list option to be able to specify special safe commands which need to be surrounded by mbox to avoid breaking (mostly this is needed with ulem package) +# - support for siunitx and cleveref packages: protect \SI command in siunitx package and \cref,\Cref{range}{*} in cleveref packages (thanks to Stefan Pinnow for testing) +# - experimental support for chemformula, mhchem packages: define \ch and \ce in packages as safe (but not \ch,\cee in equation array environments) - these unfortunately will not be marked up (thanks to Stefan Pinnow for testing) +# - bug fix: packages identified correctly even if \usepackage command options extend over several lines (previously \usepackage command needed to be fully contained in one line) +# - new subtype ONLYCHANGEDPAGE outputs only changed pages (might not work well for floating material) +# - new subtype ZLABEL operates similarly to LABEL but uses absolute page numbers (needs zref package) +# - undocumented option --debug/--nodebug to override default setting for debug mode (Default: 0 for release version, 1: for development version # # Version 1.0.4 # - introduce list UNSAFEMATHCMD, which holds list of commands which cannot be marked up with \DIFadd or \DIFdel commands (only relevant for WHOLE and COARSE math markup modes) @@ -112,8 +125,8 @@ my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); my ($versionstring)=<<EOF ; -This is LATEXDIFF 1.0.4 (Algorithm::Diff $Algorithm::Diff::VERSION, Perl $^V) - (c) 2004-2014 F J Tilmann +This is LATEXDIFF 1.1.0 (Algorithm::Diff $Algorithm::Diff::VERSION, Perl $^V) + (c) 2004-2015 F J Tilmann EOF # Configuration variables: these have to be visible from the subroutines @@ -132,8 +145,6 @@ my $COUNTERCMD='(?:footnote|part|chapter|section|subsection|subsubsection|paragr # for the associated counter such that the overall numbers # should be the same as in the new file my @UNSAFEMATHCMD=('qedhere'); # Commands which are definitely unsafe for marking up (amsmath qedhere only tested to not work with UNDERLINE markup) -my $CITECMD=0 ; # \cite-type commands which need to be protected within an mbox in UNDERLINE and other modes using ulem; pattern simply designed to never match; will be overwritten later for selected styles -my $CITE2CMD=0; # \cite-type commands which should be reinstated in deleted blocks my $MBOXINLINEMATH=0; # if set to 1 then surround marked-up inline maths expression with \mbox ( to get around compatibility # problems between some maths packages and ulem package @@ -180,6 +191,9 @@ my @MATHTEXTCMDEXCL=(); # # Note I need to declare this with "our" instead of "my" because later in the code I have to "local"ise these our @SAFECMDLIST=(); # array containing patterns of safe commands (which do not break when in the argument of DIFadd or DIFDEL) our @SAFECMDEXCL=(); +my @MBOXCMDLIST=(); # patterns for commands which are in principle safe but which need to be surrounded by an \mbox +my @MBOXCMDEXCL=(); # all the patterns in MBOXCMDLIST will be appended to SAFECMDLIST + my ($i,$j,$l); my ($old,$new); @@ -199,6 +213,7 @@ my ($type,$subtype,$floattype,$config,$preamblefile,$encoding,$nolabel,$visiblel $replacecontext2,$appendcontext2, $help,$verbose,$driver,$version,$ignorewarnings, $enablecitmark,$disablecitmark,$allowspaces,$flatten,$debug,$earlylatexdiffpreamble); ###$disablemathmark, +my ($mboxsafe); # MNEMNONICS for mathmarkup my $mathmarkup; use constant { @@ -208,9 +223,11 @@ use constant { FINE => 3 }; +my ($mboxcmd); my (@configlist,@labels, @appendsafelist,@excludesafelist, + @appendmboxsafelist,@excludemboxsafelist, @appendtextlist,@excludetextlist, @appendcontext1list,@appendcontext2list, @packagelist); @@ -219,9 +236,6 @@ my ($assign,@config); # the optional arguments to the package are the values of the hash elements my ($pkg,%packages); # Defaults -$type='UNDERLINE'; -$subtype='SAFE'; -$floattype='FLOATSAFE'; $mathmarkup=COARSE; $verbose=0; @@ -267,6 +281,8 @@ GetOptions('type|t=s' => \$type, 'append-context1cmd=s' => \@appendcontext1list, 'replace-context2cmd=s' => \$replacecontext2, 'append-context2cmd=s' => \@appendcontext2list, + 'exclude-mboxsafecmd=s' => \@excludemboxsafelist, + 'append-mboxsafecmd=s' => \@appendmboxsafelist, 'show-preamble' => \$showpreamble, 'show-safecmd' => \$showsafe, 'show-textcmd' => \$showtext, @@ -275,14 +291,15 @@ GetOptions('type|t=s' => \$type, 'packages=s' => \@packagelist, 'allow-spaces' => \$allowspaces, 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, + 'enable-citation-markup|enforce-auto-mbox' => \$enablecitmark, + 'disable-citation-markup|disable-auto-mbox' => \$disablecitmark, 'verbose|V' => \$verbose, 'ignore-warnings' => \$ignorewarnings, 'driver=s'=> \$driver, 'flatten' => \$flatten, 'version' => \$version, - 'help|h|H' => \$help); + 'help|h|H' => \$help, + 'debug!' => \$debug ); if ( $help ) { usage() ; @@ -298,6 +315,14 @@ print STDERR $versionstring if $verbose; if (defined($showall)){ $showpreamble=$showsafe=$showtext=$showconfig=1; } +# Default types +$type='UNDERLINE' unless defined($type); +$subtype='SAFE' unless defined($subtype); +# set floattype to IDENTICAL for LABEL and ONLYCHANGEDPAGE subtype, unless it has been set explicitly on the command line +$floattype=($subtype eq 'LABEL' || $subtype eq 'ONLYCHANGEDPAGE') ? 'IDENTICAL' : 'FLOATSAFE' unless defined($floattype); +if ( $subtype eq 'LABEL' ) { + print STDERR "Note that LABEL subtype is deprecated. If possible, use ZLABEL instead (requires zref package)"; +} if (defined($mathmarkup)) { $mathmarkup=~tr/a-z/A-Z/; @@ -338,6 +363,15 @@ foreach $appendsafe ( @appendsafelist ) { foreach $excludesafe ( @excludesafelist ) { init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); } +# setting up @MBOXCMDLIST and @MBOXCMDEXCL +foreach $mboxsafe ( @appendmboxsafelist ) { + init_regex_arr_ext(\@MBOXCMDLIST, $mboxsafe); +} +foreach $mboxsafe ( @excludemboxsafelist ) { + init_regex_arr_ext(\@MBOXCMDEXCL, $mboxsafe); +} + + # setting up @TEXTCMDLIST and @TEXTCMDEXCL if (defined($replacetext)) { @@ -496,18 +530,19 @@ push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); my $mathpunct='[+=<>\-\|]'; my $and = '&'; my $coords= '[\-.,\s\d]*'; +# quoted underscore - this needs special treatment as perl treats _ as a letter (\w) but latex does not +# such that a\_b is interpreted as a{\_}b by latex but a{\_b} by perl + my $quotedunderscore='\\\\_'; # word: sequence of letters or accents followed by letter my $word='(?:[-\w\d*]|\\\\[\"\'\`~^][A-Za-z\*])+'; my $cmdleftright='\\\\(?:left|right|[Bb]igg?[lrm]?|middle)\s*(?:[<>()\[\]|]|\\\\(?:[|{}]|\w+))'; - my $cmdoptseq='\\\\[\w\d\*]+'.$extraspace.'(?:(?:<'.$abrat0.'>|\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; my $backslashnl='\\\\\n'; my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(](?:.|\n)*?\\\\[)]'; ## the current maths command cannot cope with newline within the math expression - my $comment='%.*?\n'; - my $pat=qr/(?:\A\s*)?(?:${and}|${quotemarks}|${number}|${word}|$cmdleftright|${cmdoptseq}|${math}|${backslashnl}|${oneletcmd}|${comment}|${punct}|${mathpunct}|\{|\})\s*/ ; + my $pat=qr/(?:\A\s*)?(?:${and}|${quotemarks}|${number}|${word}|$quotedunderscore|$cmdleftright|${cmdoptseq}|${math}|${backslashnl}|${oneletcmd}|${comment}|${punct}|${mathpunct}|\{|\})\s*/ ; # now we are done setting up and can start working my ($oldfile, $newfile) = @ARGV; @@ -566,6 +601,10 @@ if ($flatten) { my @auxlines; + +# boolean variab +my ($ulem)=0; + if ( length $oldpreamble && length $newpreamble ) { # pre-process preamble by looking for commands used in \maketitle (title, author, date etc commands) # and marking up content with latexdiff markup @@ -579,22 +618,19 @@ if ( length $oldpreamble && length $newpreamble ) { add_safe_commands($newpreamble); # get a list of packages from preamble if not predefine - %packages=list_packages(@newpreamble) unless %packages; - ### if ( %packages ) {print STDERR "DEBUG Packages: ",%packages,"\n" ;} + %packages=list_packages($newpreamble) unless %packages; + if ( %packages && $debug ) { my $key ; foreach $key (keys %packages) { print STDERR "DEBUG \\usepackage[",$packages{$key},"]{",$key,"}\n" ;} } + if (defined $packages{"hyperref"} ) { # deleted lines should not generate or appear in link names: print STDERR "hyperref package detected.\n" if $verbose ; $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - - if (defined $packages{"units"} && ( $latexdiffpreamble =~ /\\RequirePackage(?:\[$brat0\])?\{ulem\}/ ) ) { - # protect inlined maths environments by surrounding with an \mbox - # this is done to get around an incompatibility between the ulem and units package - # where spaces in the argument to underlined or crossed-out \unit commands cause an error message - print STDERR "units package detected at the same time as style using ulem.\n" if $verbose ; - $MBOXINLINEMATH=1; + ### $latexdiffpreamble .= '%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF FOR HYPERREF PACKAGE' . "\n"; + ### $latexdiffpreamble .= '\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}}' . "\n"; + ### $latexdiffpreamble .= '\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}}' . "\n"; + ### $latexdiffpreamble .= '%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF FOR HYPERREF PACKAGE' . "\n"; } print STDERR "Differencing preamble.\n" if $verbose; @@ -636,45 +672,116 @@ elsif ( !length $oldpreamble && !length $newpreamble ) { # package documentation) # Use post-processing # and $packages{"apacite"}!~/natbibpapa/ -my ($citpat,$citpatsafe); + +$ulem = ($latexdiffpreamble =~ /\\RequirePackage(?:\[$brat0\])?\{ulem\}/ || defined $packages{"ulem"}); + + +if (defined $packages{"units"} && $ulem ) { + # protect inlined maths environments by surrounding with an \mbox + # this is done to get around an incompatibility between the ulem and units package + # where spaces in the argument to underlined or crossed-out \unit commands cause an error message + print STDERR "units package detected at the same time as style using ulem.\n" if $verbose ; + $MBOXINLINEMATH=1; +} + +if (defined $packages{"siunitx"} ) { + # protect SI command by surrounding them with an \mbox + # this is done to get around an incompatibility between the ulem and siunitx package + print STDERR "siunitx package detected.\n" if $verbose ; + my $mboxcmds='SI,ang,numlist,numrange,SIlist,SIrange'; + init_regex_arr_ext(\@SAFECMDLIST,'num,si'); + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"cleveref"} ) { + # protect selected command by surrounding them with an \mbox + # this is done to get around an incompatibility between ulem and cleveref package + print STDERR "cleveref package detected.\n" if $verbose ; + my $mboxcmds='[Cc]ref(?:range)?\*?,labelcref,(?:lc)?name[cC]refs?' ; + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"glossaries"} ) { + # protect selected command by surrounding them with an \mbox + # this is done to get around an incompatibility between ulem and glossaries package + print STDERR "glossaries package detected.\n" if $verbose ; + my $mboxcmds='[gG][lL][sS](?:|pl|disp|link|first|firstplural|desc|user[iv][iv]?[iv]?),[aA][cC][rR](?:long|longpl|full|fullpl),[aA][cC][lfp]?[lfp]?'; + init_regex_arr_ext(\@SAFECMDLIST,'[gG][lL][sS](?:(?:entry)?(?:text|plural|name|symbol)|displaynumberlist|entryfirst|entryfirstplural|entrydesc|entrydescplural|entrysymbolplural|entryuser[iv][iv]?[iv]?|entrynumberlist|entrydisplaynumberlist|entrylong|entrylongpl|entryshort|entryshortpl|entryfull|entryfullpl),[gG]lossentry(?:name|desc|symbol),[aA][cC][rR](?:short|shortpl),[aA]csp?'); + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"chemformula"} ) { + print STDERR "chemformula package detected.\n" if $verbose ; + init_regex_arr_ext(\@SAFECMDLIST,'ch'); + push(@UNSAFEMATHCMD,'ch'); + # The next command would be needed to allow highlighting the interior of \ch commands in math environments + # but the redefinitions in chemformula are too deep to make this viable + # push(@MATHTEXTCMDLIST,'ch'); +} + +if (defined $packages{"mhchem"} ) { + print STDERR "mhchem package detected.\n" if $verbose ; + init_regex_arr_ext(\@SAFECMDLIST,'ce'); + push(@UNSAFEMATHCMD,'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'); +} + + +my ( $citpat); if ( defined $packages{"apacite"} ) { - print STDERR "DEBUG apacite citation commands\n" if $debug; - $citpatsafe=qr/^(?:mask)?(?:full|short)?cite(?:A|author|year)?(?:NP)?$/; + print STDERR "apacite package detected.\n" if $verbose ; $citpat='(?:mask)?(?:full|short|no)?cite(?:A|author|year|meta)?(?:NP)?'; } else { # citation command pattern for all other citation schemes - $citpatsafe=qr/^cite.*$/; $citpat='(?:cite\w*|nocite)'; }; -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, $citpatsafe); +if ( ! $ulem ) { + # modes not using ulem: citation is safe + push (@SAFECMDLIST, $citpat); } else { ### Experimental: disable text and emph commands - push (@SAFECMDLIST, $citpatsafe) unless $disablecitmark; push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing + push(@MBOXCMDLIST,$citpat) unless $disablecitmark; if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { # remove \cite command again from list of safe commands - pop @SAFECMDLIST; + pop @MBOXCMDLIST; # deleted cite commands - $CITE2CMD=$citpat unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD=$citpat unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem } } -$CITECMD=$citpat if $enablecitmark ; # as above for explicit selection +push(@MBOXCMDLIST,$citpat) if $enablecitmark ; -print STDERR "CITECMD:|$CITECMD|\n" if $debug; if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { print STDERR "amsmath package detected.\n" if $verbose ; $MATHARRREPL='align*'; } +# add commands in MBOXCMDLIST to SAFECMDLIST +foreach $mboxcmd ( @MBOXCMDLIST ) { + init_regex_arr_ext(\@SAFECMDLIST, $mboxcmd); +} + + + print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); +preprocess($oldbody,$newbody); # run difference algorithm @@ -696,7 +803,7 @@ if (defined($visiblelabel)) { $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; } -$diffall .= "$newleadin$diffbo" ; +$diffall .= "$diffbo" ; $diffall .= "\\end{document}$newpost" if length $newpreamble ; if ( lc($encoding) ne "utf8" && lc($encoding) ne "ascii" ) { print STDERR "Encoding output file to $encoding\n" if $verbose; @@ -758,22 +865,43 @@ sub read_file_with_encoding { return $output; } -# %packages=list_packages(@preamble) +## %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 +#sub list_packages { +# my (@preamble)=@_; +# my %packages=(); +# foreach $line ( @preamble ) { +# # get rid of comments +# $line=~s/(?<!\\)%.*$// ; +# if ( $line =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[(.+?)\])?\{(.*?)\}/ ) { +## print STDERR "Found something: |$line|\n" if $debug; +# if (defined($1)) { +# $packages{$2}=$1; +# } else { +# $packages{$2}=""; +# } +# } +# } +# return (%packages); +#} + + +# %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 sub list_packages { - my (@preamble)=@_; + my ($preamble)=@_; my %packages=(); - foreach $line ( @preamble ) { - # get rid of comments - $line=~s/(?<!\\)%.*$// ; - if ( $line =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[(.+?)\])?\{(.*?)\}/ ) { -# print STDERR "Found something: |$line|\n"; - if (defined($1)) { - $packages{$2}=$1; - } else { - $packages{$2}=""; - } + + # remove comments + $preamble=~s/(?<!\\)%.*$//mg ; + + while ( $preamble =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[($brat0)\])?\{(.*?)\}/gs ) { + if (defined($1)) { + $packages{$2}=$1; + } else { + $packages{$2}=""; } } return (%packages); @@ -859,6 +987,7 @@ sub flatten { # recursively replace \\input and \\include files $text=~s/(^(?:[^%\n]|\\%)*)\\input{(.*?)}|\\include{(${includeonly}(?:\.tex)?)}/{ + $begline=(defined($1)? $1 : "") ; $fname = $2 if defined($2) ; $fname = $3 if defined($3) ; # # add tex extension unless there is a three letter extension already @@ -870,7 +999,6 @@ sub flatten { ###$replacement=read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; $replacement=flatten(read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding), $preamble,$filename,$encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; # \include always starts a new page; use explicit \newpage command to simulate this - $begline=(defined($1)? $1 : "") ; $newpage=(defined($3)? " \\newpage " : "") ; "$begline$newpage$replacement$newpage"; }/exgm; @@ -887,19 +1015,17 @@ sub flatten { }/exgm; # replace subfile with contents (subfile package) $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $fname = $2; + $begline=(defined($1)? $1 : "") ; + $fname = $2; # # add tex extension unless there is a three letter extension already $fname .= ".tex" unless $fname =~ m|\.\w{3}|; - print STDERR "DEBUG Beg of line match |$1|\n" if defined($1) && $debug ; print STDERR "Include file as subfile $fname\n" if $verbose; - print STDERR "DEBUG looking for file ",File::Spec->catfile($dirname,$fname), "\n" if $debug; # content of file becomes replacement value (use recursion) # now strip away everything outside and including \begin{document} and \end{document} pair# # # note: no checking for comments is made $subfile=read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; ($subpreamble,$subbody,$subpost)=splitdoc($subfile,'\\\\begin\{document\}','\\\\end\{document\}'); $replacement=flatten($subbody, $preamble,$filename,$encoding); - $begline=(defined($1)? $1 : "") ; "$begline$replacement"; }/exgm; @@ -1024,10 +1150,10 @@ sub bodydiff { print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); + open(TOKENOLD,">","latexdiff.debug.tokenold2"); print TOKENOLD join("***\n",@oldwords); close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); + open(TOKENNEW,">","latexdiff.debug.tokennew2"); print TOKENNEW join("***\n",@newwords); close(TOKENNEW); } @@ -1045,10 +1171,15 @@ sub bodydiff { # Each element of words is either # a word (including trailing spaces and punctuation) # a latex command +# if there is white space in the beginning return that as first token sub splitlatex { - my ($string) = @_ ; + my ($inputstring) = @_ ; + my $string=$inputstring ; # if input is empty, return empty list length($string)>0 or return (); + $string=~s/^(\s*)//s; + my $leadin=$1; + length($string)>0 or return ($leadin); my @retval=($string =~ m/$pat/osg); @@ -1086,6 +1217,7 @@ sub splitlatex { } } + unshift(@retval,$leadin) if (length($leadin)>0); return @retval; } @@ -1135,7 +1267,7 @@ sub pass1 { # print STDERR "Unchanged block $cnt, $last1,$last2 \n"; if ($cnt < $MINWORDSBLOCK && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o + grep { /^$wpat/ || ( /^\\((?:[`'^"~=.]|[\w\d@*]+))((?:\[$brat0\]|\{$pat6\})*)/o && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) && scalar(@dummy=split(" ",$2))<3 ) } @$block) ) { @@ -1267,7 +1399,7 @@ sub extracttextblocks { for ($i=0;$i< scalar @$block;$i++) { ($token,$index)=@{ $block->[$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}\{$pat6\})*)/o && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { # we have text or a command which can be treated as text @@ -1411,7 +1543,7 @@ sub pass2 { } # marktags($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,\@block) -# returns ($openmark,$open,$block,$close,$closemark) if @block only contains no commands (except white-listed ones), +# returns ($openmark,$open,$block,$close,$closemark) if @block contains no commands (except white-listed ones), # braces, ampersands, or comments # mark comments with $comment # exclude all other exceptions from scope of open, close like this @@ -1431,8 +1563,11 @@ sub marktags { # split this block to flatten out sequences joined in pass1 @$block=splitlatex(join "",@$block); + ### print STDERR "DEBUG: marktags $openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment\n" if $debug; + ### print STDERR "DEBUG: marktags blocksplit ",join("|",@$block),"\n" if $debug; foreach (@$block) { $word=$_; + ### print STDERR "DEBUG MARKTAGS: |$word|\n" if $debug; if ( $word =~ s/^%/%$comment/ ) { # a comment if ($cmd==1) { @@ -1442,16 +1577,25 @@ sub marktags { push (@$retval,$word); next; } + if ( $word =~ m/^\s*$/ ) { + ### print STDERR "DEBUG MARKTAGS: whitespace detected |$word| cmdcom |$cmdcomment| |$opencmd|\n" if $debug; + # a sequence of white-space characters - this should only ever happen for the first element of block. + # in deleted block, omit, otherwise just copy it in + if ( ! $cmdcomment) { # ignore in deleted blocks + push(@$retval,$word); + } + next; + } if (! $noncomment) { push (@$retval,$openmark); $noncomment=1; } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) patterns + # negative lookahead pattern (?!) in second clause is put in to avoid matching \( .. \) patterns # also note that second pattern will match \\ - # Note: the second pattern should really be $word =~ /^\\(?!\()(\\|[\w*@]+)/, ie * replaced by + - # and then all commands \" \' etc declared safe. But as I don't have a complete list of one letter - # commands, and nobody has complained so far, I will eave this as is - if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\(?!\()(\\|[\w*@]*)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { + ### print STDERR "DEBUG marktags: Considering word |$word|\n"; + if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { + ###print STDERR "DEBUG MARKTAGS is a non-safe command ($1)\n" if $debug; + ### if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\([\w*@\\% ]+)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { # word is a command or other significant token (not in SAFECMDLIST) ## same conditions as in subroutine extractcommand: # check if token is an alphanumeric command sequence with at least one non-optional argument @@ -1496,6 +1640,7 @@ 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 { @@ -1513,10 +1658,21 @@ sub marktags { $cmd=1; } } else { - # just an ordinary word or word in SAFECMD + ###print STDERR "DEBUG MARKTAGS is an ordinary word or SAFECMD command \n" if $debug; + # just an ordinary word or command in SAFECMD push (@$retval,$open) if $cmd==-1 ; push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); + ###TODO: check here if it is a command in MBOXCMD list, and surround it with \mbox{...} + ### $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)/ && iscmd($1,\@MBOXCMDLIST,\@MBOXCMDEXCL)) + ### but actually this check has been carried out already so can simply check if word begins with backslash + if ( $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)(.*?)(\s*)$/s && iscmd($1,\@MBOXCMDLIST,\@MBOXCMDEXCL)) { + # $word is a safe command in MBOXCMDLIST + ###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 + push (@$retval,$word); + } $cmd=0; } } @@ -1530,7 +1686,7 @@ sub marktags { # preprocess($string, ..) # carry out the following pre-processing steps for all arguments: # 1. Remove leading white-space -# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE +# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE and \& to \AMPERSAND # #. Change {,} in comments to \CLEFTBRACE, \CRIGHTBRACE # 2. mark all first empty line (in block of several) with \PAR tokens # 3. Convert all '\%' into '\PERCENTAGE ' and all '\$' into \DOLLAR to make parsing regular expressions easier @@ -1551,13 +1707,11 @@ sub marktags { # names or labels but it does not matter because they are converted back in the postprocessing step # Returns: leading white space removed in step 1 sub preprocess { - my @leadin=() ; for (@_) { - s/^(\s*)//s; - push(@leadin,$1); # Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE s/(?<!\\)\\{/\\QLEFTBRACE /sg; s/(?<!\\)\\}/\\QRIGHTBRACE /sg; + s/(?<!\\)\\&/\\AMPERSAND /sg; # replace {,} in comments with \\CLEFTBRACE,\\CRIGHTBRACE 1 while s/((?<!\\)%.*)\{(.*)$/$1\\CLEFTBRACE $2/mg ; 1 while s/((?<!\\)%.*)\}(.*)$/$1\\CRIGHTBRACE $2/mg ; @@ -1590,7 +1744,6 @@ sub preprocess { # add final token " STOP" $_ .= " STOP" } - return(@leadin); } #hashstring=tohash(\%hash,$string) @@ -1674,7 +1827,7 @@ sub fromhash { # 10. package specific processing: endfloat: make sure \begin{figure} and \end{figure} are always # on a line by themselves, similarly for table environment # 4, undo renaming of the \begin, \end,{,} in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} +# Change \QLEFTBRACE, \QRIGHTBRACE,\AMPERSAND to \{,\},\& # # Note have to manually synchronize substitution commands below and # DIF.. command names in the header @@ -1693,10 +1846,6 @@ sub postprocess { # Replace \RIGHTBRACE by } s/\\RIGHTBRACE/}/g; - # change citation commands within comments to protect from processing - if ($CITECMD){ - 1 while s/(%.*)\\($CITECMD)/$1\\CITEDIF$2/m ; - } # Check all deleted blocks: where a deleted block contains a matching \begin and # \end environment (these will be disabled by a %DIFDELCMD statements), enable # these commands again (such that for example displayed math in a deleted equation @@ -1789,18 +1938,6 @@ sub postprocess { substr($delblock,$begin2,$len2)=$mathblock; pos($delblock) = $begin2 + length($mathblock); } - if ($CITE2CMD) { - $delblock=~s/($DELCMDOPEN\s*\\($CITE2CMD)(.*)$DELCMDCLOSE)/ - # Replacement code - {my ($aux,$all); - $aux=$all=$1; - $aux=~s#\n?($DELCMDOPEN|$DELCMDCLOSE)##g; - $all."$aux$AUXCMD\n";}/sge; - } - # or protect \cite commands with \mbox - if ($CITECMD) { - $delblock=~s/(\\($CITECMD)${extraspace}(?:<$abrat0>${extraspace})?(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } # if MBOXINLINEMATH is set, protect inlined math environments with an extra mbox if ( $MBOXINLINEMATH ) { # note additional \newline after command is omitted from output if right at the end of deleted block (otherwise a spurious empty line is generated) @@ -1826,14 +1963,6 @@ sub postprocess { substr($addblock,$begin2,$len2)=$mathblock; pos($addblock) = $begin2 + length($mathblock); } - if ($CITECMD) { - my $addblockbefore=$addblock; - #(?:mask)?(?:full|short|no)?cite(?:A|author|year|meta)(?:NP)?$/ - ###my $CITECMD; $CITECMD="cite(?:A)$"; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:<$abrat0>${extraspace})?(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - print STDERR "DEBUG: CITECMD $CITECMD\nDEBUG: addblock before:|$addblockbefore|\n" if $debug; - print STDERR "DEBUG: addblock after: |$addblock|\n" if $debug; - } # if MBOXINLINEMATH is set, protect inlined math environments with an extra mbox if ( $MBOXINLINEMATH ) { ##$addblock=~s/($math)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; @@ -1937,10 +2066,6 @@ sub postprocess { } # undo renaming of the \begin and \end,{,} and dollars in comments 1 while s/(%.*)DOLLARDIF/$1\$/mg ; - # undo renaming of the \cite.. commands in comments - if ( $CITECMD ) { - 1 while s/(%.*)\\CITEDIF($CITECMD)/$1\\$2/mg ; - } # Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] s/\\end{SQUAREBRACKET}/\\\]/sg; s/\\begin{SQUAREBRACKET}/\\\[/sg; @@ -1959,6 +2084,7 @@ sub postprocess { # Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} s/\\QLEFTBRACE /\\{/sg; s/\\QRIGHTBRACE /\\}/sg; + s/\\AMPERSAND /\\&/sg; return; } @@ -2212,14 +2338,15 @@ format as new.tex but has all changes relative to old.tex marked up or commented --type=markupstyle -t markupstyle Add code to preamble for selected markup style Available styles: UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE - CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR + CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR BOLD [ Default: UNDERLINE ] --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 LABEL + Available styles: SAFE MARGINAL DVIPSCOL COLOR ZLABEL ONLYCHANGEDPAGE (LABEL)* [ Default: SAFE ] + * LABEL subtype is deprecated --floattype=markstyle -f markstyle Add code to preamble for selected style which @@ -2294,6 +2421,16 @@ format as new.tex but has all changes relative to old.tex marked up or commented context2 commands are completely disabled in deleted sections, including their arguments. +--exclude-mboxsafecmd=exclude-file +--exclude-mboxsafecmd="cmd1,cmd2,..." +--append-mboxsafecmd=append-file +--append-mboxsafecmd="cmd1,cmd2,..." + Define safe commands, which additionally need to be protected by encapsulating + in an \\mbox{..}. This is sometimes needed to get around incompatibilities + between external packages and the ulem package, which is used for highlighting + in the default style UNDERLINE as well as CULINECHBAR CFONTSTRIKE + + --config var1=val1,var2=val2,... -c var1=val1,.. Set configuration variables. @@ -2317,7 +2454,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 + endfloat hyperref amsmath apacite siunitx cleveref glossaries mhchem chemformula [ Default: scan the preamble for \\usepackage commands to determine loaded packages.] @@ -2358,10 +2495,15 @@ Other configuration options: This mode is most suitable, if only minor changes to equations are expected, e.g. correction of typos. ---disable-citation-markup Suppress citation markup in styles using ulem (UNDERLINE, - FONTSTRIKE, CULINECHBAR) ---enable-citation-markup Protect citation commands in changed sections with \\mbox command - [i.e. use default behaviour for ulem package for other packages] +--disable-citation-markup +--disable-auto-mbox Suppress citation markup and markup of other vulnerable commands in styles + using ulem (UNDERLINE,FONTSTRIKE, CULINECHBAR) + (the two options are identical and are simply aliases) + +--enable-citation-markup +--enforce-auto-mbox Protect citation commands and other vulnerable commands in changed sections + with \\mbox command, i.e. use default behaviour for ulem package for other packages + (the two options are identical and are simply aliases) Miscelleneous options @@ -2550,7 +2692,7 @@ C<\DIFadd> and C<\DIFdel> commands. Available styles: C<UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR> +CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR BOLD> [ Default: C<UNDERLINE> ] @@ -2560,9 +2702,10 @@ 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<SAFE MARGINAL COLOR DVIPSCOL LABEL> +Available styles: C<SAFE MARGINAL COLOR DVIPSCOL ZLABEL ONLYCHANGEDPAGE (LABEL)*> [ Default: C<SAFE> ] +* Subtype C<LABEL> is deprecated =item B<--floattype=markstyle> or B<-f markstyle> @@ -2616,7 +2759,8 @@ The following packages trigger special behaviour: =item C<amsmath> -Configuration variable amsmath is set to C<align*> (Default: C<eqnarray*>) +Configuration variable MATHARRREPL is set to C<align*> (Default: C<eqnarray*>). (Note that many of the +amsmath array environments are already recognised by default as such) =item C<endfloat> @@ -2633,10 +2777,31 @@ errors). Redefine the commands recognised as citation commands. +=item C<siunitx> + +Treat C<\SI> as equivalent to citation commands (i.e. protect with C<\mbox> if markup style uses ulem package. + +=item C<cleveref> + +Treat C<\cref,\Cref>, etc as equivalent to citation commands (i.e. protect with C<\mbox> if markup style uses ulem package. + +=item C<glossaries> + +Define most of the glossaries commands as safe, protecting them with \mbox'es where needed + +=item C<mhchem> + +Treat C<\ce> as a safe command, i.e. it will be highlighted (note that C<\cee> will not be highlighted in equations as this leads to processing errors) + +=item C<chemformula> + +Treat C<\ch> as a safe command outside equations, i.e. it will be highlighted (note that C<\ch> will not be highlighted in equations as this leads to processing errors) + + =back -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] +[ Default: scan the preamble for C<\usepackage> commands to determine + loaded packages. ] @@ -2702,11 +2867,24 @@ argument is shown as deleted text. =item B<--append-context2cmd=append-file> or =item B<--append-context2cmd="cmd1,cmd2,..."> + As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments. +=item B<--exclude-mboxsafecmd=exclude-file> or B<--exclude-mboxsafecmd="cmd1,cmd2,..."> + +=item B<--append-mboxsafecmd=append-file> or B<--append-mboxsafecmd="cmd1,cmd2,..."> + +Define safe commands, which additionally need to be protected by encapsulating +in an \\mbox{..}. This is sometimes needed to get around incompatibilities +between external packages and the ulem package, which is used for highlighting +in the default style UNDERLINE as well as CULINECHBAR CFONTSTRIKE + + + + =item B<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> @@ -2791,14 +2969,17 @@ C<fine> or C<3>: Detect small change in equations and mark up at fine granularit This mode is most suitable, if only minor changes to equations are expected, e.g. correction of typos. -=item B<--disable-citation-markup> +=item B<--disable-citation-markup> or B<--disable-auto-mbox> -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) +Suppress citation markup and markup of other vulnerable commands in styles +using ulem (UNDERLINE,FONTSTRIKE, CULINECHBAR) +(the two options are identical and are simply aliases) -=item B<--enable-citation-markup> +=item B<--enable-citation-markup> or B<--enforce-auto-mbox> -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] +Protect citation commands and other vulnerable commands in changed sections +with C<\mbox> command, i.e. use default behaviour for ulem package for other packages +(the two options are identical and are simply aliases) =back @@ -2842,7 +3023,7 @@ Suppress inclusion of old and new file names as comment in output file =item B<--visble-label> -Include old and new filenames (or labels set with --label option) as +Include old and new filenames (or labels set with C<--label> option) as visible output. =item B<--flatten> @@ -2924,6 +3105,10 @@ No mark up of text, but mark margins with changebars (Requires changebar package No visible markup (but generic markup commands will still be inserted. +=item C<BOLD> + +Added text is set in bold face, discarded is not shown. + =back =head2 Subtypes @@ -2956,6 +3141,20 @@ that C<DVIPSCOL> only works with the dvips converter, e.g. not pdflatex. (it is recommeneded to use instead the main types to effect colored markup, although in some cases coloring with dvipscol can be more complete). + +=item C<ZLABEL> + +can be used to highlight only changed pages, but requires post-processing. It is recommend to not call this option manually but use C<latexdiff-vc> with C<--only-changes> option. Alternatively, use the script given within preamble of diff files made using this style. + +=item C<ONLYCHANGEDPAGE> + +also highlights changed pages, without the need for post-processing, but might not work reliably if +there is floating material (figures, tables). + +=item C<LABEL> + +is similar to C<ZLABEL>, but does not need the zref package and works less reliably (deprecated). + =back =head2 Float Types @@ -3042,26 +3241,34 @@ C<|subsubsection|paragraph|subparagraph)> ] =back -=head1 COMMON PROBLEMS +=head1 COMMON PROBLEMS AND FAQ =over 10 =item Citations result in overfull boxes There is an incompatibility between the C<ulem> package, which C<latexdiff> uses for underlining and striking out in the UNDERLINE style, -the default style. In order to be able to mark up citations properly, they are placed with an C<\mbox> command in post-processing. As mboxes -cannot be broken across lines, this procedure frequently results in overfull boxes, possibly obscuring the content as it extends beyond the right margin. If this is a problem, you have two possibilities: +the default style, and the way citations are generated. In order to be able to mark up citations properly, they are enclosed with an C<\mbox> +command. As mboxes cannot be broken across lines, this procedure frequently results in overfull boxes, possibly obscuring the content as it extends beyond the right margin. The same occurs for some other packages (e.g., siunitx). If this is a problem, you have two possibilities. -1. Use C<COLOR> or C<DVIPSCOL> subtype markup (option C<-s COLOR>): If this markup is chosen, then changed citations are no longer marked up -with the wavy line (additions) or struck out (deletions), but are still highlighted in the appropriate color. +1. Use C<CFONT> type markup (option C<-t CFONT>): If this markup is chosen, then changed citations are no longer marked up +with the wavy line (additions) or struck out (deletions), but are still highlighted in the appropriate color, and deleted text is shown with a different font. Other styles not using the C<ulem> package will also work. 2. Choose option C<--disable-citation-markup> which turns off the marking up of citations: deleted citations are no longer shown, and -added ctations are shown without markup. (This was the default behaviour of latexdiff at versions 0.6 and older) +added citations are shown without markup. (This was the default behaviour of latexdiff at versions 0.6 and older) + +For custom packages you can define the commands which need to be protected by C<\mbox> with C<--append-mboxsafecmd> and C<--excludemboxsafecmd> options +(submit your lists of command as feature request at github page to set the default behaviour of future versions, see section 6) =item Changes in complicated mathematical equations result in latex processing errors Try options C<--math-markup=whole>. If even that fails, you can turn off mark up for equations with C<--math-markup=off>. +=item How can I just show the pages + +Use options -C<-s ZLABEL> (some postprocessing required) or C<-s ONLYCHANGEDPAGE>. C<latexdiff-vc --ps|--pdf> with C<--only-changes> option takes care of +the post-processing for you (requires zref packages). + =back =head1 BUGS @@ -3071,7 +3278,7 @@ the rules that number and type of white space does not matter, as different numbers of inter-argument spaces are treated as significant. Please submit bug reports using the issue tracker of the github repository page I<https://github.com/ftilmann/latexdiff.git>, -or send them to I<tilmann@gfz-potsdam.de>. Include the serial number of I<latexdiff> +or send them to I<tilmann -- AT -- gfz-potsdam.de>. Include the serial number of I<latexdiff> (from comments at the top of the source or use B<--version>). If you come across latex files that are error-free and conform to the specifications set out above, and whose differencing still does not result in error-free @@ -3098,8 +3305,8 @@ I<latexdiff-fast> requires the I<diff> command to be present. =head1 AUTHOR -Version 1.0.4 -Copyright (C) 2004-2012 Frederik Tilmann +Version 1.1.0 +Copyright (C) 2004-2015 Frederik Tilmann This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 @@ -3323,7 +3530,10 @@ min Pr sec sup -[Hclbdruvt] +[Hclbkdruvt] +[`'^"~=.] +_ +AMPERSAND (SUPER|SUB)SCRIPTNB (SUPER|SUB)SCRIPT PERCENTAGE @@ -3364,12 +3574,12 @@ sqrt %%END TEXT COMMANDS %%BEGIN CONTEXT1 COMMANDS -% Regex matching commands with a text argument (leave out the \), which will fail out of context, but whose argument should be printed as plain text +% Regex matching commands with a text argument (leave out the \), which will fail out of context. These commands behave like text commands, except when they occur in a deleted section, where they are disabled, but their argument is shown as deleted text. caption %%END CONTEXT1 COMMANDS %%BEGIN CONTEXT2 COMMANDS -% Regex matching commands with a text argument (leave out the \), which will fail out of context, but whose argument should be printed as plain text +% Regex matching commands with a text argument (leave out the \), which will fail out of context. As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments. title author date @@ -3444,6 +3654,10 @@ institute \providecommand{\DIFdel}[1]{} %DIF END INVISIBLE PREAMBLE +%DIF BOLD PREAMBLE +\providecommand{\DIFadd}[1]{{\bf #1}} +\providecommand{\DIFdel}[1]{} +%DIF END BOLD PREAMBLE %% SUBTYPES (Markers for beginning and end of changed blocks) @@ -3481,24 +3695,94 @@ institute %DIF LABEL PREAMBLE % To show only pages with changes (pdf) (external program pdftk needs to be installed) -% (only works for simple documents with non-repeated page numbers) +% (only works for simple documents with non-repeated page numbers, otherwise use ZLABEL) +% pdflatex diff.tex +% pdflatex diff.tex +%pdftk diff.pdf cat \ +%`perl -lne '\ +% if (m/\\newlabel{DIFchg[b](\d*)}{{.*}{(.*)}}/) { $start{$1}=$2; print $2}\ +% if (m/\\newlabel{DIFchg[e](\d*)}{{.*}{(.*)}}/) { \ +% if (defined($start{$1})) { \ +% for ($j=$start{$1}; $j<=$2; $j++) {print "$j";}\ +% } else { \ +% print "$2"\ +% }\ +% }' diff.aux \ +% | uniq \ +% | tr \\n ' '` \ +% output diff-changedpages.pdf +% To show only pages with changes (dvips/dvipdf) +% dvips -pp `\ +% [ put here the perl script from above] +% | uniq | tr -s \\n ','` +\typeout{Check comments in preamble of output for instructions how to show only pages where changes have been made} +\newcount\DIFcounterb +\global\DIFcounterb 0\relax +\newcount\DIFcountere +\global\DIFcountere 0\relax +\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} +\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} +%DIF END LABEL PREAMBLE + +%DIF ZLABEL PREAMBLE +% To show only pages with changes (pdf) (external program pdftk needs to be installed) +% (uses zref for reference to absolute page numbers) % pdflatex diff.tex % pdflatex diff.tex -% pdftk diff.pdf cat `perl -lne 'if (m/\\newlabel{DIFchg[be]\d*}{{.*}{(.*)}}/) { print $1 }' diff.aux | uniq | tr -s \\n ' '` output diff-changedpages.pdf +%pdftk diff.pdf cat \ +%`perl -lne 'if (m/\\zref\@newlabel{DIFchgb(\d*)}{.*\\abspage{(\d*)}}/ ) { $start{$1}=$2; print $2 } \ +% if (m/\\zref\@newlabel{DIFchge(\d*)}{.*\\abspage{(\d*)}}/) { \ +% if (defined($start{$1})) { \ +% for ($j=$start{$1}; $j<=$2; $j++) {print "$j";}\ +% } else { \ +% print "$2"\ +% }\ +% }' diff.aux \ +% | uniq \ +% | tr \\n ' '` \ +% output diff-changedpages.pdf % To show only pages with changes (dvips/dvipdf) % latex diff.tex % latex diff.tex % dvips -pp `perl -lne 'if (m/\\newlabel{DIFchg[be]\d*}{{.*}{(.*)}}/) { print $1 }' diff.aux | uniq | tr -s \\n ','` diff.dvi \typeout{Check comments in preamble of output for instructions how to show only pages where changes have been made} +\usepackage[user,abspage]{zref} \newcount\DIFcounterb \global\DIFcounterb 0\relax \newcount\DIFcountere \global\DIFcountere 0\relax -\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} %DIF PREAMBLE -\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} %DIF PREAMBLE -\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} %DIF PREAMBLE -%DIF END LABEL PREAMBLE +\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\zlabel{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\zlabel{DIFchge\the\DIFcountere}} +\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\zlabel{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\zlabel{DIFchge\the\DIFcountere}} +%DIF END ZLABEL PREAMBLE + +%DIF ONLYCHANGEDPAGE PREAMBLE +\RequirePackage{atbegshi} +\RequirePackage{etoolbox} +\RequirePackage{zref} +% redefine label command to write immediately to aux file - page references will be lost +\makeatletter \let\oldlabel\label% Store \label +\renewcommand{\label}[1]{% Update \label to write to the .aux immediately +\zref@wrapper@immediate{\oldlabel{#1}}} +\makeatother +\newbool{DIFkeeppage} +\newbool{DIFchange} +\boolfalse{DIFkeeppage} +\boolfalse{DIFchange} +\AtBeginShipout{% + \ifbool{DIFkeeppage} + {\global\boolfalse{DIFkeeppage}} % True DIFkeeppage + {\ifbool{DIFchange}{\global\boolfalse{DIFkeeppage}}{\global\boolfalse{DIFkeeppage}\AtBeginShipoutDiscard}} % False DIFkeeppage +} +\providecommand{\DIFaddbegin}{\global\booltrue{DIFkeeppage}\global\booltrue{DIFchange}} +\providecommand{\DIFaddend}{\global\booltrue{DIFkeeppage}\global\boolfalse{DIFchange}} +\providecommand{\DIFdelbegin}{\global\booltrue{DIFkeeppage}\global\booltrue{DIFchange}} +\providecommand{\DIFdelend}{\global\booltrue{DIFkeeppage}\global\boolfalse{DIFchange}} +%DIF END ONLYCHANGEDPAGE PREAMBLE + %% FLOAT TYPES %DIF FLOATSAFE PREAMBLE diff --git a/Master/texmf-dist/doc/support/latexdiff/latexdiff-fast b/Master/texmf-dist/doc/support/latexdiff/latexdiff-fast index 22f2f8f0344..01638677113 100755 --- a/Master/texmf-dist/doc/support/latexdiff/latexdiff-fast +++ b/Master/texmf-dist/doc/support/latexdiff/latexdiff-fast @@ -23,6 +23,19 @@ # Detailed usage information at the end of the file # # ToDo: +# DONE +# +# Version 1.1.0 +# - treat diacritics (\",\', etc) as safe commands +# - treat \_ and \& correctly as safe commands, even if used without spacing to the next word +# - Add a BOLD markup type that sets added text in bold face (Contribution by Victor Zabalza via pull request ) +# - add append-mboxsafecmd list option to be able to specify special safe commands which need to be surrounded by mbox to avoid breaking (mostly this is needed with ulem package) +# - support for siunitx and cleveref packages: protect \SI command in siunitx package and \cref,\Cref{range}{*} in cleveref packages (thanks to Stefan Pinnow for testing) +# - experimental support for chemformula, mhchem packages: define \ch and \ce in packages as safe (but not \ch,\cee in equation array environments) - these unfortunately will not be marked up (thanks to Stefan Pinnow for testing) +# - bug fix: packages identified correctly even if \usepackage command options extend over several lines (previously \usepackage command needed to be fully contained in one line) +# - new subtype ONLYCHANGEDPAGE outputs only changed pages (might not work well for floating material) +# - new subtype ZLABEL operates similarly to LABEL but uses absolute page numbers (needs zref package) +# - undocumented option --debug/--nodebug to override default setting for debug mode (Default: 0 for release version, 1: for development version # # Version 1.0.4 # - introduce list UNSAFEMATHCMD, which holds list of commands which cannot be marked up with \DIFadd or \DIFdel commands (only relevant for WHOLE and COARSE math markup modes) @@ -673,8 +686,8 @@ my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); my ($versionstring)=<<EOF ; -This is LATEXDIFF 1.0.4 (Algorithm::Diff $Algorithm::Diff::VERSION, Perl $^V) - (c) 2004-2014 F J Tilmann +This is LATEXDIFF 1.1.0 (Algorithm::Diff $Algorithm::Diff::VERSION, Perl $^V) + (c) 2004-2015 F J Tilmann EOF # Configuration variables: these have to be visible from the subroutines @@ -693,8 +706,6 @@ my $COUNTERCMD='(?:footnote|part|chapter|section|subsection|subsubsection|paragr # for the associated counter such that the overall numbers # should be the same as in the new file my @UNSAFEMATHCMD=('qedhere'); # Commands which are definitely unsafe for marking up (amsmath qedhere only tested to not work with UNDERLINE markup) -my $CITECMD=0 ; # \cite-type commands which need to be protected within an mbox in UNDERLINE and other modes using ulem; pattern simply designed to never match; will be overwritten later for selected styles -my $CITE2CMD=0; # \cite-type commands which should be reinstated in deleted blocks my $MBOXINLINEMATH=0; # if set to 1 then surround marked-up inline maths expression with \mbox ( to get around compatibility # problems between some maths packages and ulem package @@ -741,6 +752,9 @@ my @MATHTEXTCMDEXCL=(); # # Note I need to declare this with "our" instead of "my" because later in the code I have to "local"ise these our @SAFECMDLIST=(); # array containing patterns of safe commands (which do not break when in the argument of DIFadd or DIFDEL) our @SAFECMDEXCL=(); +my @MBOXCMDLIST=(); # patterns for commands which are in principle safe but which need to be surrounded by an \mbox +my @MBOXCMDEXCL=(); # all the patterns in MBOXCMDLIST will be appended to SAFECMDLIST + my ($i,$j,$l); my ($old,$new); @@ -760,6 +774,7 @@ my ($type,$subtype,$floattype,$config,$preamblefile,$encoding,$nolabel,$visiblel $replacecontext2,$appendcontext2, $help,$verbose,$driver,$version,$ignorewarnings, $enablecitmark,$disablecitmark,$allowspaces,$flatten,$debug,$earlylatexdiffpreamble); ###$disablemathmark, +my ($mboxsafe); # MNEMNONICS for mathmarkup my $mathmarkup; use constant { @@ -769,9 +784,11 @@ use constant { FINE => 3 }; +my ($mboxcmd); my (@configlist,@labels, @appendsafelist,@excludesafelist, + @appendmboxsafelist,@excludemboxsafelist, @appendtextlist,@excludetextlist, @appendcontext1list,@appendcontext2list, @packagelist); @@ -780,9 +797,6 @@ my ($assign,@config); # the optional arguments to the package are the values of the hash elements my ($pkg,%packages); # Defaults -$type='UNDERLINE'; -$subtype='SAFE'; -$floattype='FLOATSAFE'; $mathmarkup=COARSE; $verbose=0; @@ -828,6 +842,8 @@ GetOptions('type|t=s' => \$type, 'append-context1cmd=s' => \@appendcontext1list, 'replace-context2cmd=s' => \$replacecontext2, 'append-context2cmd=s' => \@appendcontext2list, + 'exclude-mboxsafecmd=s' => \@excludemboxsafelist, + 'append-mboxsafecmd=s' => \@appendmboxsafelist, 'show-preamble' => \$showpreamble, 'show-safecmd' => \$showsafe, 'show-textcmd' => \$showtext, @@ -836,14 +852,15 @@ GetOptions('type|t=s' => \$type, 'packages=s' => \@packagelist, 'allow-spaces' => \$allowspaces, 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, + 'enable-citation-markup|enforce-auto-mbox' => \$enablecitmark, + 'disable-citation-markup|disable-auto-mbox' => \$disablecitmark, 'verbose|V' => \$verbose, 'ignore-warnings' => \$ignorewarnings, 'driver=s'=> \$driver, 'flatten' => \$flatten, 'version' => \$version, - 'help|h|H' => \$help); + 'help|h|H' => \$help, + 'debug!' => \$debug ); if ( $help ) { usage() ; @@ -859,6 +876,14 @@ print STDERR $versionstring if $verbose; if (defined($showall)){ $showpreamble=$showsafe=$showtext=$showconfig=1; } +# Default types +$type='UNDERLINE' unless defined($type); +$subtype='SAFE' unless defined($subtype); +# set floattype to IDENTICAL for LABEL and ONLYCHANGEDPAGE subtype, unless it has been set explicitly on the command line +$floattype=($subtype eq 'LABEL' || $subtype eq 'ONLYCHANGEDPAGE') ? 'IDENTICAL' : 'FLOATSAFE' unless defined($floattype); +if ( $subtype eq 'LABEL' ) { + print STDERR "Note that LABEL subtype is deprecated. If possible, use ZLABEL instead (requires zref package)"; +} if (defined($mathmarkup)) { $mathmarkup=~tr/a-z/A-Z/; @@ -899,6 +924,15 @@ foreach $appendsafe ( @appendsafelist ) { foreach $excludesafe ( @excludesafelist ) { init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); } +# setting up @MBOXCMDLIST and @MBOXCMDEXCL +foreach $mboxsafe ( @appendmboxsafelist ) { + init_regex_arr_ext(\@MBOXCMDLIST, $mboxsafe); +} +foreach $mboxsafe ( @excludemboxsafelist ) { + init_regex_arr_ext(\@MBOXCMDEXCL, $mboxsafe); +} + + # setting up @TEXTCMDLIST and @TEXTCMDEXCL if (defined($replacetext)) { @@ -1057,18 +1091,19 @@ push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); my $mathpunct='[+=<>\-\|]'; my $and = '&'; my $coords= '[\-.,\s\d]*'; +# quoted underscore - this needs special treatment as perl treats _ as a letter (\w) but latex does not +# such that a\_b is interpreted as a{\_}b by latex but a{\_b} by perl + my $quotedunderscore='\\\\_'; # word: sequence of letters or accents followed by letter my $word='(?:[-\w\d*]|\\\\[\"\'\`~^][A-Za-z\*])+'; my $cmdleftright='\\\\(?:left|right|[Bb]igg?[lrm]?|middle)\s*(?:[<>()\[\]|]|\\\\(?:[|{}]|\w+))'; - my $cmdoptseq='\\\\[\w\d\*]+'.$extraspace.'(?:(?:<'.$abrat0.'>|\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; my $backslashnl='\\\\\n'; my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(](?:.|\n)*?\\\\[)]'; ## the current maths command cannot cope with newline within the math expression - my $comment='%.*?\n'; - my $pat=qr/(?:\A\s*)?(?:${and}|${quotemarks}|${number}|${word}|$cmdleftright|${cmdoptseq}|${math}|${backslashnl}|${oneletcmd}|${comment}|${punct}|${mathpunct}|\{|\})\s*/ ; + my $pat=qr/(?:\A\s*)?(?:${and}|${quotemarks}|${number}|${word}|$quotedunderscore|$cmdleftright|${cmdoptseq}|${math}|${backslashnl}|${oneletcmd}|${comment}|${punct}|${mathpunct}|\{|\})\s*/ ; # now we are done setting up and can start working my ($oldfile, $newfile) = @ARGV; @@ -1127,6 +1162,10 @@ if ($flatten) { my @auxlines; + +# boolean variab +my ($ulem)=0; + if ( length $oldpreamble && length $newpreamble ) { # pre-process preamble by looking for commands used in \maketitle (title, author, date etc commands) # and marking up content with latexdiff markup @@ -1140,22 +1179,19 @@ if ( length $oldpreamble && length $newpreamble ) { add_safe_commands($newpreamble); # get a list of packages from preamble if not predefine - %packages=list_packages(@newpreamble) unless %packages; - ### if ( %packages ) {print STDERR "DEBUG Packages: ",%packages,"\n" ;} + %packages=list_packages($newpreamble) unless %packages; + if ( %packages && $debug ) { my $key ; foreach $key (keys %packages) { print STDERR "DEBUG \\usepackage[",$packages{$key},"]{",$key,"}\n" ;} } + if (defined $packages{"hyperref"} ) { # deleted lines should not generate or appear in link names: print STDERR "hyperref package detected.\n" if $verbose ; $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - - if (defined $packages{"units"} && ( $latexdiffpreamble =~ /\\RequirePackage(?:\[$brat0\])?\{ulem\}/ ) ) { - # protect inlined maths environments by surrounding with an \mbox - # this is done to get around an incompatibility between the ulem and units package - # where spaces in the argument to underlined or crossed-out \unit commands cause an error message - print STDERR "units package detected at the same time as style using ulem.\n" if $verbose ; - $MBOXINLINEMATH=1; + ### $latexdiffpreamble .= '%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF FOR HYPERREF PACKAGE' . "\n"; + ### $latexdiffpreamble .= '\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}}' . "\n"; + ### $latexdiffpreamble .= '\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}}' . "\n"; + ### $latexdiffpreamble .= '%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF FOR HYPERREF PACKAGE' . "\n"; } print STDERR "Differencing preamble.\n" if $verbose; @@ -1197,45 +1233,116 @@ elsif ( !length $oldpreamble && !length $newpreamble ) { # package documentation) # Use post-processing # and $packages{"apacite"}!~/natbibpapa/ -my ($citpat,$citpatsafe); + +$ulem = ($latexdiffpreamble =~ /\\RequirePackage(?:\[$brat0\])?\{ulem\}/ || defined $packages{"ulem"}); + + +if (defined $packages{"units"} && $ulem ) { + # protect inlined maths environments by surrounding with an \mbox + # this is done to get around an incompatibility between the ulem and units package + # where spaces in the argument to underlined or crossed-out \unit commands cause an error message + print STDERR "units package detected at the same time as style using ulem.\n" if $verbose ; + $MBOXINLINEMATH=1; +} + +if (defined $packages{"siunitx"} ) { + # protect SI command by surrounding them with an \mbox + # this is done to get around an incompatibility between the ulem and siunitx package + print STDERR "siunitx package detected.\n" if $verbose ; + my $mboxcmds='SI,ang,numlist,numrange,SIlist,SIrange'; + init_regex_arr_ext(\@SAFECMDLIST,'num,si'); + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"cleveref"} ) { + # protect selected command by surrounding them with an \mbox + # this is done to get around an incompatibility between ulem and cleveref package + print STDERR "cleveref package detected.\n" if $verbose ; + my $mboxcmds='[Cc]ref(?:range)?\*?,labelcref,(?:lc)?name[cC]refs?' ; + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"glossaries"} ) { + # protect selected command by surrounding them with an \mbox + # this is done to get around an incompatibility between ulem and glossaries package + print STDERR "glossaries package detected.\n" if $verbose ; + my $mboxcmds='[gG][lL][sS](?:|pl|disp|link|first|firstplural|desc|user[iv][iv]?[iv]?),[aA][cC][rR](?:long|longpl|full|fullpl),[aA][cC][lfp]?[lfp]?'; + init_regex_arr_ext(\@SAFECMDLIST,'[gG][lL][sS](?:(?:entry)?(?:text|plural|name|symbol)|displaynumberlist|entryfirst|entryfirstplural|entrydesc|entrydescplural|entrysymbolplural|entryuser[iv][iv]?[iv]?|entrynumberlist|entrydisplaynumberlist|entrylong|entrylongpl|entryshort|entryshortpl|entryfull|entryfullpl),[gG]lossentry(?:name|desc|symbol),[aA][cC][rR](?:short|shortpl),[aA]csp?'); + if ( $enablecitmark || ( $ulem && ! $disablecitmark )) { + init_regex_arr_ext(\@MBOXCMDLIST,$mboxcmds); + } else { + init_regex_arr_ext(\@SAFECMDLIST,$mboxcmds); + } +} + +if (defined $packages{"chemformula"} ) { + print STDERR "chemformula package detected.\n" if $verbose ; + init_regex_arr_ext(\@SAFECMDLIST,'ch'); + push(@UNSAFEMATHCMD,'ch'); + # The next command would be needed to allow highlighting the interior of \ch commands in math environments + # but the redefinitions in chemformula are too deep to make this viable + # push(@MATHTEXTCMDLIST,'ch'); +} + +if (defined $packages{"mhchem"} ) { + print STDERR "mhchem package detected.\n" if $verbose ; + init_regex_arr_ext(\@SAFECMDLIST,'ce'); + push(@UNSAFEMATHCMD,'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'); +} + + +my ( $citpat); if ( defined $packages{"apacite"} ) { - print STDERR "DEBUG apacite citation commands\n" if $debug; - $citpatsafe=qr/^(?:mask)?(?:full|short)?cite(?:A|author|year)?(?:NP)?$/; + print STDERR "apacite package detected.\n" if $verbose ; $citpat='(?:mask)?(?:full|short|no)?cite(?:A|author|year|meta)?(?:NP)?'; } else { # citation command pattern for all other citation schemes - $citpatsafe=qr/^cite.*$/; $citpat='(?:cite\w*|nocite)'; }; -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, $citpatsafe); +if ( ! $ulem ) { + # modes not using ulem: citation is safe + push (@SAFECMDLIST, $citpat); } else { ### Experimental: disable text and emph commands - push (@SAFECMDLIST, $citpatsafe) unless $disablecitmark; push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing + push(@MBOXCMDLIST,$citpat) unless $disablecitmark; if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { # remove \cite command again from list of safe commands - pop @SAFECMDLIST; + pop @MBOXCMDLIST; # deleted cite commands - $CITE2CMD=$citpat unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD=$citpat unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem } } -$CITECMD=$citpat if $enablecitmark ; # as above for explicit selection +push(@MBOXCMDLIST,$citpat) if $enablecitmark ; -print STDERR "CITECMD:|$CITECMD|\n" if $debug; if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { print STDERR "amsmath package detected.\n" if $verbose ; $MATHARRREPL='align*'; } +# add commands in MBOXCMDLIST to SAFECMDLIST +foreach $mboxcmd ( @MBOXCMDLIST ) { + init_regex_arr_ext(\@SAFECMDLIST, $mboxcmd); +} + + + print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); +preprocess($oldbody,$newbody); # run difference algorithm @@ -1257,7 +1364,7 @@ if (defined($visiblelabel)) { $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; } -$diffall .= "$newleadin$diffbo" ; +$diffall .= "$diffbo" ; $diffall .= "\\end{document}$newpost" if length $newpreamble ; if ( lc($encoding) ne "utf8" && lc($encoding) ne "ascii" ) { print STDERR "Encoding output file to $encoding\n" if $verbose; @@ -1319,22 +1426,43 @@ sub read_file_with_encoding { return $output; } -# %packages=list_packages(@preamble) +## %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 +#sub list_packages { +# my (@preamble)=@_; +# my %packages=(); +# foreach $line ( @preamble ) { +# # get rid of comments +# $line=~s/(?<!\\)%.*$// ; +# if ( $line =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[(.+?)\])?\{(.*?)\}/ ) { +## print STDERR "Found something: |$line|\n" if $debug; +# if (defined($1)) { +# $packages{$2}=$1; +# } else { +# $packages{$2}=""; +# } +# } +# } +# return (%packages); +#} + + +# %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 sub list_packages { - my (@preamble)=@_; + my ($preamble)=@_; my %packages=(); - foreach $line ( @preamble ) { - # get rid of comments - $line=~s/(?<!\\)%.*$// ; - if ( $line =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[(.+?)\])?\{(.*?)\}/ ) { -# print STDERR "Found something: |$line|\n"; - if (defined($1)) { - $packages{$2}=$1; - } else { - $packages{$2}=""; - } + + # remove comments + $preamble=~s/(?<!\\)%.*$//mg ; + + while ( $preamble =~ m/\\(?:documentclass|usepackage|RequirePackage)(?:\[($brat0)\])?\{(.*?)\}/gs ) { + if (defined($1)) { + $packages{$2}=$1; + } else { + $packages{$2}=""; } } return (%packages); @@ -1420,6 +1548,7 @@ sub flatten { # recursively replace \\input and \\include files $text=~s/(^(?:[^%\n]|\\%)*)\\input{(.*?)}|\\include{(${includeonly}(?:\.tex)?)}/{ + $begline=(defined($1)? $1 : "") ; $fname = $2 if defined($2) ; $fname = $3 if defined($3) ; # # add tex extension unless there is a three letter extension already @@ -1431,7 +1560,6 @@ sub flatten { ###$replacement=read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; $replacement=flatten(read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding), $preamble,$filename,$encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; # \include always starts a new page; use explicit \newpage command to simulate this - $begline=(defined($1)? $1 : "") ; $newpage=(defined($3)? " \\newpage " : "") ; "$begline$newpage$replacement$newpage"; }/exgm; @@ -1448,19 +1576,17 @@ sub flatten { }/exgm; # replace subfile with contents (subfile package) $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $fname = $2; + $begline=(defined($1)? $1 : "") ; + $fname = $2; # # add tex extension unless there is a three letter extension already $fname .= ".tex" unless $fname =~ m|\.\w{3}|; - print STDERR "DEBUG Beg of line match |$1|\n" if defined($1) && $debug ; print STDERR "Include file as subfile $fname\n" if $verbose; - print STDERR "DEBUG looking for file ",File::Spec->catfile($dirname,$fname), "\n" if $debug; # content of file becomes replacement value (use recursion) # now strip away everything outside and including \begin{document} and \end{document} pair# # # note: no checking for comments is made $subfile=read_file_with_encoding(File::Spec->catfile($dirname,$fname), $encoding) or die "Couldn't find file ",File::Spec->catfile($dirname,$fname),": $!"; ($subpreamble,$subbody,$subpost)=splitdoc($subfile,'\\\\begin\{document\}','\\\\end\{document\}'); $replacement=flatten($subbody, $preamble,$filename,$encoding); - $begline=(defined($1)? $1 : "") ; "$begline$replacement"; }/exgm; @@ -1585,10 +1711,10 @@ sub bodydiff { print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); + open(TOKENOLD,">","latexdiff.debug.tokenold2"); print TOKENOLD join("***\n",@oldwords); close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); + open(TOKENNEW,">","latexdiff.debug.tokennew2"); print TOKENNEW join("***\n",@newwords); close(TOKENNEW); } @@ -1606,10 +1732,15 @@ sub bodydiff { # Each element of words is either # a word (including trailing spaces and punctuation) # a latex command +# if there is white space in the beginning return that as first token sub splitlatex { - my ($string) = @_ ; + my ($inputstring) = @_ ; + my $string=$inputstring ; # if input is empty, return empty list length($string)>0 or return (); + $string=~s/^(\s*)//s; + my $leadin=$1; + length($string)>0 or return ($leadin); my @retval=($string =~ m/$pat/osg); @@ -1647,6 +1778,7 @@ sub splitlatex { } } + unshift(@retval,$leadin) if (length($leadin)>0); return @retval; } @@ -1696,7 +1828,7 @@ sub pass1 { # print STDERR "Unchanged block $cnt, $last1,$last2 \n"; if ($cnt < $MINWORDSBLOCK && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o + grep { /^$wpat/ || ( /^\\((?:[`'^"~=.]|[\w\d@*]+))((?:\[$brat0\]|\{$pat6\})*)/o && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) && scalar(@dummy=split(" ",$2))<3 ) } @$block) ) { @@ -1828,7 +1960,7 @@ sub extracttextblocks { for ($i=0;$i< scalar @$block;$i++) { ($token,$index)=@{ $block->[$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}\{$pat6\})*)/o && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { # we have text or a command which can be treated as text @@ -1972,7 +2104,7 @@ sub pass2 { } # marktags($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,\@block) -# returns ($openmark,$open,$block,$close,$closemark) if @block only contains no commands (except white-listed ones), +# returns ($openmark,$open,$block,$close,$closemark) if @block contains no commands (except white-listed ones), # braces, ampersands, or comments # mark comments with $comment # exclude all other exceptions from scope of open, close like this @@ -1992,8 +2124,11 @@ sub marktags { # split this block to flatten out sequences joined in pass1 @$block=splitlatex(join "",@$block); + ### print STDERR "DEBUG: marktags $openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment\n" if $debug; + ### print STDERR "DEBUG: marktags blocksplit ",join("|",@$block),"\n" if $debug; foreach (@$block) { $word=$_; + ### print STDERR "DEBUG MARKTAGS: |$word|\n" if $debug; if ( $word =~ s/^%/%$comment/ ) { # a comment if ($cmd==1) { @@ -2003,16 +2138,25 @@ sub marktags { push (@$retval,$word); next; } + if ( $word =~ m/^\s*$/ ) { + ### print STDERR "DEBUG MARKTAGS: whitespace detected |$word| cmdcom |$cmdcomment| |$opencmd|\n" if $debug; + # a sequence of white-space characters - this should only ever happen for the first element of block. + # in deleted block, omit, otherwise just copy it in + if ( ! $cmdcomment) { # ignore in deleted blocks + push(@$retval,$word); + } + next; + } if (! $noncomment) { push (@$retval,$openmark); $noncomment=1; } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) patterns + # negative lookahead pattern (?!) in second clause is put in to avoid matching \( .. \) patterns # also note that second pattern will match \\ - # Note: the second pattern should really be $word =~ /^\\(?!\()(\\|[\w*@]+)/, ie * replaced by + - # and then all commands \" \' etc declared safe. But as I don't have a complete list of one letter - # commands, and nobody has complained so far, I will eave this as is - if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\(?!\()(\\|[\w*@]*)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { + ### print STDERR "DEBUG marktags: Considering word |$word|\n"; + if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { + ###print STDERR "DEBUG MARKTAGS is a non-safe command ($1)\n" if $debug; + ### if ( $word =~ /^[&{}\[\]]/ || ( $word =~ /^\\([\w*@\\% ]+)/ && !iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL)) ) { # word is a command or other significant token (not in SAFECMDLIST) ## same conditions as in subroutine extractcommand: # check if token is an alphanumeric command sequence with at least one non-optional argument @@ -2057,6 +2201,7 @@ 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 { @@ -2074,10 +2219,21 @@ sub marktags { $cmd=1; } } else { - # just an ordinary word or word in SAFECMD + ###print STDERR "DEBUG MARKTAGS is an ordinary word or SAFECMD command \n" if $debug; + # just an ordinary word or command in SAFECMD push (@$retval,$open) if $cmd==-1 ; push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); + ###TODO: check here if it is a command in MBOXCMD list, and surround it with \mbox{...} + ### $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)/ && iscmd($1,\@MBOXCMDLIST,\@MBOXCMDEXCL)) + ### but actually this check has been carried out already so can simply check if word begins with backslash + if ( $word =~ /^\\(?!\()(\\|[`'^"~=.]|[\w*@]+)(.*?)(\s*)$/s && iscmd($1,\@MBOXCMDLIST,\@MBOXCMDEXCL)) { + # $word is a safe command in MBOXCMDLIST + ###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 + push (@$retval,$word); + } $cmd=0; } } @@ -2091,7 +2247,7 @@ sub marktags { # preprocess($string, ..) # carry out the following pre-processing steps for all arguments: # 1. Remove leading white-space -# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE +# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE and \& to \AMPERSAND # #. Change {,} in comments to \CLEFTBRACE, \CRIGHTBRACE # 2. mark all first empty line (in block of several) with \PAR tokens # 3. Convert all '\%' into '\PERCENTAGE ' and all '\$' into \DOLLAR to make parsing regular expressions easier @@ -2112,13 +2268,11 @@ sub marktags { # names or labels but it does not matter because they are converted back in the postprocessing step # Returns: leading white space removed in step 1 sub preprocess { - my @leadin=() ; for (@_) { - s/^(\s*)//s; - push(@leadin,$1); # Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE s/(?<!\\)\\{/\\QLEFTBRACE /sg; s/(?<!\\)\\}/\\QRIGHTBRACE /sg; + s/(?<!\\)\\&/\\AMPERSAND /sg; # replace {,} in comments with \\CLEFTBRACE,\\CRIGHTBRACE 1 while s/((?<!\\)%.*)\{(.*)$/$1\\CLEFTBRACE $2/mg ; 1 while s/((?<!\\)%.*)\}(.*)$/$1\\CRIGHTBRACE $2/mg ; @@ -2151,7 +2305,6 @@ sub preprocess { # add final token " STOP" $_ .= " STOP" } - return(@leadin); } #hashstring=tohash(\%hash,$string) @@ -2235,7 +2388,7 @@ sub fromhash { # 10. package specific processing: endfloat: make sure \begin{figure} and \end{figure} are always # on a line by themselves, similarly for table environment # 4, undo renaming of the \begin, \end,{,} in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} +# Change \QLEFTBRACE, \QRIGHTBRACE,\AMPERSAND to \{,\},\& # # Note have to manually synchronize substitution commands below and # DIF.. command names in the header @@ -2254,10 +2407,6 @@ sub postprocess { # Replace \RIGHTBRACE by } s/\\RIGHTBRACE/}/g; - # change citation commands within comments to protect from processing - if ($CITECMD){ - 1 while s/(%.*)\\($CITECMD)/$1\\CITEDIF$2/m ; - } # Check all deleted blocks: where a deleted block contains a matching \begin and # \end environment (these will be disabled by a %DIFDELCMD statements), enable # these commands again (such that for example displayed math in a deleted equation @@ -2350,18 +2499,6 @@ sub postprocess { substr($delblock,$begin2,$len2)=$mathblock; pos($delblock) = $begin2 + length($mathblock); } - if ($CITE2CMD) { - $delblock=~s/($DELCMDOPEN\s*\\($CITE2CMD)(.*)$DELCMDCLOSE)/ - # Replacement code - {my ($aux,$all); - $aux=$all=$1; - $aux=~s#\n?($DELCMDOPEN|$DELCMDCLOSE)##g; - $all."$aux$AUXCMD\n";}/sge; - } - # or protect \cite commands with \mbox - if ($CITECMD) { - $delblock=~s/(\\($CITECMD)${extraspace}(?:<$abrat0>${extraspace})?(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } # if MBOXINLINEMATH is set, protect inlined math environments with an extra mbox if ( $MBOXINLINEMATH ) { # note additional \newline after command is omitted from output if right at the end of deleted block (otherwise a spurious empty line is generated) @@ -2387,14 +2524,6 @@ sub postprocess { substr($addblock,$begin2,$len2)=$mathblock; pos($addblock) = $begin2 + length($mathblock); } - if ($CITECMD) { - my $addblockbefore=$addblock; - #(?:mask)?(?:full|short|no)?cite(?:A|author|year|meta)(?:NP)?$/ - ###my $CITECMD; $CITECMD="cite(?:A)$"; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:<$abrat0>${extraspace})?(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - print STDERR "DEBUG: CITECMD $CITECMD\nDEBUG: addblock before:|$addblockbefore|\n" if $debug; - print STDERR "DEBUG: addblock after: |$addblock|\n" if $debug; - } # if MBOXINLINEMATH is set, protect inlined math environments with an extra mbox if ( $MBOXINLINEMATH ) { ##$addblock=~s/($math)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; @@ -2498,10 +2627,6 @@ sub postprocess { } # undo renaming of the \begin and \end,{,} and dollars in comments 1 while s/(%.*)DOLLARDIF/$1\$/mg ; - # undo renaming of the \cite.. commands in comments - if ( $CITECMD ) { - 1 while s/(%.*)\\CITEDIF($CITECMD)/$1\\$2/mg ; - } # Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] s/\\end{SQUAREBRACKET}/\\\]/sg; s/\\begin{SQUAREBRACKET}/\\\[/sg; @@ -2520,6 +2645,7 @@ sub postprocess { # Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} s/\\QLEFTBRACE /\\{/sg; s/\\QRIGHTBRACE /\\}/sg; + s/\\AMPERSAND /\\&/sg; return; } @@ -2773,14 +2899,15 @@ format as new.tex but has all changes relative to old.tex marked up or commented --type=markupstyle -t markupstyle Add code to preamble for selected markup style Available styles: UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE - CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR + CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR BOLD [ Default: UNDERLINE ] --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 LABEL + Available styles: SAFE MARGINAL DVIPSCOL COLOR ZLABEL ONLYCHANGEDPAGE (LABEL)* [ Default: SAFE ] + * LABEL subtype is deprecated --floattype=markstyle -f markstyle Add code to preamble for selected style which @@ -2855,6 +2982,16 @@ format as new.tex but has all changes relative to old.tex marked up or commented context2 commands are completely disabled in deleted sections, including their arguments. +--exclude-mboxsafecmd=exclude-file +--exclude-mboxsafecmd="cmd1,cmd2,..." +--append-mboxsafecmd=append-file +--append-mboxsafecmd="cmd1,cmd2,..." + Define safe commands, which additionally need to be protected by encapsulating + in an \\mbox{..}. This is sometimes needed to get around incompatibilities + between external packages and the ulem package, which is used for highlighting + in the default style UNDERLINE as well as CULINECHBAR CFONTSTRIKE + + --config var1=val1,var2=val2,... -c var1=val1,.. Set configuration variables. @@ -2878,7 +3015,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 + endfloat hyperref amsmath apacite siunitx cleveref glossaries mhchem chemformula [ Default: scan the preamble for \\usepackage commands to determine loaded packages.] @@ -2919,10 +3056,15 @@ Other configuration options: This mode is most suitable, if only minor changes to equations are expected, e.g. correction of typos. ---disable-citation-markup Suppress citation markup in styles using ulem (UNDERLINE, - FONTSTRIKE, CULINECHBAR) ---enable-citation-markup Protect citation commands in changed sections with \\mbox command - [i.e. use default behaviour for ulem package for other packages] +--disable-citation-markup +--disable-auto-mbox Suppress citation markup and markup of other vulnerable commands in styles + using ulem (UNDERLINE,FONTSTRIKE, CULINECHBAR) + (the two options are identical and are simply aliases) + +--enable-citation-markup +--enforce-auto-mbox Protect citation commands and other vulnerable commands in changed sections + with \\mbox command, i.e. use default behaviour for ulem package for other packages + (the two options are identical and are simply aliases) Miscelleneous options @@ -3111,7 +3253,7 @@ C<\DIFadd> and C<\DIFdel> commands. Available styles: C<UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR> +CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR BOLD> [ Default: C<UNDERLINE> ] @@ -3121,9 +3263,10 @@ 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<SAFE MARGINAL COLOR DVIPSCOL LABEL> +Available styles: C<SAFE MARGINAL COLOR DVIPSCOL ZLABEL ONLYCHANGEDPAGE (LABEL)*> [ Default: C<SAFE> ] +* Subtype C<LABEL> is deprecated =item B<--floattype=markstyle> or B<-f markstyle> @@ -3177,7 +3320,8 @@ The following packages trigger special behaviour: =item C<amsmath> -Configuration variable amsmath is set to C<align*> (Default: C<eqnarray*>) +Configuration variable MATHARRREPL is set to C<align*> (Default: C<eqnarray*>). (Note that many of the +amsmath array environments are already recognised by default as such) =item C<endfloat> @@ -3194,10 +3338,31 @@ errors). Redefine the commands recognised as citation commands. +=item C<siunitx> + +Treat C<\SI> as equivalent to citation commands (i.e. protect with C<\mbox> if markup style uses ulem package. + +=item C<cleveref> + +Treat C<\cref,\Cref>, etc as equivalent to citation commands (i.e. protect with C<\mbox> if markup style uses ulem package. + +=item C<glossaries> + +Define most of the glossaries commands as safe, protecting them with \mbox'es where needed + +=item C<mhchem> + +Treat C<\ce> as a safe command, i.e. it will be highlighted (note that C<\cee> will not be highlighted in equations as this leads to processing errors) + +=item C<chemformula> + +Treat C<\ch> as a safe command outside equations, i.e. it will be highlighted (note that C<\ch> will not be highlighted in equations as this leads to processing errors) + + =back -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] +[ Default: scan the preamble for C<\usepackage> commands to determine + loaded packages. ] @@ -3263,11 +3428,24 @@ argument is shown as deleted text. =item B<--append-context2cmd=append-file> or =item B<--append-context2cmd="cmd1,cmd2,..."> + As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments. +=item B<--exclude-mboxsafecmd=exclude-file> or B<--exclude-mboxsafecmd="cmd1,cmd2,..."> + +=item B<--append-mboxsafecmd=append-file> or B<--append-mboxsafecmd="cmd1,cmd2,..."> + +Define safe commands, which additionally need to be protected by encapsulating +in an \\mbox{..}. This is sometimes needed to get around incompatibilities +between external packages and the ulem package, which is used for highlighting +in the default style UNDERLINE as well as CULINECHBAR CFONTSTRIKE + + + + =item B<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> @@ -3352,14 +3530,17 @@ C<fine> or C<3>: Detect small change in equations and mark up at fine granularit This mode is most suitable, if only minor changes to equations are expected, e.g. correction of typos. -=item B<--disable-citation-markup> +=item B<--disable-citation-markup> or B<--disable-auto-mbox> -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) +Suppress citation markup and markup of other vulnerable commands in styles +using ulem (UNDERLINE,FONTSTRIKE, CULINECHBAR) +(the two options are identical and are simply aliases) -=item B<--enable-citation-markup> +=item B<--enable-citation-markup> or B<--enforce-auto-mbox> -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] +Protect citation commands and other vulnerable commands in changed sections +with C<\mbox> command, i.e. use default behaviour for ulem package for other packages +(the two options are identical and are simply aliases) =back @@ -3403,7 +3584,7 @@ Suppress inclusion of old and new file names as comment in output file =item B<--visble-label> -Include old and new filenames (or labels set with --label option) as +Include old and new filenames (or labels set with C<--label> option) as visible output. =item B<--flatten> @@ -3485,6 +3666,10 @@ No mark up of text, but mark margins with changebars (Requires changebar package No visible markup (but generic markup commands will still be inserted. +=item C<BOLD> + +Added text is set in bold face, discarded is not shown. + =back =head2 Subtypes @@ -3517,6 +3702,20 @@ that C<DVIPSCOL> only works with the dvips converter, e.g. not pdflatex. (it is recommeneded to use instead the main types to effect colored markup, although in some cases coloring with dvipscol can be more complete). + +=item C<ZLABEL> + +can be used to highlight only changed pages, but requires post-processing. It is recommend to not call this option manually but use C<latexdiff-vc> with C<--only-changes> option. Alternatively, use the script given within preamble of diff files made using this style. + +=item C<ONLYCHANGEDPAGE> + +also highlights changed pages, without the need for post-processing, but might not work reliably if +there is floating material (figures, tables). + +=item C<LABEL> + +is similar to C<ZLABEL>, but does not need the zref package and works less reliably (deprecated). + =back =head2 Float Types @@ -3603,26 +3802,34 @@ C<|subsubsection|paragraph|subparagraph)> ] =back -=head1 COMMON PROBLEMS +=head1 COMMON PROBLEMS AND FAQ =over 10 =item Citations result in overfull boxes There is an incompatibility between the C<ulem> package, which C<latexdiff> uses for underlining and striking out in the UNDERLINE style, -the default style. In order to be able to mark up citations properly, they are placed with an C<\mbox> command in post-processing. As mboxes -cannot be broken across lines, this procedure frequently results in overfull boxes, possibly obscuring the content as it extends beyond the right margin. If this is a problem, you have two possibilities: +the default style, and the way citations are generated. In order to be able to mark up citations properly, they are enclosed with an C<\mbox> +command. As mboxes cannot be broken across lines, this procedure frequently results in overfull boxes, possibly obscuring the content as it extends beyond the right margin. The same occurs for some other packages (e.g., siunitx). If this is a problem, you have two possibilities. -1. Use C<COLOR> or C<DVIPSCOL> subtype markup (option C<-s COLOR>): If this markup is chosen, then changed citations are no longer marked up -with the wavy line (additions) or struck out (deletions), but are still highlighted in the appropriate color. +1. Use C<CFONT> type markup (option C<-t CFONT>): If this markup is chosen, then changed citations are no longer marked up +with the wavy line (additions) or struck out (deletions), but are still highlighted in the appropriate color, and deleted text is shown with a different font. Other styles not using the C<ulem> package will also work. 2. Choose option C<--disable-citation-markup> which turns off the marking up of citations: deleted citations are no longer shown, and -added ctations are shown without markup. (This was the default behaviour of latexdiff at versions 0.6 and older) +added citations are shown without markup. (This was the default behaviour of latexdiff at versions 0.6 and older) + +For custom packages you can define the commands which need to be protected by C<\mbox> with C<--append-mboxsafecmd> and C<--excludemboxsafecmd> options +(submit your lists of command as feature request at github page to set the default behaviour of future versions, see section 6) =item Changes in complicated mathematical equations result in latex processing errors Try options C<--math-markup=whole>. If even that fails, you can turn off mark up for equations with C<--math-markup=off>. +=item How can I just show the pages + +Use options -C<-s ZLABEL> (some postprocessing required) or C<-s ONLYCHANGEDPAGE>. C<latexdiff-vc --ps|--pdf> with C<--only-changes> option takes care of +the post-processing for you (requires zref packages). + =back =head1 BUGS @@ -3632,7 +3839,7 @@ the rules that number and type of white space does not matter, as different numbers of inter-argument spaces are treated as significant. Please submit bug reports using the issue tracker of the github repository page I<https://github.com/ftilmann/latexdiff.git>, -or send them to I<tilmann@gfz-potsdam.de>. Include the serial number of I<latexdiff> +or send them to I<tilmann -- AT -- gfz-potsdam.de>. Include the serial number of I<latexdiff> (from comments at the top of the source or use B<--version>). If you come across latex files that are error-free and conform to the specifications set out above, and whose differencing still does not result in error-free @@ -3659,8 +3866,8 @@ I<latexdiff-fast> requires the I<diff> command to be present. =head1 AUTHOR -Version 1.0.4 -Copyright (C) 2004-2012 Frederik Tilmann +Version 1.1.0 +Copyright (C) 2004-2015 Frederik Tilmann This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 @@ -3884,7 +4091,10 @@ min Pr sec sup -[Hclbdruvt] +[Hclbkdruvt] +[`'^"~=.] +_ +AMPERSAND (SUPER|SUB)SCRIPTNB (SUPER|SUB)SCRIPT PERCENTAGE @@ -3925,12 +4135,12 @@ sqrt %%END TEXT COMMANDS %%BEGIN CONTEXT1 COMMANDS -% Regex matching commands with a text argument (leave out the \), which will fail out of context, but whose argument should be printed as plain text +% Regex matching commands with a text argument (leave out the \), which will fail out of context. These commands behave like text commands, except when they occur in a deleted section, where they are disabled, but their argument is shown as deleted text. caption %%END CONTEXT1 COMMANDS %%BEGIN CONTEXT2 COMMANDS -% Regex matching commands with a text argument (leave out the \), which will fail out of context, but whose argument should be printed as plain text +% Regex matching commands with a text argument (leave out the \), which will fail out of context. As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments. title author date @@ -4005,6 +4215,10 @@ institute \providecommand{\DIFdel}[1]{} %DIF END INVISIBLE PREAMBLE +%DIF BOLD PREAMBLE +\providecommand{\DIFadd}[1]{{\bf #1}} +\providecommand{\DIFdel}[1]{} +%DIF END BOLD PREAMBLE %% SUBTYPES (Markers for beginning and end of changed blocks) @@ -4042,24 +4256,94 @@ institute %DIF LABEL PREAMBLE % To show only pages with changes (pdf) (external program pdftk needs to be installed) -% (only works for simple documents with non-repeated page numbers) +% (only works for simple documents with non-repeated page numbers, otherwise use ZLABEL) % pdflatex diff.tex % pdflatex diff.tex -% pdftk diff.pdf cat `perl -lne 'if (m/\\newlabel{DIFchg[be]\d*}{{.*}{(.*)}}/) { print $1 }' diff.aux | uniq | tr -s \\n ' '` output diff-changedpages.pdf +%pdftk diff.pdf cat \ +%`perl -lne '\ +% if (m/\\newlabel{DIFchg[b](\d*)}{{.*}{(.*)}}/) { $start{$1}=$2; print $2}\ +% if (m/\\newlabel{DIFchg[e](\d*)}{{.*}{(.*)}}/) { \ +% if (defined($start{$1})) { \ +% for ($j=$start{$1}; $j<=$2; $j++) {print "$j";}\ +% } else { \ +% print "$2"\ +% }\ +% }' diff.aux \ +% | uniq \ +% | tr \\n ' '` \ +% output diff-changedpages.pdf +% To show only pages with changes (dvips/dvipdf) +% dvips -pp `\ +% [ put here the perl script from above] +% | uniq | tr -s \\n ','` +\typeout{Check comments in preamble of output for instructions how to show only pages where changes have been made} +\newcount\DIFcounterb +\global\DIFcounterb 0\relax +\newcount\DIFcountere +\global\DIFcountere 0\relax +\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} +\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} +%DIF END LABEL PREAMBLE + +%DIF ZLABEL PREAMBLE +% To show only pages with changes (pdf) (external program pdftk needs to be installed) +% (uses zref for reference to absolute page numbers) +% pdflatex diff.tex +% pdflatex diff.tex +%pdftk diff.pdf cat \ +%`perl -lne 'if (m/\\zref\@newlabel{DIFchgb(\d*)}{.*\\abspage{(\d*)}}/ ) { $start{$1}=$2; print $2 } \ +% if (m/\\zref\@newlabel{DIFchge(\d*)}{.*\\abspage{(\d*)}}/) { \ +% if (defined($start{$1})) { \ +% for ($j=$start{$1}; $j<=$2; $j++) {print "$j";}\ +% } else { \ +% print "$2"\ +% }\ +% }' diff.aux \ +% | uniq \ +% | tr \\n ' '` \ +% output diff-changedpages.pdf % To show only pages with changes (dvips/dvipdf) % latex diff.tex % latex diff.tex % dvips -pp `perl -lne 'if (m/\\newlabel{DIFchg[be]\d*}{{.*}{(.*)}}/) { print $1 }' diff.aux | uniq | tr -s \\n ','` diff.dvi \typeout{Check comments in preamble of output for instructions how to show only pages where changes have been made} +\usepackage[user,abspage]{zref} \newcount\DIFcounterb \global\DIFcounterb 0\relax \newcount\DIFcountere \global\DIFcountere 0\relax -\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} %DIF PREAMBLE -\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\label{DIFchgb\the\DIFcounterb}} %DIF PREAMBLE -\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\label{DIFchge\the\DIFcountere}} %DIF PREAMBLE -%DIF END LABEL PREAMBLE +\providecommand{\DIFaddbegin}{\global\advance\DIFcounterb 1\relax\zlabel{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFaddend}{\global\advance\DIFcountere 1\relax\zlabel{DIFchge\the\DIFcountere}} +\providecommand{\DIFdelbegin}{\global\advance\DIFcounterb 1\relax\zlabel{DIFchgb\the\DIFcounterb}} +\providecommand{\DIFdelend}{\global\advance\DIFcountere 1\relax\zlabel{DIFchge\the\DIFcountere}} +%DIF END ZLABEL PREAMBLE + +%DIF ONLYCHANGEDPAGE PREAMBLE +\RequirePackage{atbegshi} +\RequirePackage{etoolbox} +\RequirePackage{zref} +% redefine label command to write immediately to aux file - page references will be lost +\makeatletter \let\oldlabel\label% Store \label +\renewcommand{\label}[1]{% Update \label to write to the .aux immediately +\zref@wrapper@immediate{\oldlabel{#1}}} +\makeatother +\newbool{DIFkeeppage} +\newbool{DIFchange} +\boolfalse{DIFkeeppage} +\boolfalse{DIFchange} +\AtBeginShipout{% + \ifbool{DIFkeeppage} + {\global\boolfalse{DIFkeeppage}} % True DIFkeeppage + {\ifbool{DIFchange}{\global\boolfalse{DIFkeeppage}}{\global\boolfalse{DIFkeeppage}\AtBeginShipoutDiscard}} % False DIFkeeppage +} +\providecommand{\DIFaddbegin}{\global\booltrue{DIFkeeppage}\global\booltrue{DIFchange}} +\providecommand{\DIFaddend}{\global\booltrue{DIFkeeppage}\global\boolfalse{DIFchange}} +\providecommand{\DIFdelbegin}{\global\booltrue{DIFkeeppage}\global\booltrue{DIFchange}} +\providecommand{\DIFdelend}{\global\booltrue{DIFkeeppage}\global\boolfalse{DIFchange}} +%DIF END ONLYCHANGEDPAGE PREAMBLE + %% FLOAT TYPES %DIF FLOATSAFE PREAMBLE |