diff --git a/Makefile b/Makefile index eaf5505..8a236dd 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Makefile for preparing files for distribution -VERSION=1.1.1 +VERSION=1.2.0 .PHONY: distribution release test mkdirs clean cleanall cleantest webmanual diff --git a/latexdiff b/latexdiff index 45720e2..f234566 100755 --- a/latexdiff +++ b/latexdiff @@ -30,7 +30,7 @@ ### - --flatten option only expands first including command per line if there is more than one ### - move --show-options so that they are also capable of showing preamble (and commands) after all modificationsbased on source file packages # -# Version 1.2.0alpha: +# Version 1.2.0: # - highlight new and deleted figures # - bug fix in title mark-up. Previously deleted commands in title (such as \title, \author or \date) were marked up erroneously # - (minor) bug fixes in new 1.1.1 features: disabled label was commented out twice, additional spaces were introduced before list environment begin and end commands @@ -147,7 +147,7 @@ my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); my ($versionstring)=< requires the I command to be present. =head1 AUTHOR -Version 1.1.1 +Version 1.2.0 Copyright (C) 2004-2015 Frederik Tilmann This program is free software; you can redistribute it and/or modify diff --git a/latexdiff-1.0.1/COPYING b/latexdiff-1.0.1/COPYING deleted file mode 100644 index d6fa915..0000000 --- a/latexdiff-1.0.1/COPYING +++ /dev/null @@ -1,623 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - diff --git a/latexdiff-1.0.1/README b/latexdiff-1.0.1/README deleted file mode 100644 index 2b218ba..0000000 --- a/latexdiff-1.0.1/README +++ /dev/null @@ -1,105 +0,0 @@ - -INTRODUCTION - -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -A rudimentary revision facilility is provided by another Perl script, -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) - -Project webpage: http://latexdiff.berlios.de/ -CTAN page: http://www.ctan.org/tex-archive/support/latexdiff - - -REQUIREMENTS - -Perl 5.8 or higher must be installed. - The latexdiff script makes use of the Perl package Algorithm::Diff (available -from www.cpan.org, current version 1.19). You can either install this package, or -use the standalone version of latexdiff, latexdiff-so, which has version 1.15 of -this package inlined and does not require external installation of -the package. Because latexdiff uses internal functions of Algorithm:Diff whose -calling format or availability can change without notice, the preferred method is -now to use the standalone version. - -As an alternative, latexdiff-fast has a modified version of Algorithm::Diff inlined, -which internally uses the UNIX diff command. This version is much faster but is dependent -on an external "diff" command. Subtle differences in the algorithm of Algorithm::Diff and -UNIX-diff mean that the resulting set of differences will generally not be the same as -for the standard latexdiff. In most practical cases, these differences are minor, though. - -INSTALLATION UNIX/LINUX - -The basic installation procedure is almost trivial: - -1. Copy latexdiff, latexrevise and latexdiff-vc into a directory which - is in the search path and make them executable. If the Algorithm::Diff - package is not installed, use latexdiff-so instead of latexdiff. - -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. - -The attached Makefile contains example commands to carry out above -steps as root for a typical UNIX installation. Type - - make install (for the stand alone version) -or - make install-ext (for the version using the external Algorithm::Diff) -or - make install-fast (for the version using the UNIX 'diff' function for fast differencing) - -to get it rolling. You can type - - make test -or - make test-ext -or - make test-fast - -to test the respective versions on a brief example before installation - - -DOCUMENTATION: - -Usage instructions are in the manual latexdiff-man.pdf as well as the -man pages. - -CHANGELOGS: - -Check out the comment lines at the beginning of the perl scripts (latexdiff, latexdiff-vc, latexrevise) - -CONTRIBUTIONS - -The directory contrib contains code written by others relating to latexdiff. -Currently this directory contains: - -latexdiff-wrap (Author: V. Kuhlmann) An alternative wrapper script which can be used - instead of latexdiff-vc. Its main use is as a template for customised wrapper scripts. - -latexdiff.spec (Author: T. Doerges) spec file for RPM generation - -The following contributions 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) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License Version 3 as published by -the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details (file LICENSE in the -distribution). - diff --git a/latexdiff-1.0.1/doc/example-diff.tex b/latexdiff-1.0.1/doc/example-diff.tex deleted file mode 100644 index 4193ecc..0000000 --- a/latexdiff-1.0.1/doc/example-diff.tex +++ /dev/null @@ -1,89 +0,0 @@ -\documentclass[12pt,a4paper]{article} -%DIF LATEXDIFF DIFFERENCE FILE -%DIF DEL example-draft.tex Tue Nov 13 00:43:28 2012 -%DIF ADD example-rev.tex Tue Nov 13 00:43:28 2012 - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -\title{latexdiff Example - \DIFdelbegin \DIFdel{Draft }\DIFdelend \DIFaddbegin \DIFadd{Revised }\DIFaddend version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of \DIFaddbegin \DIFadd{the }\DIFaddend latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{\DIFdelbegin \DIFdel{Another }\DIFdelend \DIFaddbegin \DIFadd{Yet another }\DIFaddend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft document. }\DIFdelend More things could be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised document. }\DIFaddend More things could be -said were it not for the constraints of time and space. - -And here is a \DIFdelbegin \DIFdel{tipo}\DIFdelend \DIFaddbegin \DIFadd{typo}\DIFaddend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFdelbegin \DIFdel{Grey }\DIFdelend \DIFaddbegin \DIFadd{White }\DIFaddend \\ -Saruman & \DIFdelbegin \DIFdel{White -}\DIFdelend \DIFaddbegin \DIFadd{Evil -}\DIFaddend \end{tabular} - -And \DIFdelbegin \DIFdel{sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend \DIFaddbegin \DIFadd{now for something completely different, with not a paragraph in sight}\DIFaddend . -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.1/doc/latexdiff-man.tex b/latexdiff-1.0.1/doc/latexdiff-man.tex deleted file mode 100644 index 2adffcc..0000000 --- a/latexdiff-1.0.1/doc/latexdiff-man.tex +++ /dev/null @@ -1,355 +0,0 @@ -\documentclass[a4]{article} -\usepackage{graphicx} -%\def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -%\def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -\setlength{\parindent}{0pt} -%\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}} -\date{\today} - -\begin{document} -\maketitle - -\section*{Preamble} - -{\em latexdiff} is a Perl script, which compares two -latex files and marks up significant differences between them. Various options are available for visual markup using standard -latex packages such as {\em color.sty}. Changes not directly affecting visible -text, for example in formatting commands, are still marked in the -latex source. - -A rudimentary revision facilility is provided by another Perl script, -{\em 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. - -There is no explicit support for annotations as these are trivial to implement. -For example, I include the following command definition in the preamble -\begin{verbatim} -\newcommand{\remark}[1]{{ \bf [ \footnotesize #1 ]}} -\end{verbatim} -and mark up annotations as follows -\begin{verbatim} -... The roadrunner is the fastest running bird \remark{Check this -again with a zoologist!}. The most famous roadrunner ... -\end{verbatim} -Alternatively, instead of a command like \verb#\remark# in the example just given, an -equivalent annotation environment could be defined. -{\em latexrevise} can remove such comments or -environments from the text body. - -%It is planned that the revision capabilities of this system will be -%further expanded, dependent on the amount of feedback received. - -On the following pages you find the {\em man} pages for {\em - latexdiff} and {\em latexrevise} and a simple example. - -\include{latexdiff} -\setcounter{section}{0} - -\include{latexrevise} -\setcounter{section}{0} - -\include{latexdiff-vc} -\setcounter{section}{0} - -\section*{A simple example} - -We start with a draft text, \verb|example-draft.tex|, listed here in -full but also included in the distribution (except that the ``verbatim'' environment had -to be renamed to ``Verbatim'' for the listing). - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. Of course, instead of \verb|xpdf| you can use -\verb|okular, evince, acroread| or any other pdf or postscript viewer. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things -could be said were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} -\end{verbatim} -} - -We can now edit -this text as we would do with any other latex file to create -a new revision of the text, \verb|example-rev.tex|. We should run -\begin{verbatim} -latex example-rev.tex -\end{verbatim} -and look at the resulting \verb|.dvi| file to make sure that all -changes are valid. An example revision is listed here: - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. -More things could be said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} -\end{verbatim} -} - -To compare both revisions, type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -This results in the following difference file (a few newlines have been -added in this listing for legibility reasosn): -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -%DIF 9c9 -%DIF < \title{latexdiff Example - Draft version} -%DIF ------- -\title{latexdiff Example - Revised version} %DIF > -%DIF ------- -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\color{blue}\uline{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{\DIFaddbegin \DIFadd{Yet another }\DIFaddend \DIFdelbegin -\DIFdel{Another }\DIFdelend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft - document. }\DIFdelend More things could - be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised - document. }\DIFaddend More things could be said -were it not for the constraints of time and space. - -And here is a \DIFaddbegin \DIFadd{typo}\DIFaddend \DIFdelbegin -\DIFdel{tipo}\DIFdelend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFaddbegin \DIFadd{White }\DIFaddend \DIFdelbegin -\DIFdel{Grey }\DIFdelend \\ -Saruman & \DIFaddbegin \DIFadd{Evil -}\DIFaddend \DIFdelbegin \DIFdel{White -}\DIFdelend \end{tabular} - -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -No change, -no markup! -\end{document} -\end{verbatim} -} -Type -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -to make the markup visible. This is what it looks like: - -\vspace{1cm} -\framebox[\textwidth]{\includegraphics[width=\textwidth]{example-diff}} -\vspace{1cm} - -If you approve of all the changes in the revision, just continue with -\verb|example-rev.tex| for the next revision. If you like to adopt -most but not all changes you can use \verb|latexrevise| in the -following manner. Simply remove the \verb|\DIFdelbegin| and -\verb|\DIFdelend| tags around the text you would like to keep and -simply remove the text between \verb|\DIFaddbegin| and -\verb|\DIFaddend| tags, if you do not wish to keep them. Say you are happy with all proposed changes for the -example above except in -the last paragraph where you prefer the original draft. You have -to change - -{\scriptsize -\begin{verbatim} -... -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -... -\end{verbatim} -} -into -{\scriptsize -\begin{verbatim} -... -And \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}. -... -\end{verbatim} -} -and run -\begin{verbatim} -latexrevise -a example-rev.tex > example-final.tex -\end{verbatim} -\verb|example-final.tex| is then almost identical to -\verb|example-rev.tex| except for the last paragraph. -\end{document} diff --git a/latexdiff-1.0.1/example/example-draft.tex b/latexdiff-1.0.1/example/example-draft.tex deleted file mode 100644 index 593a170..0000000 --- a/latexdiff-1.0.1/example/example-draft.tex +++ /dev/null @@ -1,59 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things could be said -were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} - - diff --git a/latexdiff-1.0.1/example/example-rev.tex b/latexdiff-1.0.1/example/example-rev.tex deleted file mode 100644 index 4bcaf15..0000000 --- a/latexdiff-1.0.1/example/example-rev.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. More things could be -said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.1/latexdiff b/latexdiff-1.0.1/latexdiff deleted file mode 100755 index 4f34c1a..0000000 --- a/latexdiff-1.0.1/latexdiff +++ /dev/null @@ -1,3392 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -use Algorithm::Diff qw(traverse_sequences); - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -C or C<3>: Detect small change in equations and mark up and fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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 - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. - -Please send bug reports -to I or submit on latexdiff project page I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.1/latexdiff-fast b/latexdiff-1.0.1/latexdiff-fast deleted file mode 100755 index 46de52d..0000000 --- a/latexdiff-1.0.1/latexdiff-fast +++ /dev/null @@ -1,3953 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for differenceing -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that subroutine _longestCommonSubsequence has been replace by -# a routine which internally uses the UNIX diff command for -# the differencing rather than the Perl routines if the -# length of the sequences exceeds some threshold. -# Also, all POD documentation has been stripped out. -# -# (the distribution on which this modification is based is available -# from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The fast-differencing version of latexdiff is provided as a convenience -# for latex users under Unix-like systems which have a 'diff' command. -# If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -# Jonathan Paisley is acknowledged for the idea of using the system diff -# command to achieve shorter running times -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d fast', (q$Revision: 1.15 $ =~ /\d+/g)); - -# Global parameters - -use File::Temp qw/tempfile/; -# if larger number of elements in longestCommonSubsequence smaller than -# this number, then use internal algorithm, otherwise use UNIX diff -use constant THRESHOLD => 100 ; -# Detect whether diff --minimal option is available -# if yes we use it -use constant MINIMAL => ( system('diff','--minimal','/dev/null','/dev/null') >> 8 ==0 ? "--minimal" : "" ) ; - - - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # Check whether to use internal routine (small number of elements) - # or use it as a wrapper for UNIX diff - if ( ( $#$a > $#$b ? $#$a : $#$b) < THRESHOLD ) { - ### print STDERR "DEBUG: regular longestCommonSubsequence\n"; - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - } - else { - my ($fha,$fhb,$fna,$fnb,$ele,$key); - my ($alines,$blines,$alb,$alf,$blb,$blf); - my ($minimal)=MINIMAL; - # large number of elements, use system diff - ### print STDERR "DEBUG: fast (diff) longestCommonSubsequence\n"; - - ($fha,$fna)=tempfile("DiffA-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence A"; - ($fhb,$fnb)=tempfile("DiffB-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence B"; - # prepare sequence A - foreach $ele ( @$a ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fha "$key\n" ; - } - close($fha); - # prepare sequence B - foreach $ele ( @$b ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fhb "$key\n" ; - } - close($fhb); - - open(DIFFPIPE, "diff $minimal $fna $fnb |") or die "_longestCommonSubsequence: Cannot launch diff process. $!" ; - # The diff line numbering begins with 1, but Perl subscripts start with 0 - # We follow the diff numbering but substract 1 when assigning to matchVector - $aStart++; $bStart++ ; $aFinish++ ; $bFinish++ ; - while( ) { - if ( ($alines,$blines) = ( m/^(\d*(?:,\d*)?)?c(\d*(?:,\d*)?)?$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - ($blb,$blf)=split(/,/,$blines); - $alf=$alb unless defined($alf); - $blf=$blb unless defined($blf); - while($aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - # check for consistency - $bStart==$blb or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in changed sequence"; - $aStart=$alf+1; - $bStart=$blf+1; - } - elsif ( ($alb,$blines) = ( m/^(\d*)a(\d*(?:,\d*)?)$/ ) ) { - ($blb,$blf)=split(/,/,$blines); - $blf=$blb unless defined($blf); - while ( $bStart < $blb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $aStart==$alb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in appended sequence near elements $aStart and $bStart"; - $bStart=$blf+1; - } - elsif ( ($alines,$blb) = ( m/^(\d*(?:,\d*)?)d(\d*)$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - $alf=$alb unless defined($alf); - while ( $aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$blb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in deleted sequence near elements $aStart and $bStart"; - $aStart=$alf+1; - } - elsif ( m/^Binary files/ ) { - # if diff reports it is a binary file force --text mode. I do not like - # to always use this option because it is probably only available in GNU diff - open(DIFFPIPE, "diff --text $fna $fnb |") or die "Cannot launch diff process. $!" ; - } - # Default: just skip line - } - while ($aStart <= $aFinish ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$bFinish+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency at end"; - close DIFFPIPE; - # check whether a system error has occurred or return status is greater than or equal to 5 - if ( $! || ($? >> 8) > 5) { - print STDERR "diff process failed with exit code ", ($? >> 8), " $!\n"; - die; - } - unlink $fna,$fnb ; - } - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -C or C<3>: Detect small change in equations and mark up and fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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 - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. - -Please send bug reports -to I or submit on latexdiff project page I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.1/latexdiff-so b/latexdiff-1.0.1/latexdiff-so deleted file mode 100755 index 0ded5a8..0000000 --- a/latexdiff-1.0.1/latexdiff-so +++ /dev/null @@ -1,3849 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for stand-alone version replaces -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that all POD documentation has been stripped out. -# I encourage you to download and install the Algorithm::Diff -# package and use the standard latexdiff version instead -# (current distribution available from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The stand-alone version of latexdiff is provided as a convenience -# for latex users with no knowledge of PERL who do not wish to install -# additional packages to be able to use latexdiff. If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d so', (q$Revision: 1.15 $ =~ /\d+/g)); - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -C or C<3>: Detect small change in equations and mark up and fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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 - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. - -Please send bug reports -to I or submit on latexdiff project page I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.1/latexdiff-vc b/latexdiff-1.0.1/latexdiff-vc deleted file mode 100755 index 45d52cd..0000000 --- a/latexdiff-1.0.1/latexdiff-vc +++ /dev/null @@ -1,485 +0,0 @@ -#!/usr/bin/env perl -# Place the following 2 lines at beginning to make script independent of location of perl -#eval 'exec perl -w -S $0 ${1+"$@"}' -# if 0; # not running under some shell -# -# latexdiff-vc - wrapper script for applying latexdiff to rcs managed files -# and for automatised creation of postscript or pdf from difference file -# -# Copyright (C) 2005-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# -# Contributors: S Utcke, H Bruyninckx -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# version 1.0.1 (change version numbering to match that of latexdiff) -# - Option --fast to use latexdiff-fast -# - git support (thanks to Bjørn Magnus Mathisen, Santi Béjar, Pietro Battiston and Stefan Alfredson for patches) - UNTESTED -# version 0.25: -# - bbl is allowed as alternative extension (instead of .tex) -# version 0.26a -# - Bug fix: it copes now correctly with the possibility that there are no changes between current -# and archived version -use Getopt::Long ; -use Pod::Usage qw/pod2usage/ ; -use File::Temp qw/tempdir/ ; -use File::Basename qw/dirname/; -use strict ; -use warnings ; - -my $versionstring=< 1); -# Variables -my ($file1,$file2,$diff,$diffbase,$answer,$options,$infile,$append,$dirname,$cwd); -my (@files,@ldoptions,@tmpfiles,@ptmpfiles,@difffiles); # , - -Getopt::Long::Configure('pass_through','bundling'); - -GetOptions('revision|r:s' => \@revs, - 'cvs' => \$cvs, - 'rcs' => \$rcs, - 'svn' => \$svn, - 'git' => \$git, - 'dir|d:s' => \$dir, - 'fast' => \$fast, - 'postscript|ps' => \$postscript, - 'pdf' => \$pdf, - 'force' => \$force, - 'version' => \$version, - 'help|h' => \$help); - -if ( $help ) { - pod2usage(1) ; -} - -if ( $version ) { - die $versionstring ; -} - -if ( $fast ) { - $latexdiff='latexdiff-fast'; -} - -if ( $cvs ) { - $vc="CVS"; -} -if ( $rcs ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="RCS"; -} -if ( $svn ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="SVN"; -} -if ( $git ) { - die "Cannot specify more than one of --cvs, --rcs, --svn or --git." if ($vc); - $vc="GIT"; -} - - -# check whether the first file name got misinterpreted as an option to an empty -r option -if ( @revs && -f $revs[$#revs] ) { - unshift @ARGV,$revs[$#revs]; - $revs[$#revs]=""; -} -# check whether the first file name got misinterpreted as an option to an empty -d option -if ( defined($dir) && -f $dir ) { - unshift @ARGV,$dir; - $dir=""; -} - -$file2=pop @ARGV; -( defined($file2) && $file2 =~ /\.(tex|bbl)$/ ) or pod2usage("Must specify at least one tex or bbl file"); - -if (! $vc && scalar(@revs)>0 ) { - # have to guess $vc - # check whether we have a special name - if ( $0 =~ /-cvs$/ ) { - $vc="CVS"; - } elsif ( $0 =~ /-rcs$/ ) { - $vc="RCS"; - } elsif ( $0 =~ /-svn$/ ) { - $vc="SVN"; - } elsif ( $0 =~ /-git$/ ) { - $vc="GIT"; - } elsif ( -e "CVSROOT" || defined($ENV{"CVSROOT"}) ) { - print STDERR "Guess you are using CVS ...\n"; - $vc="CVS"; - } elsif ( -e "$file2,v" ) { - print STDERR "Guess you are using RCS ...\n"; - $vc="RCS"; - } elsif ( -d ".svn" ) { - print STDERR "Guess you are using SVN ...\n"; - $vc="SVN"; - } elsif ( -d ".git" ) { - print STDERR "Guess you are using GIT ...\n"; - $vc="GIT"; - } else { - print STDERR "Cannot figure out version control system, so I default to CVS\n"; - $vc="CVS"; - } -} - -if (defined($dir) && $dir=~/^\.\/?/ ) { - print STDERR "You wrote -dir=. but you do not really like to do that, do you ?\n"; - exit 10 -} - -if ( scalar(@revs)>0 ) { - if ( $vc eq "CVS" ) { - $diffcmd = "cvs diff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "RCS" ) { - $diffcmd = "rcsdiff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "SVN" ) { - $diffcmd = "svn diff -r "; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "GIT" ) { - $diffcmd = "git diff -r --relative --no-prefix "; - $patchcmd = "patch -R -p0"; - # alternatively: - # $diffcmd = "git diff "; - # $patchcmd = "patch -R -p1"; - } else { - print STDERR "Unknown versioning system $vc \n"; - exit 10; - } -} - - -# make file list (last arguments), initial arguments have to be passed to latexdiff -# We assume an argument is a valid file rather than a latexdiff argument -# if it has extension .tex or .bbl - -@files=($file2); -while( $file1=pop @ARGV ) { - if ( $file1 =~ /\.(tex|bbl)$/ ) { - # $file1 looks like a valid file name and is prepended to file list - unshift @files, $file1 ; - } else { - # $file1 looks like an option for latexdiff, push it back to argument stack - unshift @ldoptions, $file1 ; - } -} - -if ( scalar(@revs) == 0 ) { - pod2usage("When -r option is not used, two .tex files (old and new) must be given on the command line") unless @files==2; - # compare two files - $file1=shift @files ; -} - -if ( scalar(@revs) == 2 ) { - $append = "-diff$revs[0]-$revs[1]"; -} elsif ( scalar(@revs) == 1 || $revs[0] ) { - $append = "-diff$revs[0]"; -} else { - $append = "-diff"; -} - -if ( defined ($dir) && ! $dir ) { - # bare -d option => choose directory name - ($dir=$append) =~ s/^-//; -} - -if ( ($vc eq "SVN" || $vc eq "CVS") && scalar(@revs)) { - length($revs[$#revs]) > 0 or $revs[$#revs]="HEAD"; - length($revs[0]) > 0 or $revs[0]="HEAD"; -} - -#exit ; - - -# cycle through all files - -@difffiles=(); -while ( $infile=$file2=shift @files ) { - print STDERR "Working on $infile \n"; - if ( scalar(@revs) == 1 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - push @tmpfiles,$file1; - # compare file with previous version ($revs[0]="") or specified version - ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - # no differences detected, i.e. file is equal to current version - system("\cp $infile $file1"); - } - } elsif ( scalar(@revs) == 2 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - $file2 =~ s/\.(tex|bbl)/-newtmp-$$.$1/ ; - push @tmpfiles,$file2; - ; - if (system("$diffcmd$revs[1] $infile | $patchcmd -o$file2")==0 and -z $file2 ) { - system("\cp $infile $file2"); - } - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - system("\cp $infile $file1"); - }; - } - - if ( -z $file1 || -z $file2) { - print STDERR "One or both of the files to compare are empty. Possibly something went wrong in the retrieval of older versions. Aborting ...\n" ; - exit(10); - } - - # Get name of difference file - if ( defined($dir) ) { - $diff="$dir/$infile" ; - } else { - ($diff=$infile) =~ s/\.(tex|bbl)$/$append.$1/ ; - } - # make directories if needed - $dirname=dirname($diff) ; - system("mkdir -p $dirname") unless ( -e $dirname ); - - # Remaining options are passed to latexdiff - $options = join(" ",@ldoptions); - - if ( -e $diff && ! $force ) { - print STDERR "OK to overwrite existing file $diff (y/n)? "; - $answer = ; - unless ($answer =~ /^y/i ) { - unlink @tmpfiles; - die "Abort ... " ; - } - } - print "Running $latexdiff\n"; - unless ( system("$latexdiff $options $file1 $file2 > $diff") == 0 ) { - print STDERR "Something went wrong in $latexdiff. Deleting $diff and abort\n" ; unlink $diff ; exit(5) - }; - print "Generated difference file $diff\n"; - - if ( ( $postscript or $pdf ) and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff ) ) ) { - # save filename for later processing if postscript or pdf conversion is requested and either two-file mode was used (scalar(@revs)==0) or the diff file contains documentclass statement (ie. is a root document) - push @difffiles, $diff ; - } - - unlink @tmpfiles; -} - -foreach $diff ( @difffiles ) { - chomp($cwd=(`pwd`)); - if (defined($dir)) { - ( $diff =~ s/$dir\/?// ) ; - chdir $dir ; - } - @ptmpfiles=(); - ( $diffbase=$diff) =~ s/\.(tex)$// ; - - # adapt magically changebar styles to [pdftex] display driver if pdf output was selected - if ( $pdf ) { - system("sed \"s/Package\\[dvips\\]/Package[pdftex]/\" $diff > $diff.tmp$$ ; \\mv $diff.tmp$$ $diff"); - } - print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n"; - - if ( system("grep -q \'^[^%]*\\\\bibliography\' $diff") == 0 ) { - if ( $postscript) { - system("latex --interaction=batchmode $diff; bibtex $diffbase"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } elsif ( $pdf ) { - system("pdflatex --interaction=batchmode $diff; bibtex $diffbase"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } - } - - if ( $postscript ) { - my $dvi="$diffbase.dvi"; - my $ps="$diffbase.ps"; - - system("latex --interaction=batchmode $diff; latex $diff; dvips -o $ps $dvi"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; - print "Generated postscript file $ps\n"; - } - elsif ( $pdf ) { - system("pdflatex --interaction=batchmode $diff; pdflatex $diff"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log"; - } - unlink @ptmpfiles; - chdir $cwd; -} - -# greptex returns 1 if regex is not matched in filename -# 0 if there is a match -sub greptex { - my ($regex,$filename)=@_; - my ($i)=0; - open (FH, $filename) or die("Couldn't open $filename: $!"); - while () { - next if /^\s*%/; # skip comment lines - if ( m/$regex/ ) { - close(FH); - return(0); - } - # only scan 25 lines - $i++; - last if $i>25 ; - } - close(FH); - return(1); -} - - -=head1 NAME - -latexdiff-vc - wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) - -=head1 SYNOPSIS - -B [ F ] [ F ] B<-r> [F] [B<-r> F] F [ F ...] - - or - -B [ F ] [ F ][ B<--postscript> | B<--pdf> ] F F - -=head1 DESCRIPTION - -I is a wrapper script that applies I to a -file, or multiple files under version control (CVS, RCS or SVN), and optionally runs the -sequence of C and C or C commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. - -=head1 OPTIONS - -=over 4 - -=item B<--rcs>, B<--svn>, B<--cvs>, or B<--git> - -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. - -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. - -=item B<-r>, B<-r> F or B<--revision>, B<--revision=>F - -Choose revision (under RCS, CVS, SVN or GIT). One or two B<-r> options can be -specified, and they result in different behaviour: - -=over 4 - -=item B -r F ... - -compares F with the most recent version checked into RCS. - -=item B -r F F ... - -compares F with revision F. - -=item B -r F -r F F ... - -compares revisions F and F of F. - -Multiple files can be specified for all of the above options. All files must have the -extension C<.tex>, though. - -=item B F F - -compares two files. - -=back - -The name of the difference file is generated automatically and -reported to stdout. - -=item B<-d> or B<--dir> B<-d> F or B<--dir=>F - -Rather than appending the string C and optionally the version -numbers given to the output-file, this will prepend a directory name C -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname F can be specified, which is prepended instead of C. - -=item B<--fast> - -Use C instead of C - -=item B<--ps> or B<--postscript> - -Generate postscript output from difference file. This will run the -sequence C on the difference file (do not use -this option in the rare cases, where three C commands are -required if you care about correct referencing). If the difference -file contains a C<\bibliography> tag, run the sequence C. - -=item B<--pdf> - -Generate pdf output from difference file using C. This will -run the sequence C on the difference file, or -C for files requiring bibtex. - -=item B<--force> - -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - -All other options are passed on to C. - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I uses external commands and is therefore -limited to Unix-like systems. It also requires the RCS version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. - -=head1 BUG REPORTING - - Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(option C<--version>) -. -=head1 AUTHOR - -Copyright (C) 2005,2012 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 -Contributors: S Utcke, H Bruyninckx - -=cut - diff --git a/latexdiff-1.0.1/latexdiff-vc.1 b/latexdiff-1.0.1/latexdiff-vc.1 deleted file mode 100644 index 6cb393f..0000000 --- a/latexdiff-1.0.1/latexdiff-vc.1 +++ /dev/null @@ -1,246 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF-VC 1" -.TH LATEXDIFF-VC 1 "2012-11-13" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff\-vc \- wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ] \fB\-r\fR [\fIrev1\fR] [\fB\-r\fR \fIrev2\fR] \fIfile1.tex\fR [ \fIfile2.tex\fR ...] -.PP -.Vb 1 -\& or -.Ve -.PP -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ][ \fB\-\-postscript\fR | \fB\-\-pdf\fR ] \fIold.tex\fR \fInew.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexdiff-vc\fR is a wrapper script that applies \fIlatexdiff\fR to a -file, or multiple files under version control (\s-1CVS\s0, \s-1RCS\s0 or \s-1SVN\s0), and optionally runs the -sequence of \f(CW\*(C`latex\*(C'\fR and \f(CW\*(C`dvips\*(C'\fR or \f(CW\*(C`pdflatex\*(C'\fR commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-\-rcs\fR, \fB\-\-svn\fR, \fB\-\-cvs\fR, or \fB\-\-git\fR" 4 -.IX Item "--rcs, --svn, --cvs, or --git" -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. -.Sp -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. -.IP "\fB\-r\fR, \fB\-r\fR \fIrev\fR or \fB\-\-revision\fR, \fB\-\-revision=\fR\fIrev\fR" 4 -.IX Item "-r, -r rev or --revision, --revision=rev" -Choose revision (under \s-1RCS\s0, \s-1CVS\s0, \s-1SVN\s0 or \s-1GIT\s0). One or two \fB\-r\fR options can be -specified, and they result in different behaviour: -.RS 4 -.IP "\fBlatexdiff-vc\fR \-r \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r file.tex ..." -compares \fIfile.tex\fR with the most recent version checked into \s-1RCS\s0. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 file.tex ..." -compares \fIfile.tex\fR with revision \fIrev1\fR. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \-r \fIrev2\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 -r rev2 file.tex ..." -compares revisions \fIrev1\fR and \fIrev2\fR of \fIfile.tex\fR. -.Sp -Multiple files can be specified for all of the above options. All files must have the -extension \f(CW\*(C`.tex\*(C'\fR, though. -.IP "\fBlatexdiff-vc\fR \fIold.tex\fR \fInew.tex\fR" 4 -.IX Item "latexdiff-vc old.tex new.tex" -compares two files. -.RE -.RS 4 -.Sp -The name of the difference file is generated automatically and -reported to stdout. -.RE -.IP "\fB\-d\fR or \fB\-\-dir\fR \fB\-d\fR \fIpath\fR or \fB\-\-dir=\fR\fIpath\fR" 4 -.IX Item "-d or --dir -d path or --dir=path" -Rather than appending the string \f(CW\*(C`diff\*(C'\fR and optionally the version -numbers given to the output-file, this will prepend a directory name \f(CW\*(C`diff\*(C'\fR -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname \fIpath\fR can be specified, which is prepended instead of \f(CW\*(C`diff\*(C'\fR. -.IP "\fB\-\-fast\fR" 4 -.IX Item "--fast" -Use \f(CW\*(C`latexdiff\-fast\*(C'\fR instead of \f(CW\*(C`latexdiff\*(C'\fR -.IP "\fB\-\-ps\fR or \fB\-\-postscript\fR" 4 -.IX Item "--ps or --postscript" -Generate postscript output from difference file. This will run the -sequence \f(CW\*(C`latex; latex; dvips\*(C'\fR on the difference file (do not use -this option in the rare cases, where three \f(CW\*(C`latex\*(C'\fR commands are -required if you care about correct referencing). If the difference -file contains a \f(CW\*(C`\ebibliography\*(C'\fR tag, run the sequence \f(CW\*(C`latex; -bibtex; latex; latex; dvips\*(C'\fR. -.IP "\fB\-\-pdf\fR" 4 -.IX Item "--pdf" -Generate pdf output from difference file using \f(CW\*(C`pdflatex\*(C'\fR. This will -run the sequence \f(CW\*(C`pdflatex; pdflatex\*(C'\fR on the difference file, or -\&\f(CW\*(C`pdflatex; bibtex; pdflatex; pdflatex\*(C'\fR for files requiring bibtex. -.IP "\fB\-\-force\fR" 4 -.IX Item "--force" -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. -.IP "\fB\-\-help\fR or \fB\-h\fR" 4 -.IX Item "--help or -h" -Show help text -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Show version number -.PP -All other options are passed on to \f(CW\*(C`latexdiff\*(C'\fR. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff-vc\fR uses external commands and is therefore -limited to Unix-like systems. It also requires the \s-1RCS\s0 version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. -.SH "BUG REPORTING" -.IX Header "BUG REPORTING" -.Vb 6 -\& Please submit bug reports through -\&the latexdiff project page I or send -\&to I. Include the serial number of I -\&(option C<\-\-version>) -\&. -\&=head1 AUTHOR -.Ve -.PP -Copyright (C) 2005,2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -Contributors: S Utcke, H Bruyninckx diff --git a/latexdiff-1.0.1/latexdiff.1 b/latexdiff-1.0.1/latexdiff.1 deleted file mode 100644 index 7073b62..0000000 --- a/latexdiff-1.0.1/latexdiff.1 +++ /dev/null @@ -1,751 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF 1" -.TH LATEXDIFF 1 "2012-11-13" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff \- determine and markup differences between two latex files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff\fR [ \fB\s-1OPTIONS\s0\fR ] \fIold.tex\fR \fInew.tex\fR > \fIdiff.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Briefly, \fIlatexdiff\fR is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. -.PP -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "\f(CW\*(C`%DIF\ >\*(C'\fR" is appended to each added line, i.e. a -line present in \f(CW\*(C`new.tex\*(C'\fR but not in \f(CW\*(C`old.tex\*(C'\fR. Discarded lines - are deactivated by prepending "\f(CW\*(C`%DIF\ <\*(C'\fR". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file \f(CW\*(C`diff.tex\*(C'\fR will be similar to -\&\f(CW\*(C`new.tex\*(C'\fR. At the end of the preamble, the definitions for \fIlatexdiff\fR markup commands are inserted. -In differencing the main body of the text, \fIlatexdiff\fR attempts to -satisfy the following guidelines (in order of priority): -.IP "1." 3 -If both \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR are valid LaTeX, then the resulting -\&\f(CW\*(C`diff.tex\*(C'\fR should also be valid LateX. (\s-1NB\s0 If a few plain TeX commands -are used within \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR then \f(CW\*(C`diff.tex\*(C'\fR is not -guaranteed to work but usually will). -.IP "2." 3 -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -\&\f(CW\*(C`diff.tex\*(C'\fR. -.IP "3." 3 -If a changed passage contains text or text-producing commands, then -running \f(CW\*(C`diff.tex\*(C'\fR through LateX should produce output where added -and discarded passages are highlighted. -.IP "4." 3 -Where there are insignificant differences, e.g. in the positioning of -line breaks, \f(CW\*(C`diff.tex\*(C'\fR should follow the formatting of \f(CW\*(C`new.tex\*(C'\fR -.PP -For differencing the same algorithm as \fIdiff\fR is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, \f(CW\*(C`\ecaption\*(C'\fR and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write -.PP -.Vb 1 -\& \esection{\etextem{This is an emphasized section title}} -.Ve -.PP -and not -.PP -.Vb 1 -\& \esection {\etextem{This is an emphasized section title}} -.Ve -.PP -or -.PP -.Vb 1 -\& \esection\etextem{This is an emphasized section title} -.Ve -.PP -even though all varieties are the same to LaTeX (but see -\&\fB\-\-allow\-spaces\fR option which allows the second variety). -.PP -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the \s-1PICTUREENV\s0 configuration variable, set by -default to \f(CW\*(C`picture\*(C'\fR and \f(CW\*(C`DIFnomarkup\*(C'\fR environments; see \fB\-\-config\fR -option). The latter environment (\f(CW\*(C`DIFnomarkup\*(C'\fR) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by \f(CW\*(C`\ebegin{DIFnomarkup}\*(C'\fR and \f(CW\*(C`\eend{DIFnomarkup}\*(C'\fR. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, -.PP -\&\f(CW\*(C`\enewenvironment{DIFnomarkup}{}{}\*(C'\fR -.PP -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. -.PP -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. -.PP -All markup commands inserted by \fIlatexdiff\fR begin with "\f(CW\*(C`\eDIF\*(C'\fR". Added -blocks containing words, commands or comments which are in \f(CW\*(C`new.tex\*(C'\fR -but not in \f(CW\*(C`old.tex\*(C'\fR are marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR and \f(CW\*(C`\eDIFaddend\*(C'\fR. -Discarded blocks are marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR. -Within added blocks all text is highlighted with \f(CW\*(C`\eDIFadd\*(C'\fR like this: -\&\f(CW\*(C`\eDIFadd{Added text block}\*(C'\fR -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces \*(L"{\*(R" and \*(L"}\*(R" are never put within -the scope of \f(CW\*(C`\eDIFadd\*(C'\fR. Added comments are marked by prepending -"\f(CW\*(C`%DIF\ >\ \*(C'\fR". -.PP -Within deleted blocks text is highlighted with \f(CW\*(C`\eDIFdel\*(C'\fR. Deleted -comments are marked by prepending "\f(CW\*(C`%DIF\ <\ \*(C'\fR\*(L". Non-safe command -and curly braces within deleted blocks are commented out with -\&\*(R"\f(CW\*(C`%DIFDELCMD\ <\ \*(C'\fR". -.SH "OPTIONS" -.IX Header "OPTIONS" -.SS "Preamble" -.IX Subsection "Preamble" -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. -.IP "\fB\-\-type=markupstyle\fR or \fB\-t markupstyle\fR" 4 -.IX Item "--type=markupstyle or -t markupstyle" -Add code to preamble for selected markup style. This option defines -\&\f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands. -Available styles: -.Sp -\&\f(CW\*(C`UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR\*(C'\fR -.Sp -[ Default: \f(CW\*(C`UNDERLINE\*(C'\fR ] -.IP "\fB\-\-subtype=markstyle\fR or \fB\-s markstyle\fR" 4 -.IX Item "--subtype=markstyle or -s markstyle" -Add code to preamble for selected style for bracketing -commands (e.g. to mark changes in margin). This option defines -\&\f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR commands. -Available styles: \f(CW\*(C`SAFE MARGINAL COLOR DVIPSCOL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`SAFE\*(C'\fR ] -.IP "\fB\-\-floattype=markstyle\fR or \fB\-f markstyle\fR" 4 -.IX Item "--floattype=markstyle or -f markstyle" -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -\&\f(CW\*(C`\eDIF...FL\*(C'\fR commands. -Available styles: \f(CW\*(C`FLOATSAFE TRADITIONALSAFE IDENTICAL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`FLOATSAFE\*(C'\fR ] -.IP "\fB\-\-encoding=enc\fR or \fB\-e enc\fR" 4 -.IX Item "--encoding=enc or -e enc" -Specify encoding of old.tex and new.tex. Typical encodings are -\&\f(CW\*(C`ascii\*(C'\fR, \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR, \f(CW\*(C`latin9\*(C'\fR. A list of available encodings can be -obtained by executing -.Sp -\&\f(CW\*(C`perl \-MEncode \-e \*(Aqprint join ("\en",Encode\-\*(C'\fRencodings( \*(L":all\*(R" )) ;' > -.Sp -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation \f(CW\*(C`\eusepackage[..]{inputenc}\*(C'\fR in which case the -encoding chosen by this command is asssumed. Note that \s-1ASCII\s0 (standard -latex) is a subset of utf8] -.IP "\fB\-\-preamble=file\fR or \fB\-p file\fR" 4 -.IX Item "--preamble=file or -p file" -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -\&\f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFadd{..}, -\&\eDIFdelbegin,\eDIFdelend,\eDIFdel{..},\*(C'\fR -and varieties for use within floats -\&\f(CW\*(C`\eDIFaddbeginFL, \eDIFaddendFL, \eDIFaddFL{..}, -\&\eDIFdelbeginFL, \eDIFdelendFL, \eDIFdelFL{..}\*(C'\fR -(If this option is set \fB\-t\fR, \fB\-s\fR, and \fB\-f\fR options -are ignored.) -.IP "\fB\-\-packages=pkg1,pkg2,..\fR" 4 -.IX Item "--packages=pkg1,pkg2,.." -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for \f(CW\*(C`\eusepackage\*(C'\fR commands. -Use of the \fB\-\-packages\fR option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use \fB\-\-packages=none\fR. -The following packages trigger special behaviour: -.RS 4 -.ie n .IP """amsmath""" 8 -.el .IP "\f(CWamsmath\fR" 8 -.IX Item "amsmath" -Configuration variable amsmath is set to \f(CW\*(C`align*\*(C'\fR (Default: \f(CW\*(C`eqnarray*\*(C'\fR) -.ie n .IP """endfloat""" 8 -.el .IP "\f(CWendfloat\fR" 8 -.IX Item "endfloat" -Ensure that \f(CW\*(C`\ebegin{figure}\*(C'\fR and \f(CW\*(C`\eend{figure}\*(C'\fR always appear by themselves on a line. -.ie n .IP """hyperref""" 8 -.el .IP "\f(CWhyperref\fR" 8 -.IX Item "hyperref" -Change name of \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands to \f(CW\*(C`\eDIFaddtex\*(C'\fR and \f(CW\*(C`\eDIFdeltex\*(C'\fR and -define new \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). -.RE -.RS 4 -.Sp -[ Default: scan the preamble for \f(CW\*(C`\e\eusepackage\*(C'\fR commands to determine - loaded packages.] -.RE -.IP "\fB\-\-show\-preamble\fR" 4 -.IX Item "--show-preamble" -Print generated or included preamble commands to stdout. -.SS "Configuration" -.IX Subsection "Configuration" -.ie n .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-safecmd=exclude-file or -A exclude-file or --exclude-safecmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-safecmd=replace\-file\fR" 4 -.IX Item "--replace-safecmd=replace-file" -.ie n .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-safecmd=append-file or -a append-file or --append-safecmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a \f(CW\*(C`\eDIFadd\*(C'\fR or \f(CW\*(C`\eDIFdel\*(C'\fR command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -\&\*(L"\e\*(R" of the command is not included. -The \fB\-\-exclude\-safecmd\fR and \fB\-\-append\-safecmd\fR options can be combined with the \-\fB\-\-replace\-safecmd\fR -option and can be used repeatedly to add cumulatively to the lists. - \fB\-\-exclude\-safecmd\fR -and \fB\-\-append\-safecmd\fR can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus \*(L"\e,\*(R". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. -.ie n .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-textcmd=exclude-file or -X exclude-file or --exclude-textcmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-textcmd=replace\-file\fR" 4 -.IX Item "--replace-textcmd=replace-file" -.ie n .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-textcmd=append-file or -x append-file or --append-textcmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for \fB\-\-exclude\-safecmd\fR directly above for further details. -.IP "\fB\-\-replace\-context1cmd=replace\-file\fR" 4 -.IX Item "--replace-context1cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-context1cmd=append-file or =item --append-context1cmd=cmd1,cmd2,..." -.PD -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \ecaption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. -.IP "\fB\-\-replace\-context2cmd=replace\-file\fR" 4 -.IX Item "--replace-context2cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=""cmd1,cmd2,...""\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.el .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=``cmd1,cmd2,...''\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.IX Item "--append-context2cmd=append-file or =item --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." -.IP "\fB\-\-config var1=val1,var2=val2,...\fR or \fB\-c var1=val1,..\fR" 4 -.IX Item "--config var1=val1,var2=val2,... or -c var1=val1,.." -.IP "\fB\-c configfile\fR" 4 -.IX Item "-c configfile" -.PD -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): -.Sp -\&\f(CW\*(C`MINWORDSBLOCK\*(C'\fR (integer) -.Sp -\&\f(CW\*(C`FLOATENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`PICTUREENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`MATHARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHARRREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`ARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`COUNTERCMD\*(C'\fR (RegEx) -.IP "\fB\-\-show\-safecmd\fR" 4 -.IX Item "--show-safecmd" -Print list of RegEx matching and excluding safe commands. -.IP "\fB\-\-show\-textcmd\fR" 4 -.IX Item "--show-textcmd" -Print list of RegEx matching and excluding commands with text argument. -.IP "\fB\-\-show\-config\fR" 4 -.IX Item "--show-config" -Show values of configuration variables. -.IP "\fB\-\-show\-all\fR" 4 -.IX Item "--show-all" -Combine all \-\-show commands. -.Sp -\&\s-1NB\s0 For all \-\-show commands, no \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR file needs to be specified, and no -differencing takes place. -.SS "Other configuration options:" -.IX Subsection "Other configuration options:" -.IP "\fB\-\-allow\-spaces\fR" 4 -.IX Item "--allow-spaces" -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). -.IP "\fB\-\-math\-markup=level\fR" 4 -.IX Item "--math-markup=level" -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): -.Sp -\&\f(CW\*(C`off\*(C'\fR or \f(CW0\fR: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. -.Sp -\&\f(CW\*(C`whole\*(C'\fR or \f(CW1\fR: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. -.Sp -\&\f(CW\*(C`coarse\*(C'\fR or \f(CW2\fR: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -\&\f(CW\*(C`fine\*(C'\fR or \f(CW3\fR: Detect small change in equations and mark up and fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. -.IP "\fB\-\-disable\-citation\-markup\fR" 4 -.IX Item "--disable-citation-markup" -Suppress citation markup in styles using ulem (\s-1UNDERLINE\s0, -\&\s-1FONTSTRIKE\s0, \s-1CULINECHBAR\s0) -.IP "\fB\-\-enable\-citation\-markup\fR" 4 -.IX Item "--enable-citation-markup" -Protect citation commands in changed sections with \e\embox command [i.e. use default behaviour for ulem package for other packages] -.SS "Miscellaneous" -.IX Subsection "Miscellaneous" -.RS 4 -Output various status information to stderr during processing. -Default is to work silently. -.Sp -\&\fB\-\-driver=type\fR -.Sp -Choose driver for changebar package (only relevant for styles using - changebar: \s-1CCHANGEBAR\s0 \s-1CFONTCHBAR\s0 \s-1CULINECHBAR\s0 \s-1CHANGEBAR\s0). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] -.Sp -\&\fB\-\-ignore\-warnings\fR -.Sp -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to \f(CW\*(C`latexdiff\*(C'\fR but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. -.Sp -\&\fB\-\-label=label\fR or -\&\fB\-L label\fR -.Sp -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this \f(CW\*(C`\-L labelold \-L labelnew\*(C'\fR. -[Default: use the filename and modification dates for the label] -.Sp -\&\fB\-\-no\-label\fR -.Sp -Suppress inclusion of old and new file names as comment in output file -.Sp -\&\fB\-\-visble\-label\fR -.Sp -Include old and new filenames (or labels set with \-\-label option) as -visible output. -.Sp -\&\fB\-\-flatten\fR -.Sp -Replace \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within body by the content -of the files in their argument. If \f(CW\*(C`\eincludeonly\*(C'\fR is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. -\&\-\-flatten is applied recursively, so inputted files can contain further -\&\f(CW\*(C`\einput\*(C'\fR statements. -.Sp -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. -.Sp -\&\fB\-\-help\fR or -\&\fB\-h\fR -.Sp -Show help text -.Sp -\&\fB\-\-version\fR -.Sp -Show version number -.RE -.SS "Predefined styles" -.IX Subsection "Predefined styles" -.SS "Major types" -.IX Subsection "Major types" -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands \f(CW\*(C`\eDIFadd{...}\*(C'\fR and \f(CW\*(C`\eDIFdel{...}\*(C'\fR . -.ie n .IP """UNDERLINE""" 10 -.el .IP "\f(CWUNDERLINE\fR" 10 -.IX Item "UNDERLINE" -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). -.ie n .IP """CTRADITIONAL""" 10 -.el .IP "\f(CWCTRADITIONAL\fR" 10 -.IX Item "CTRADITIONAL" -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) -.ie n .IP """TRADITIONAL""" 10 -.el .IP "\f(CWTRADITIONAL\fR" 10 -.IX Item "TRADITIONAL" -Like \f(CW\*(C`CTRADITIONAL\*(C'\fR but without the use of color. -.ie n .IP """CFONT""" 10 -.el .IP "\f(CWCFONT\fR" 10 -.IX Item "CFONT" -Added text is blue and set in sans-serif, and discarded text is red and very small size. -.ie n .IP """FONTSTRIKE""" 10 -.el .IP "\f(CWFONTSTRIKE\fR" 10 -.IX Item "FONTSTRIKE" -Added tex is set in sans-serif, discarded text small and struck out -.ie n .IP """CCHANGEBAR""" 10 -.el .IP "\f(CWCCHANGEBAR\fR" 10 -.IX Item "CCHANGEBAR" -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). -.ie n .IP """CFONTCHBAR""" 10 -.el .IP "\f(CWCFONTCHBAR\fR" 10 -.IX Item "CFONTCHBAR" -Like \f(CW\*(C`CFONT\*(C'\fR but with additional changebars (Requires color and changebar packages). -.ie n .IP """CULINECHBAR""" 10 -.el .IP "\f(CWCULINECHBAR\fR" 10 -.IX Item "CULINECHBAR" -Like \f(CW\*(C`UNDERLINE\*(C'\fR but with additional changebars (Requires color, ulem and changebar packages). -.ie n .IP """CHANGEBAR""" 10 -.el .IP "\f(CWCHANGEBAR\fR" 10 -.IX Item "CHANGEBAR" -No mark up of text, but mark margins with changebars (Requires changebar package). -.ie n .IP """INVISIBLE""" 10 -.el .IP "\f(CWINVISIBLE\fR" 10 -.IX Item "INVISIBLE" -No visible markup (but generic markup commands will still be inserted. -.SS "Subtypes" -.IX Subsection "Subtypes" -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR) -.ie n .IP """SAFE""" 10 -.el .IP "\f(CWSAFE\fR" 10 -.IX Item "SAFE" -No additional markup (Recommended choice) -.ie n .IP """MARGIN""" 10 -.el .IP "\f(CWMARGIN\fR" 10 -.IX Item "MARGIN" -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard \f(CW\*(C`\emarginpar\*(C'\fR command \- note that this sometimes moves somewhat -from the intended position. -.ie n .IP """COLOR""" 10 -.el .IP "\f(CWCOLOR\fR" 10 -.IX Item "COLOR" -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). -.ie n .IP """DVIPSCOL""" 10 -.el .IP "\f(CWDVIPSCOL\fR" 10 -.IX Item "DVIPSCOL" -An alternative way of marking added passages in blue, and deleted ones in red. Note -that \f(CW\*(C`DVIPSCOL\*(C'\fR 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). -.SS "Float Types" -.IX Subsection "Float Types" -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. -.ie n .IP """FLOATSAFE""" 10 -.el .IP "\f(CWFLOATSAFE\fR" 10 -.IX Item "FLOATSAFE" -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is \f(CW\*(C`MARGIN\*(C'\fR as \f(CW\*(C`\emarginpar\*(C'\fR does not work properly within floats. -.ie n .IP """TRADITIONALSAFE""" 10 -.el .IP "\f(CWTRADITIONALSAFE\fR" 10 -.IX Item "TRADITIONALSAFE" -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \e[ and \e] and the deleted text is set in scriptscript size. This float type should always be used with the \f(CW\*(C`TRADITIONAL\*(C'\fR and \f(CW\*(C`CTRADITIONAL\*(C'\fR markup types as the \efootnote command does not work properly in floating environments. -.ie n .IP """IDENTICAL""" 10 -.el .IP "\f(CWIDENTICAL\fR" 10 -.IX Item "IDENTICAL" -Make no difference between the main text and floats. -.SS "Configuration Variables" -.IX Subsection "Configuration Variables" -.ie n .IP """MINWORDSBLOCK""" 10 -.el .IP "\f(CWMINWORDSBLOCK\fR" 10 -.IX Item "MINWORDSBLOCK" -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than \f(CW\*(C`MINWORDSBLOCK\*(C'\fR to the preceding added and discarded parts. -.Sp -[ Default: 3 ] -.ie n .IP """FLOATENV""" 10 -.el .IP "\f(CWFLOATENV\fR" 10 -.IX Item "FLOATENV" -Environments whose name matches the regular expression in \f(CW\*(C`FLOATENV\*(C'\fR are -considered floats. Within these environments, the \fIlatexdiff\fR markup commands -are replaced by their \s-1FL\s0 variaties. -.Sp -[ Default: \f(CW\*(C`(?:figure|table|plate)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """PICTUREENV""" 10 -.el .IP "\f(CWPICTUREENV\fR" 10 -.IX Item "PICTUREENV" -Within environments whose name matches the regular expression in \f(CW\*(C`PICTUREENV\*(C'\fR -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). -.Sp -[ Default: \f(CW\*(C`(?:picture|DIFnomarkup)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """MATHENV"",""MATHREPL""" 10 -.el .IP "\f(CWMATHENV\fR,\f(CWMATHREPL\fR" 10 -.IX Item "MATHENV,MATHREPL" -If both \ebegin and \eend for a math environment (environment name matching \f(CW\*(C`MATHENV\*(C'\fR -or \e[ and \e]) -are within the same deleted block, they are replaced by a \ebegin and \eend commands for \f(CW\*(C`MATHREPL\*(C'\fR -rather than being commented out. -.Sp -[ Default: \f(CW\*(C`MATHENV\*(C'\fR=\f(CW\*(C`(?:displaymath|equation)\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`displaymath\*(C'\fR\ ] -.ie n .IP """MATHARRENV"",""MATHARRREPL""" 10 -.el .IP "\f(CWMATHARRENV\fR,\f(CWMATHARRREPL\fR" 10 -.IX Item "MATHARRENV,MATHARRREPL" -as \f(CW\*(C`MATHENV\*(C'\fR,\f(CW\*(C`MATHREPL\*(C'\fR but for equation arrays -.Sp -[ Default: \f(CW\*(C`MATHARRENV\*(C'\fR=\f(CW\*(C`eqnarray\e*?\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`eqnarray\*(C'\fR\ ] -.ie n .IP """ARRENV""" 10 -.el .IP "\f(CWARRENV\fR" 10 -.IX Item "ARRENV" -If a match to \f(CW\*(C`ARRENV\*(C'\fR is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by \f(CW\*(C`\embox{\*(C'\fR...\f(CW\*(C`}\*(C'\fR. This is necessary as underlining does not work within inlined array environments. -.Sp -[ Default: \f(CW\*(C`ARRENV\*(C'\fR=\f(CW\*(C`(?:array|[pbvBV]matrix)\*(C'\fR\ -.ie n .IP """COUNTERCMD""" 10 -.el .IP "\f(CWCOUNTERCMD\fR" 10 -.IX Item "COUNTERCMD" -If a command in a deleted block which is also in the textcmd list matches \f(CW\*(C`COUNTERCMD\*(C'\fR then an -additional command \f(CW\*(C`\eaddtocounter{\*(C'\fR\fIcntcmd\fR\f(CW\*(C`}{\-1}\*(C'\fR, where \fIcntcmd\fR is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. -.Sp -[ Default: \f(CW\*(C`COUNTERCMD\*(C'\fR=\f(CW\*(C`(?:footnote|part|section|subsection\*(C'\fR ... -.Sp -\&\f(CW\*(C`|subsubsection|paragraph|subparagraph)\*(C'\fR ] -.SH "COMMON PROBLEMS" -.IX Header "COMMON PROBLEMS" -.IP "Citations result in overfull boxes" 10 -.IX Item "Citations result in overfull boxes" -There is an incompatibility between the \f(CW\*(C`ulem\*(C'\fR package, which \f(CW\*(C`latexdiff\*(C'\fR uses for underlining and striking out in the \s-1UNDERLINE\s0 style, -the default style. In order to be able to mark up citations properly, they are placed with an \f(CW\*(C`\embox\*(C'\fR 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: -.Sp -1. Use \f(CW\*(C`COLOR\*(C'\fR or \f(CW\*(C`DVIPSCOL\*(C'\fR subtype markup (option \f(CW\*(C`\-s COLOR\*(C'\fR): 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. -.Sp -2. Choose option \f(CW\*(C`\-\-disable\-citation\-markup\*(C'\fR 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 -.SH "BUGS" -.IX Header "BUGS" -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. -.PP -Please send bug reports -to \fItilmann@gfz\-potsdam.de\fR or submit on latexdiff project page \fIhttp://developer.berlios.de/projects/latexdiff/\fR. Include the serial number of \fIlatexdiff\fR -(from comments at the top of the source or use \fB\-\-version\fR). 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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexrevise, latexdiff-vc -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff\fR does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than \s-1ASCII\s0 or \s-1UTF\-8\s0 are processed, Perl 5.8 or higher is required. -.PP -The standard version of \fIlatexdiff\fR requires installation of the Perl package -\&\f(CW\*(C`Algorithm::Diff\*(C'\fR (available from \fIwww.cpan.org\fR \- -\&\fIhttp://search.cpan.org/~nedkonz/Algorithm\-Diff\-1.15\fR) but a stand-alone -version, \fIlatexdiff-so\fR, which has this package inlined, is available, too. -\&\fIlatexdiff-fast\fR requires the \fIdiff\fR command to be present. -.SH "AUTHOR" -.IX Header "AUTHOR" -Copyright (C) 2004\-2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -.PP -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. -.SH "POD ERRORS" -.IX Header "POD ERRORS" -Hey! \fBThe above document had some coding errors, which are explained below:\fR -.IP "Around line 2941:" 4 -.IX Item "Around line 2941:" -=over should be: '=over' or '=over positive_number' -.Sp -You can't have =items (as at line 2947) unless the first thing after the =over is an =item diff --git a/latexdiff-1.0.1/latexrevise b/latexdiff-1.0.1/latexrevise deleted file mode 100755 index bf3ec83..0000000 --- a/latexdiff-1.0.1/latexrevise +++ /dev/null @@ -1,527 +0,0 @@ -#!/usr/bin/env/perl -# latexrevise - takes output file of latexdiff and removes either discarded -# or appended passages, then deletes all other latexdiff markup -# -# Copyright (C) 2004 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# Note: version number now keeping up with latexdiff -# Version 1.0.1 no changes to latexrevise -# Version 0.3 Updated for compatibility with latexdiff 0.3 output (DIFAUXCMD removal) -# Version 0.1 First public release - -use Getopt::Long ; -use strict; -use warnings; - -# Markup strings (make sure that this are set to the same value as in -# latexdiff) -# If at all possible, do not change these as parts of the program -# depend on the actual name. -# At the very least adapt subroutine postprocess to new tokens. - -# note: have to use three backslashes to mean one literal one (reason -# unknown -my $ADDMARKOPEN='\\\DIFaddbegin(?:FL)? '; # Token to mark begin of appended text -my $ADDMARKCLOSE='\\\DIFaddend(?:FL)?(?: |\z)'; # Token to mark end of appended text (|\z only deals with the case of \DIFaddend right before \end{document} -my $ADDOPEN='\\\DIFadd(?:FL)?{'; # To mark begin of added text passage -my $ADDCLOSE='}'; # To mark end of added text passage -my $ADDCOMMENT='DIF > '; # To mark added comment line -my $DELMARKOPEN='\\\DIFdelbegin(?:FL)? '; # Token to mark begin of deleted text -my $DELMARKCLOSE='\\\DIFdelend(?:FL)?(?: |\z)'; # Token to mark end of deleted text -my $DELOPEN='\\\DIFdel(?:FL)?{'; # To mark begin of deleted text passage -my $DELCLOSE='}'; # To mark end of deleted text passage -my $ALTEXT='FL'; # string which might be appended to above commands -my $DELCMDOPEN='%DIFDELCMD < '; # To mark begin of deleted commands (must begin with %, i.e., be a comment -my $DELCMDCLOSE="%%%\n"; # To mark end of deleted commands (must end with a new line) -my $AUXCMD='%DIFAUXCMD' ; # follows auxiliary commands put in by latexdiff to make difference file legal -my $DELCOMMENT='DIF < '; # To mark deleted comment line - -my $PREAMBLEXTBEG='^%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF$'; -my $PREAMBLEXTEND='^%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF$'; - - -my $pat0 = '(?:[^{}]|\\\{|\\\})*'; -my $pat1 = '(?:[^{}]|\\\{|\\\}|\{'.$pat0.'\})*'; -my $pat2 = '(?:[^{}]|\\\{|\\\}|\{'.$pat1.'\})*'; -my $pat3 = '(?:[^{}]|\\\{|\\\}|\{'.$pat2.'\})*'; -my $pat4 = '(?:[^{}]|\\\{|\\\}|\{'.$pat3.'\})*'; -my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - -my ($input,$preamble,$body,$post); -my (@matches); -my ($cnt,$prematch,$postmatch); -my ($help); -my ($verbose,$quiet,$accept,$decline,$simplify)=(0,0,0,0,0); -my ($comment,$comenv,$markup,$markenv); - -# A word unlikely ever to be used in a real latex file -my $someword='gobbledegooksygook'; - -Getopt::Long::Configure('bundling'); -GetOptions('accept|a' => \$accept, - 'decline|d'=> \$decline, - 'simplify|s' => \$simplify, - 'comment|c=s' => \$comment, - 'comment-environment|e=s' => \$comenv, - 'markup|m=s' => \$markup, - 'markup-environment|n=s' => \$markenv, - 'no-warnings|q' => \$verbose, - 'verbose|V' => \$verbose, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - -if ( ($accept && $decline) || ($accept && $simplify) || ($decline && $simplify) ) { - die '-a,-d and -s options are mutually axclusive. Type latexrevise -h to get more help.'; -} - - - -print STDERR "ACCEPT mode\n" if $verbose && $accept; -print STDERR "DECLINE mode\n" if $verbose && $decline; -print STDERR "SIMPLIFY mode. WARNING: The output will not normally be valid latex,\n" if $verbose && $simplify; - -# Slurp old and new files -{ - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $input=<>; -} - -# split into parts -($preamble,$body,$post)=splitdoc($input,'\begin{document}','\end{document}'); - -if (length $preamble && ( $accept || $decline ) ) { - # - # WORK ON PREAMBLE - # - # (compare subroutine linediff in latexdiff to make sure correct strings are used) - - # remove extra commands added to preamble by latexdiff - $preamble =~ s/${PREAMBLEXTBEG}.*?${PREAMBLEXTEND}\n{0,1}//smg ; - - if ( $accept ) { - # delete mark up in appended lines - $preamble =~ s/^(.*) %DIF > $/$1/mg ; - } elsif ( $decline ) { - # delete appended lines - # $preamble =~ s/^(.*) %DIF > $//mg ; - $preamble =~ s/^(.*) %DIF > \n//mg ; - # delete markup in deleted lines - $preamble =~ s/^%DIF < //mg ; - } - # remove any remaining DIF markups - #$preamble =~ s/%DIF.*$//mg ; - $preamble =~ s/%DIF.*?\n//sg ; -} -#print $preamble ; - -# -# WORK ON BODY -# -if ($accept) { - # remove ADDMARKOPEN, ADDMARKCLOSE tokens - @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/$1/sg; - # remove text flanked by DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}//sg; - # remove markup of added comments - $body =~ s/%${ADDCOMMENT}(.*?)$/%$1/mg ; - # remove deleted comments (full line) - $body =~ s/^%${DELCOMMENT}.*?\n//mg ; - # remove deleted comments (part of line) - $body =~ s/%${DELCOMMENT}.*?$//mg ; -} -elsif ( $decline) { - # remove DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/$1/sg; - # remove text flanked by ADDMARKOPEN, ADDMARKCLOSE tokens - # as latexdiff algorithm keeps the formatting and white spaces - # of the new text, sometimes whitespace might be inserted or - # removed inappropriately. We try to guess whether this has - # happened - - # Mop up tokens. This must be done already now as otherwise - # detection of white-space problems does not work - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - # remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - $cnt += $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - while ( $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/s ) { - $prematch=$`; - $postmatch=$'; - checkpure($1); - if ( $prematch =~ /\w$/s && $postmatch =~ /^\w/ ) { - # apparently no white-space between word=>Insert white space - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/ /s ; - } - elsif ( $prematch =~ /\s$/s && $postmatch =~ /^[.,;:]/ ) { - # space immediately before one of ".,:;" => remove this space - $body =~ s/\s${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s ; - } - else { - # do not insert or remove any extras - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s; - } - } -# Alternative without special cases treatment -# @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; -# checkpure(@matches); -# $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//sg; - # remove markup of deleted comments - $body =~ s/%${DELCOMMENT}(.*?)$/%$1/mg ; - # remove added comments (full line) - $body =~ s/^%${ADDCOMMENT}.*?\n//mg ; - # remove added comments (part of line) - $body =~ s/%${ADDCOMMENT}.*?$//mg ; -} - -# remove any remaining tokens -if ( $accept || $decline || $simplify ) { - # first substitution command deals with special case of added paragraph - $cnt = $body =~ s/${ADDOPEN}($pat4)\n${ADDCLOSE}\n/$1\n/sg; - $cnt += $body =~ s/${ADDOPEN}($pat4)${ADDCLOSE}/$1/sg; - $cnt==0 || warn 'Remaining $ADDOPEN tokens in DECLINE mode\n' unless ( $quiet || $accept || $simplify ); -} -if ($accept || $simplify ) { - # Note: in decline mode these commands have already been removed above - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - #### remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - # $cnt += - $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - #### remove deleted comments - ###$cnt += $body =~ s/${DIFDELCMD}.*?$//mg ; - $cnt==0 || warn 'Remaining $DELOPEN or $DIFDELCMD tokens in ACCEPT mode\n' unless ( $quiet || $simplify ); -} - -# Remove comment commands -if (defined($comment)) { - print STDERR "Removing \\$comment\{..\} sequences ..." if $verbose; - # protect $comments in comments by making them look different - $body =~ s/(%.*)${comment}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${comment}(?:\[${brat0}\])?\{${pat4}\}//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${comment}$2/mg ; -} -if (defined($comenv)) { - print STDERR "Removing $comenv environments ..." if $verbose; - $body =~ s/(%.*)${comenv}/$1${someword}/mg ; -## $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{\$comenv\}.*?\\end\{\$comenv\}//sg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${comenv}\}.*?\\end\{${comenv}\}\s*?\n//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${comenv}/mg ; -} - -if (defined($markup)) { - print STDERR "Removing \\$markup\{..\} cpmmands ..." if $verbose; - # protect $markups in comments by making them look different - $body =~ s/(%.*)${markup}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${markup}(?:\[${brat0}\])?\{(${pat4})\}/$1/sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${markup}$2/mg ; -} -if (defined($markenv)) { - print STDERR "Removing $markenv environments ..." if $verbose; - $body =~ s/(%.*)${markenv}/$1${someword}/mg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${markenv}\}\n?//sg; - $cnt += 0 + $body =~ s/\\end\{${markenv}\}\n?//sg; - print STDERR $cnt/2, " matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${markenv}/mg ; -} - - -if ( length $preamble ) { - print "$preamble\\begin{document}${body}\\end{document}$post"; -} else { - print $body; -} - -# checkpure(@matches) -# checks whether any of the strings in matches contains -# $ADDMARKOPEN, $ADDMARKCLOSE,$DELMARKOPEN, or $DELMARKCLOSE -# If so, die reporting nesting problems, otherwise return to caller -sub checkpure { - while (defined($_=shift)) { - if ( /$ADDMARKOPEN/ || /$ADDMARKCLOSE/ - || /$DELMARKOPEN/ || /$DELMARKCLOSE/ ) { - die <=0 && $j>$i ) { - $part1 = substr($text,0,$i) ; - $part2 = substr($text,$i+$l1,$j-$i-$l1); - $part3 = substr($text,$j+$l2) unless $j+$l2 >= length $text; - } else { - die "$word1 or $word2 not in the correct order or not present as a pair." - } - return ($part1,$part2,$part3); -} - - - -sub usage { - die <<"EOF"; -Usage: $0 [OPTIONS] [diff.tex] > revised.tex - -Read a file diff.tex (output of latexdiff), and remove its markup. -If no filename is given read from standard input. The command can be used -in ACCEPT, DECLINE, or SIMPLIFY mode, and be used to remove user-defined -latex commands from the input (see options -c, -e, -m, -n below). -In ACCEPT mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In DECLINE mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that latexrevise only pays attention to the \\DIFaddbegin, -\\DIFaddend, \\DIFdelbegin, and \\DIFdelend tokens and corresponding FL -varieties. All \\DIFadd and \\DIFdel commands (but not their content) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In SIMPLIFY mode all latexdiff markup is removed from the body of the text (after -\\begin{document}) except for \\DIFaddbegin, \\DIFaddend, \\DIFdelbegin, \\DIFdelend -tokens and the corresponding FL varieties of those commands. The result -will not in general be valid latex-code but might be easier to read and edit in -preparation for a subsequent run in ACCEPT or DECLINE mode. -In SIMPLIFY mode the preamble is left unmodified. - --a ---accept Run in ACCEPT mode (delete all blocks marked by \\DIFdelbegin - and \\DIFdelend). - --d ---decline Run in DECLINE mode (delete all blocks marked by \\DIFaddbegin - and \\DIFaddend). - --s ---simplify Run in SIMPLIFY mode (Keep all \\DIFaddbegin, \\DIFaddend, - \\DIFdelbegin, \\DIFdelend tokens, but remove all other latexdiff - markup from body. - -Note that the three mode options are mutually exclusive. If no mode option is given, -latexrevise simply removes user annotations and markup according to the following four -options. - - --c cmd ---comment=cmd Remove \\cmd{...}. cmd is supposed to mark some explicit - anotations which should be removed from the file before - release. - --e envir ---comment-environment=envir - Remove explicit annotation environments from the text, i.e. remove - \\begin{envir} - ... - \\end{envir} - blocks. - --m cmd ---markup=cmd Remove the markup command cmd but leave its argument, i.e. - turn \\cmd{abc} into abc. - --n envir ---markup-environment=envir - Similarly, remove \\begin{envir} and \\end{envir} commands, - but leave content of the environment in the text. - --q ---no-warnings Do not warn users about \\DIDadd{..} or \\DIFdel statements - which should not be there anymore - --V ---verbose Verbose output - -EOF -} - -=head1 NAME - -latexrevise - selectively remove markup and text from latexdiff output - -=head1 SYNOPSIS - -B [ B ] [ F ] > F - -=head1 DESCRIPTION - -I reads a file C (output of I), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in I, I, or I mode, or can be used to remove user-defined -latex commands from the input (see B<-c>, B<-e>, B<-m>, and B<-n> below). -In I mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In I mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that I only pays attention to the C<\DIFaddbegin>, -C<\DIFaddend>, C<\DIFdelbegin>, and C<\DIFdelend> tokens and corresponding FL -varieties. All C<\DIFadd> and C<\DIFdel> commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In I mode, C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend> -tokens and their corresponding C varieties are kept but all other markup (e.g. C and <\DIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in I or I mode. -In I mode the preamble is left unmodified. - -=head1 OPTIONS - -=over 4 - -=item B<-a> or B<--accept> - -Run in I mode (delete all blocks marked by C<\DIFdelbegin> and C<\DIFdelend>). - -=item B<-d> or B<--decline> - -Run in I mode (delete all blocks marked by C<\DIFaddbegin> -and C<\DIFaddend>). - -=item B<-s> or B<--simplify> - -Run in I mode (Keep all C<\DIFaddbegin>, C<\DIFaddend>, -C<\DIFdelbegin>, C<\DIFdelend> tokens, but remove all other latexdiff -markup from body). - -=back - -Note that the three mode options are mutually exclusive. If no mode option is given, -I simply removes user annotations and markup according to the following four -options. - -=over 4 - -=item B<-c cmd> or B<--comment=cmd> - -Remove C<\cmd{...}> sequences. C is supposed to mark some explicit -anotations which should be removed from the file before -release. - -=item B<-e envir> or B<--comment-environment=envir> - -Remove explicit annotation environments from the text, i.e. remove - - \begin{envir} - ... - \end{envir} - -blocks. - -=item B<-m cmd> or B<--markup=cmd> - -Remove the markup command C<\cmd> but leave its argument, i.e. -turn C<\cmd{abc}> into C. - -=item B<-n envir> or B<--markup-environment=envir> - -Similarly, remove C<\begin{envir}> and C<\end{envir}> commands but -leave content of the environment in the text. - - -=item B<-V> or B<--verbose> - -Verbose output - -=item B<-q> or B<--no-warnings> - -Do not warn users about C<\DIDadd{..}> or C<\DIFdel{..}> statements -which should have been removed already. - -=back - -=head1 BUGS - -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by I please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. - -Note that I gets confused by commented C<\begin{document}> or -C<\end{document}> statements - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting PERL v5 or higher. - -=head1 AUTHOR - -Copyright (C) 2004 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 - -=cut diff --git a/latexdiff-1.0.1/latexrevise.1 b/latexdiff-1.0.1/latexrevise.1 deleted file mode 100644 index b44a245..0000000 --- a/latexdiff-1.0.1/latexrevise.1 +++ /dev/null @@ -1,235 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXREVISE 1" -.TH LATEXREVISE 1 "2012-11-13" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexrevise \- selectively remove markup and text from latexdiff output -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexrevise\fR [ \fB\s-1OPTIONS\s0\fR ] [ \fIdiff.tex\fR ] > \fIrevised.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexrevise\fR reads a file \f(CW\*(C`diff.tex\*(C'\fR (output of \fIlatexdiff\fR), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in \fI\s-1ACCEPT\s0\fR, \fI\s-1DECLINE\s0\fR, or \fI\s-1SIMPLIFY\s0\fR mode, or can be used to remove user-defined -latex commands from the input (see \fB\-c\fR, \fB\-e\fR, \fB\-m\fR, and \fB\-n\fR below). -In \fI\s-1ACCEPT\s0\fR mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In \fI\s-1DECLINE\s0\fR mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that \fIlatexrevise\fR only pays attention to the \f(CW\*(C`\eDIFaddbegin\*(C'\fR, -\&\f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR, and \f(CW\*(C`\eDIFdelend\*(C'\fR tokens and corresponding \s-1FL\s0 -varieties. All \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In \fI\s-1SIMPLIFY\s0\fR mode, \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR -tokens and their corresponding \f(CW\*(C`FL\*(C'\fR varieties are kept but all other markup (e.g. \f(CW\*(C`DIFadd\*(C'\fR and <\eDIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in \fI\s-1ACCEPT\s0\fR or \fI\s-1DECLINE\s0\fR mode. -In \fI\s-1SIMPLIFY\s0\fR mode the preamble is left unmodified. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-a\fR or \fB\-\-accept\fR" 4 -.IX Item "-a or --accept" -Run in \fI\s-1ACCEPT\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR). -.IP "\fB\-d\fR or \fB\-\-decline\fR" 4 -.IX Item "-d or --decline" -Run in \fI\s-1DECLINE\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR -and \f(CW\*(C`\eDIFaddend\*(C'\fR). -.IP "\fB\-s\fR or \fB\-\-simplify\fR" 4 -.IX Item "-s or --simplify" -Run in \fI\s-1SIMPLIFY\s0\fR mode (Keep all \f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, -\&\f(CW\*(C`\eDIFdelbegin\*(C'\fR, \f(CW\*(C`\eDIFdelend\*(C'\fR tokens, but remove all other latexdiff -markup from body). -.PP -Note that the three mode options are mutually exclusive. If no mode option is given, -\&\fIlatexrevise\fR simply removes user annotations and markup according to the following four -options. -.IP "\fB\-c cmd\fR or \fB\-\-comment=cmd\fR" 4 -.IX Item "-c cmd or --comment=cmd" -Remove \f(CW\*(C`\ecmd{...}\*(C'\fR sequences. \f(CW\*(C`cmd\*(C'\fR is supposed to mark some explicit -anotations which should be removed from the file before -release. -.IP "\fB\-e envir\fR or \fB\-\-comment\-environment=envir\fR" 4 -.IX Item "-e envir or --comment-environment=envir" -Remove explicit annotation environments from the text, i.e. remove -.Sp -.Vb 3 -\& \ebegin{envir} -\& ... -\& \eend{envir} -.Ve -.Sp -blocks. -.IP "\fB\-m cmd\fR or \fB\-\-markup=cmd\fR" 4 -.IX Item "-m cmd or --markup=cmd" -Remove the markup command \f(CW\*(C`\ecmd\*(C'\fR but leave its argument, i.e. -turn \f(CW\*(C`\ecmd{abc}\*(C'\fR into \f(CW\*(C`abc\*(C'\fR. -.IP "\fB\-n envir\fR or \fB\-\-markup\-environment=envir\fR" 4 -.IX Item "-n envir or --markup-environment=envir" -Similarly, remove \f(CW\*(C`\ebegin{envir}\*(C'\fR and \f(CW\*(C`\eend{envir}\*(C'\fR commands but -leave content of the environment in the text. -.IP "\fB\-V\fR or \fB\-\-verbose\fR" 4 -.IX Item "-V or --verbose" -Verbose output -.IP "\fB\-q\fR or \fB\-\-no\-warnings\fR" 4 -.IX Item "-q or --no-warnings" -Do not warn users about \f(CW\*(C`\eDIDadd{..}\*(C'\fR or \f(CW\*(C`\eDIFdel{..}\*(C'\fR statements -which should have been removed already. -.SH "BUGS" -.IX Header "BUGS" -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page \fIhttp://developer.berlios.de/projects/latexdiff/\fR or send -to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexrevise\fR -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by \fIlatexrevise\fR please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. -.PP -Note that \fIlatexrevise\fR gets confused by commented \f(CW\*(C`\ebegin{document}\*(C'\fR or -\&\f(CW\*(C`\eend{document}\*(C'\fR statements -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexrevise\fR does not make use of external commands and thus should run -on any platform supporting \s-1PERL\s0 v5 or higher. -.SH "AUTHOR" -.IX Header "AUTHOR" -Copyright (C) 2004 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 diff --git a/latexdiff-1.0.2/COPYING b/latexdiff-1.0.2/COPYING deleted file mode 100644 index d6fa915..0000000 --- a/latexdiff-1.0.2/COPYING +++ /dev/null @@ -1,623 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - diff --git a/latexdiff-1.0.2/README b/latexdiff-1.0.2/README deleted file mode 100644 index 7c7ff86..0000000 --- a/latexdiff-1.0.2/README +++ /dev/null @@ -1,107 +0,0 @@ -INTRODUCTION - -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -A rudimentary revision facilility is provided by another Perl script, -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). - -Project webpage: http://latexdiff.berlios.de/ -CTAN page: http://www.ctan.org/tex-archive/support/latexdiff - - -REQUIREMENTS - -Perl 5.8 or higher must be installed. - The latexdiff script makes use of the Perl package Algorithm::Diff (available -from www.cpan.org, current version 1.19). You can either install this package, or -use the standalone version of latexdiff, latexdiff-so, which has version 1.15 of -this package inlined and does not require external installation of -the package. Because latexdiff uses internal functions of Algorithm:Diff whose -calling format or availability can change without notice, the preferred method is -now to use the standalone version. - -As an alternative, latexdiff-fast has a modified version of Algorithm::Diff inlined, -which internally uses the UNIX diff command. This version is much faster but is dependent -on an external "diff" command. Subtle differences in the algorithm of Algorithm::Diff and -UNIX-diff mean that the resulting set of differences will generally not be the same as -for the standard latexdiff. In most practical cases, these differences are minor, though. - -INSTALLATION UNIX/LINUX - -The basic installation procedure is almost trivial: - -1. Copy latexdiff, latexrevise and latexdiff-vc into a directory which - is in the search path and make them executable. If the Algorithm::Diff - package is not installed, use latexdiff-so instead of latexdiff. - -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. - -The attached Makefile contains example commands to carry out above -steps as root for a typical UNIX installation. Type - - make install (for the stand alone version) -or - make install-ext (for the version using the external Algorithm::Diff) -or - make install-fast (for the version using the UNIX 'diff' function for fast differencing) - -to get it rolling. You can type - - make test -or - make test-ext -or - make test-fast - -to test the respective versions on a brief example before installation - - -DOCUMENTATION: - -Usage instructions are in the manual latexdiff-man.pdf as well as the -man pages. - -CHANGELOGS: - -Check out the comment lines at the beginning of the perl scripts (latexdiff, latexdiff-vc, latexrevise) - -CONTRIBUTIONS - -The directory contrib contains code written by others relating to latexdiff. -Currently this directory contains: - -latexdiff-wrap (Author: V. Kuhlmann) An alternative wrapper script which can be used - instead of latexdiff-vc. Its main use is as a template for customised wrapper scripts. - -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 -extend latexdiff in a similar way: J. Paisley, N. Becker, K. Huebner - -LICENSE (also see file COPYING) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License Version 3 as published by -the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details (file LICENSE in the -distribution). - diff --git a/latexdiff-1.0.2/contrib/README.latexchanges b/latexdiff-1.0.2/contrib/README.latexchanges deleted file mode 100644 index 4a02765..0000000 --- a/latexdiff-1.0.2/contrib/README.latexchanges +++ /dev/null @@ -1,13 +0,0 @@ -latexchanges.py (Jan-Ake Larsson): -Here's a wrapper I wrote for latexdiff, intended as a drop-in -replacement for latex, when you have several numbered (or dated) -versions of a manuscript. My coauthors don't as a rule know what CVS or -SVN is, they simply use a number or date for the different versions. - -latexchanges replaces the current DVI with one that includes a -latexdiff to the last version. The last version is selected as the -TEX file in the same directory with the same prefix (up to a number -or a dot), that has an mtime immediately preceding the given TEX -file. - - diff --git a/latexdiff-1.0.2/contrib/latexchanges.py b/latexdiff-1.0.2/contrib/latexchanges.py deleted file mode 100644 index de7acbe..0000000 --- a/latexdiff-1.0.2/contrib/latexchanges.py +++ /dev/null @@ -1,67 +0,0 @@ -#! /bin/env python -# latexchanges -# -# Wrapper for latexdiff, intended as a drop-in replacement for latex, -# when you have several numbered (or dated) versions of a manuscript. -# My coauthors don't as a rule know what CVS or SVN is, they simply -# use a number or date for the different versions. -# -# latexchanges replaces the current DVI with one that includes a -# latexdiff to the last version. The last version is selected as the -# TEX file in the same directory with the same prefix (up to a number -# or a dot), that has an mtime immediately preceding the given TEX -# file. -# -# (I should probably add CVS version numbering too, at some point.) -# -# Copyright (C) 2009 by Jan-\AA{}ke Larsson -# Released under the terms of the GNU General Public License (GPL) -# Version 2. See http://www.gnu.org/ for details. -# -# Please do provide patches and bug reports, but remember: if it -# breaks, you get to keep the pieces. -# -# Jan-\AA{}ke Larsson -# Sept 16 2009 - -from os import listdir,system,stat -from sys import argv -from re import split - -name="" -newarg=[] - -# Find filename argument -for i in range(1,len(argv)): - if argv[i][-4:]==".tex": - basename=split('[0-9.]',argv[i])[0] - name=argv[i][:-4] - newarg.append(name+".changes.tex") - else: - newarg.append(argv[i]) - -if name: - print "Filename",name+".tex" - print "Prefix is",basename - # Find last archived version - mtime=stat(name+".tex").st_mtime - old_mtime=0 - ls=listdir(".") - for j in ls: - if j.startswith(basename) and j.endswith(".tex")\ - and not j.endswith(".changes.tex"): - tmptime=stat(j).st_mtime - if mtime>tmptime and old_mtime0: - print "Comparing with",oldname - system ("/bin/cp "+name+".aux "+name+".changes.aux") - system ("/bin/cp "+name+".bbl "+name+".changes.bbl") - system ("latexdiff "+oldname+" "+name+".tex > "+name+".changes.tex") - system ("latex "+" ".join(newarg)) - system ("cp "+name+".changes.dvi "+name+".dvi") - else: - system ("latex "+" ".join(argv[1:])) diff --git a/latexdiff-1.0.2/contrib/latexdiff-wrap b/latexdiff-1.0.2/contrib/latexdiff-wrap deleted file mode 100755 index 894b424..0000000 --- a/latexdiff-1.0.2/contrib/latexdiff-wrap +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/bash -# -# latexdiff-wrap -# -# Wrapper for latexdiff, to -# * provide support for documents consiting of more than 1 latex file -# * provide my common arguments -# -# Copyright (C) by Volker Kuhlmann -# Released under the terms of the GNU General Public License (GPL) Version 2. -# See http://www.gnu.org/ for details. -# -# Volker Kuhlmann -# 5, 6, 7, 12, 16, 17 Oct 2005 -# 31 Jan; 5, 7, 13, 15 Feb 2006 -# - -VERSION="0.6, 15 Feb 2006" -AUTHOR="Volker Kuhlmann " -COPYRIGHT="Copyright (C) 2005-2006" - - -#### -#### Constants and initialised variables -# -diffcmd="latexdiff" -diffrc="$HOME/texmf/latexdiff" -#diffargs="-e latin1 --ignore-warnings -p latexdiff-preamble.sty" -diffargs="-e latin1 --ignore-warnings" -diffargs="$diffargs --append-safecmd $diffrc/safe-cmds" -diffargs="$diffargs --append-textcmd $diffrc/text-cmds" -# Note: Can't use multiple --append-safecmd -# show current command lists: -#diffcmd="$diffcmd --show-safecmd --show-textcmd --show-config" - - -#### -#### Version, Usage, Help -# -show_version() { - echo "${0##*/} version $VERSION -$COPYRIGHT by $AUTHOR" -} - -show_usage() { - echo " -Usage: ${0##*/} OLDDIR NEWDIR DIFFDIR [DIFFARGS --] FILE.tex [...] - ${0##*/} --show [DIFFARGS] -Version $VERSION -$COPYRIGHT by $AUTHOR -" -} - -show_help() { - show_usage - echo "\ -For each FILE.tex, build a new file DIFFDIR/FILE.tex with markup of the changes -which were made from OLDDIR/FILE.tex to NEWDIR/FILE.tex. -Any path given with FILE.tex is stripped off. -Any DIFFARGS are added to the latexdiff call, if present (remember to follow -them with a double-hyphen on its own before the FILE arguments). - -With --show, shows the settings latexdiff would be running with, including the -changes applied by the user. -" -} - -# For scripts not using function library only: -Version() { show_version; exitwith ErrVersion; } -Usage() { show_help; exitwith ErrUsage; } -Help() { test "$1" && exitwith ErrHelp show_help; show_help; exitwith ErrOK; } - - -#### -#### Error/Exit codes -# -exitwith() { - exec 1>&2 # write stdout on stderr instead - case "$1" in - ErrOK) - exit 0;; - ErrVersion|ErrUsage|ErrHelp) - # Output generated by function (program) $2, if given - test -n "$2" && "$2" - exit 1;; - # more codes in here - # more codes in here - ErrBadoption) - echo "Bad option '$2'." - echo "Call with -h for help." - exit 9;; - ErrMissingParameter) - echo "A required parameter for option $2 is missing." - echo "Call with -h for help." - exit 9;; - *) - echo "Internal error: exitwith() called with illegal error code '$1'." - exit 19;; - esac -} - - -#### -#### Parse command line parameters -# - -# If the next arg starts with a "-", collect additional argument for latexdiff -# until "--". -scanextraargs() { - addargs=() - case "$1" in -*) - while [ $# -gt 0 -a "$1" != "--" ]; do - addargs=( "${addargs[@]}" "$1" ) - shift - done - test "$1" == "--" && shift - ;; esac - fileargs=( "$@" ) -} - -case "$1" in - --version) Version;; - --usage) Usage;; - --help|-h|-help) Help;; - --show) - shift - scanextraargs "$@" - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - --show-safecmd --show-textcmd --show-config - ) | fmt - exit $? ;; -esac - -olddir="${1%/}" -newdir="${2%/}" -diffdir="${3%/}" - -if ! [ -d "$olddir" -a -d "$newdir" -a -d "$diffdir" ]; then - Help 1>&2 err -fi - -shift 3 - -scanextraargs "$@" -set -- "${fileargs[@]}" - - - -#### -#### Functions -# -#set -x -Log() { echo 1>&2 "+ $@"; "$@"; } - - -#### -#### Main -# - -# Create output directory, just in case. -(set -x -mkdir -p "$diffdir" -) -while [ $# -gt 0 ]; do - file="${1##*/}" - echo Examining: "$file" - # No point running latexdiff if both files are identical, - # but run latexdiff on top-level LaTeX file in any case. - if cmp --quiet "$olddir/$file" "$newdir/$file" \ - && ! grep -lq '\\begin.*{document}' "$newdir/$file"; then - (set -x - cp -p "$olddir/$file" "$diffdir" - ) - else - # Delete file, to make sure it's not clobbered by redirecting stdout - # in case it's a symlink to te original. - test -f "$diffdir/$file" && (set -x - rm "$diffdir/$file" - ) - # Run latexdiff if both input files are present. - run=1 - test -f "$olddir/$file" || { echo 1>&2 "No file: $olddir/$file"; run=; } - test -f "$newdir/$file" || { echo 1>&2 "No file: $newdir/$file"; run=; } - test -n "$run" && \ - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - "$olddir/$file" "$newdir/$file" > "$diffdir/$file" - ) - fi - shift -done diff --git a/latexdiff-1.0.2/contrib/latexdiff.spec b/latexdiff-1.0.2/contrib/latexdiff.spec deleted file mode 100644 index 9255a69..0000000 --- a/latexdiff-1.0.2/contrib/latexdiff.spec +++ /dev/null @@ -1,58 +0,0 @@ -Summary: Diff for LaTeX files -Name: latexdiff -Version: 0.5 -Release: 1 -License: GPL -Group: Productivity/Publishing/TeX/Utilities -URL: http://www.tug.org/tex-archive/help/Catalogue/entries/latexdiff.html -Source0: %{name}.zip -BuildArch: noarch -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -# only required for 'make install-ext' -# Requires: perl-Algorithm-Diff - - -%description -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -(C) 2004 Frederik Tilmann - - -%prep -%setup -n %{name} - - -%build -# quick had to adapt the Makefile -%{__mv} Makefile Makefile.old -%{__sed} \ - -e "s;INSTALLPATH = /usr/local;INSTALLPATH = \${DESTDIR}%{_prefix};" \ - -e "s;INSTALLMANPATH = \$(INSTALLPATH)/man;INSTALLMANPATH = \${DESTDIR}%{_mandir};" \ - Makefile.old > Makefile - - -%install -%{__mkdir_p} $RPM_BUILD_ROOT%{_bindir} -%{__mkdir_p} $RPM_BUILD_ROOT%{_mandir}/man1 - -%makeinstall - - -%clean -[ "${RPM_BUILD_ROOT}" != "/" ] && [ -d "${RPM_BUILD_ROOT}" ] && %{__rm} -rf "${RPM_BUILD_ROOT}" - - -%files -%defattr(-,root,root) -%doc example CHANGES LICENSE README -%{_bindir}/* -%{_mandir}/man*/* - -%changelog -* Thu Jan 4 2007 Till Dörges - 0.5-1 -- Initial build. diff --git a/latexdiff-1.0.2/doc/example-diff.tex b/latexdiff-1.0.2/doc/example-diff.tex deleted file mode 100644 index 149588d..0000000 --- a/latexdiff-1.0.2/doc/example-diff.tex +++ /dev/null @@ -1,89 +0,0 @@ -\documentclass[12pt,a4paper]{article} -%DIF LATEXDIFF DIFFERENCE FILE -%DIF DEL example-draft.tex Sat Nov 17 00:45:22 2012 -%DIF ADD example-rev.tex Sat Nov 17 00:45:22 2012 - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -\title{latexdiff Example - \DIFdelbegin \DIFdel{Draft }\DIFdelend \DIFaddbegin \DIFadd{Revised }\DIFaddend version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of \DIFaddbegin \DIFadd{the }\DIFaddend latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{\DIFdelbegin \DIFdel{Another }\DIFdelend \DIFaddbegin \DIFadd{Yet another }\DIFaddend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft document. }\DIFdelend More things could be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised document. }\DIFaddend More things could be -said were it not for the constraints of time and space. - -And here is a \DIFdelbegin \DIFdel{tipo}\DIFdelend \DIFaddbegin \DIFadd{typo}\DIFaddend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFdelbegin \DIFdel{Grey }\DIFdelend \DIFaddbegin \DIFadd{White }\DIFaddend \\ -Saruman & \DIFdelbegin \DIFdel{White -}\DIFdelend \DIFaddbegin \DIFadd{Evil -}\DIFaddend \end{tabular} - -And \DIFdelbegin \DIFdel{sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend \DIFaddbegin \DIFadd{now for something completely different, with not a paragraph in sight}\DIFaddend . -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.2/doc/latexdiff-man.tex b/latexdiff-1.0.2/doc/latexdiff-man.tex deleted file mode 100644 index b6bb37e..0000000 --- a/latexdiff-1.0.2/doc/latexdiff-man.tex +++ /dev/null @@ -1,355 +0,0 @@ -\documentclass[a4]{article} -\usepackage{graphicx} -%\def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -%\def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -\setlength{\parindent}{0pt} -%\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}} -\date{\today} - -\begin{document} -\maketitle - -\section*{Preamble} - -{\em latexdiff} is a Perl script, which compares two -latex files and marks up significant differences between them. Various options are available for visual markup using standard -latex packages such as {\em color.sty}. Changes not directly affecting visible -text, for example in formatting commands, are still marked in the -latex source. - -A rudimentary revision facilility is provided by another Perl script, -{\em 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. - -There is no explicit support for annotations as these are trivial to implement. -For example, I include the following command definition in the preamble -\begin{verbatim} -\newcommand{\remark}[1]{{ \bf [ \footnotesize #1 ]}} -\end{verbatim} -and mark up annotations as follows -\begin{verbatim} -... The roadrunner is the fastest running bird \remark{Check this -again with a zoologist!}. The most famous roadrunner ... -\end{verbatim} -Alternatively, instead of a command like \verb#\remark# in the example just given, an -equivalent annotation environment could be defined. -{\em latexrevise} can remove such comments or -environments from the text body. - -%It is planned that the revision capabilities of this system will be -%further expanded, dependent on the amount of feedback received. - -On the following pages you find the {\em man} pages for {\em - latexdiff} and {\em latexrevise} and a simple example. - -\include{latexdiff} -\setcounter{section}{0} - -\include{latexrevise} -\setcounter{section}{0} - -\include{latexdiff-vc} -\setcounter{section}{0} - -\section*{A simple example} - -We start with a draft text, \verb|example-draft.tex|, listed here in -full but also included in the distribution (except that the ``verbatim'' environment had -to be renamed to ``Verbatim'' for the listing). - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. Of course, instead of \verb|xpdf| you can use -\verb|okular, evince, acroread| or any other pdf or postscript viewer. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things -could be said were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} -\end{verbatim} -} - -We can now edit -this text as we would do with any other latex file to create -a new revision of the text, \verb|example-rev.tex|. We should run -\begin{verbatim} -latex example-rev.tex -\end{verbatim} -and look at the resulting \verb|.dvi| file to make sure that all -changes are valid. An example revision is listed here: - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. -More things could be said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} -\end{verbatim} -} - -To compare both revisions, type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -This results in the following difference file (a few newlines have been -added in this listing for legibility reasosn): -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -%DIF 9c9 -%DIF < \title{latexdiff Example - Draft version} -%DIF ------- -\title{latexdiff Example - Revised version} %DIF > -%DIF ------- -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\color{blue}\uline{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{\DIFaddbegin \DIFadd{Yet another }\DIFaddend \DIFdelbegin -\DIFdel{Another }\DIFdelend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft - document. }\DIFdelend More things could - be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised - document. }\DIFaddend More things could be said -were it not for the constraints of time and space. - -And here is a \DIFaddbegin \DIFadd{typo}\DIFaddend \DIFdelbegin -\DIFdel{tipo}\DIFdelend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFaddbegin \DIFadd{White }\DIFaddend \DIFdelbegin -\DIFdel{Grey }\DIFdelend \\ -Saruman & \DIFaddbegin \DIFadd{Evil -}\DIFaddend \DIFdelbegin \DIFdel{White -}\DIFdelend \end{tabular} - -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -No change, -no markup! -\end{document} -\end{verbatim} -} -Type -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -to make the markup visible. This is what it looks like: - -\vspace{1cm} -\framebox[\textwidth]{\includegraphics[width=\textwidth]{example-diff}} -\vspace{1cm} - -If you approve of all the changes in the revision, just continue with -\verb|example-rev.tex| for the next revision. If you like to adopt -most but not all changes you can use \verb|latexrevise| in the -following manner. Simply remove the \verb|\DIFdelbegin| and -\verb|\DIFdelend| tags around the text you would like to keep and -simply remove the text between \verb|\DIFaddbegin| and -\verb|\DIFaddend| tags, if you do not wish to keep them. Say you are happy with all proposed changes for the -example above except in -the last paragraph where you prefer the original draft. You have -to change - -{\scriptsize -\begin{verbatim} -... -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -... -\end{verbatim} -} -into -{\scriptsize -\begin{verbatim} -... -And \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}. -... -\end{verbatim} -} -and run -\begin{verbatim} -latexrevise -a example-rev.tex > example-final.tex -\end{verbatim} -\verb|example-final.tex| is then almost identical to -\verb|example-rev.tex| except for the last paragraph. -\end{document} diff --git a/latexdiff-1.0.2/example/example-draft.tex b/latexdiff-1.0.2/example/example-draft.tex deleted file mode 100644 index 593a170..0000000 --- a/latexdiff-1.0.2/example/example-draft.tex +++ /dev/null @@ -1,59 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things could be said -were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} - - diff --git a/latexdiff-1.0.2/example/example-rev.tex b/latexdiff-1.0.2/example/example-rev.tex deleted file mode 100644 index 4bcaf15..0000000 --- a/latexdiff-1.0.2/example/example-rev.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. More things could be -said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.2/latexdiff b/latexdiff-1.0.2/latexdiff deleted file mode 100755 index 7075561..0000000 --- a/latexdiff-1.0.2/latexdiff +++ /dev/null @@ -1,3400 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -use Algorithm::Diff qw(traverse_sequences); - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.2/latexdiff-fast b/latexdiff-1.0.2/latexdiff-fast deleted file mode 100755 index 310ecc4..0000000 --- a/latexdiff-1.0.2/latexdiff-fast +++ /dev/null @@ -1,3961 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for differenceing -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that subroutine _longestCommonSubsequence has been replace by -# a routine which internally uses the UNIX diff command for -# the differencing rather than the Perl routines if the -# length of the sequences exceeds some threshold. -# Also, all POD documentation has been stripped out. -# -# (the distribution on which this modification is based is available -# from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The fast-differencing version of latexdiff is provided as a convenience -# for latex users under Unix-like systems which have a 'diff' command. -# If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -# Jonathan Paisley is acknowledged for the idea of using the system diff -# command to achieve shorter running times -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d fast', (q$Revision: 1.15 $ =~ /\d+/g)); - -# Global parameters - -use File::Temp qw/tempfile/; -# if larger number of elements in longestCommonSubsequence smaller than -# this number, then use internal algorithm, otherwise use UNIX diff -use constant THRESHOLD => 100 ; -# Detect whether diff --minimal option is available -# if yes we use it -use constant MINIMAL => ( system('diff','--minimal','/dev/null','/dev/null') >> 8 ==0 ? "--minimal" : "" ) ; - - - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # Check whether to use internal routine (small number of elements) - # or use it as a wrapper for UNIX diff - if ( ( $#$a > $#$b ? $#$a : $#$b) < THRESHOLD ) { - ### print STDERR "DEBUG: regular longestCommonSubsequence\n"; - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - } - else { - my ($fha,$fhb,$fna,$fnb,$ele,$key); - my ($alines,$blines,$alb,$alf,$blb,$blf); - my ($minimal)=MINIMAL; - # large number of elements, use system diff - ### print STDERR "DEBUG: fast (diff) longestCommonSubsequence\n"; - - ($fha,$fna)=tempfile("DiffA-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence A"; - ($fhb,$fnb)=tempfile("DiffB-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence B"; - # prepare sequence A - foreach $ele ( @$a ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fha "$key\n" ; - } - close($fha); - # prepare sequence B - foreach $ele ( @$b ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fhb "$key\n" ; - } - close($fhb); - - open(DIFFPIPE, "diff $minimal $fna $fnb |") or die "_longestCommonSubsequence: Cannot launch diff process. $!" ; - # The diff line numbering begins with 1, but Perl subscripts start with 0 - # We follow the diff numbering but substract 1 when assigning to matchVector - $aStart++; $bStart++ ; $aFinish++ ; $bFinish++ ; - while( ) { - if ( ($alines,$blines) = ( m/^(\d*(?:,\d*)?)?c(\d*(?:,\d*)?)?$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - ($blb,$blf)=split(/,/,$blines); - $alf=$alb unless defined($alf); - $blf=$blb unless defined($blf); - while($aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - # check for consistency - $bStart==$blb or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in changed sequence"; - $aStart=$alf+1; - $bStart=$blf+1; - } - elsif ( ($alb,$blines) = ( m/^(\d*)a(\d*(?:,\d*)?)$/ ) ) { - ($blb,$blf)=split(/,/,$blines); - $blf=$blb unless defined($blf); - while ( $bStart < $blb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $aStart==$alb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in appended sequence near elements $aStart and $bStart"; - $bStart=$blf+1; - } - elsif ( ($alines,$blb) = ( m/^(\d*(?:,\d*)?)d(\d*)$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - $alf=$alb unless defined($alf); - while ( $aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$blb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in deleted sequence near elements $aStart and $bStart"; - $aStart=$alf+1; - } - elsif ( m/^Binary files/ ) { - # if diff reports it is a binary file force --text mode. I do not like - # to always use this option because it is probably only available in GNU diff - open(DIFFPIPE, "diff --text $fna $fnb |") or die "Cannot launch diff process. $!" ; - } - # Default: just skip line - } - while ($aStart <= $aFinish ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$bFinish+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency at end"; - close DIFFPIPE; - # check whether a system error has occurred or return status is greater than or equal to 5 - if ( $! || ($? >> 8) > 5) { - print STDERR "diff process failed with exit code ", ($? >> 8), " $!\n"; - die; - } - unlink $fna,$fnb ; - } - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.2/latexdiff-so b/latexdiff-1.0.2/latexdiff-so deleted file mode 100755 index 865fc48..0000000 --- a/latexdiff-1.0.2/latexdiff-so +++ /dev/null @@ -1,3857 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for stand-alone version replaces -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that all POD documentation has been stripped out. -# I encourage you to download and install the Algorithm::Diff -# package and use the standard latexdiff version instead -# (current distribution available from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The stand-alone version of latexdiff is provided as a convenience -# for latex users with no knowledge of PERL who do not wish to install -# additional packages to be able to use latexdiff. If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d so', (q$Revision: 1.15 $ =~ /\d+/g)); - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$brat0.'\]|\{'. $pat6 . '\}|\(' . $coords .'\))'.$extraspace.')*'; - my $backslashnl='\\\\\n'; - my $oneletcmd='\\\\.\*?(?:\['.$brat0.'\]|\{'. $pat6 . '\})*'; - my $math='\$(?:[^$]|\\\$)*?\$|\\\\[(].*?\\\\[)]'; -## 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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 2. mark all first empty line (in block of several) with \PAR tokens -# 3. Convert all '\%' into '\PERCENTAGE ' to make parsing regular expressions easier -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.2/latexdiff-vc b/latexdiff-1.0.2/latexdiff-vc deleted file mode 100755 index 16b0dea..0000000 --- a/latexdiff-1.0.2/latexdiff-vc +++ /dev/null @@ -1,490 +0,0 @@ -#!/usr/bin/env perl -# -# latexdiff-vc - wrapper script for applying latexdiff to rcs managed files -# and for automatised creation of postscript or pdf from difference file -# -# Copyright (C) 2005-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# -# Contributors: S Utcke, H Bruyninckx -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# version 1.0.2: - option --so to use latexdiff-so -# version 1.0.1 (change version numbering to match that of latexdiff) -# - Option --fast to use latexdiff-fast, -# - git support (thanks to Bjørn Magnus Mathisen, Santi Béjar, Pietro Battiston and Stefan Alfredson for patches) - UNTESTED -# version 0.25: -# - bbl is allowed as alternative extension (instead of .tex) -# version 0.26a -# - Bug fix: it copes now correctly with the possibility that there are no changes between current -# and archived version -use Getopt::Long ; -use Pod::Usage qw/pod2usage/ ; -use File::Temp qw/tempdir/ ; -use File::Basename qw/dirname/; -use strict ; -use warnings ; - -my $versionstring=< 1); -# Variables -my ($file1,$file2,$diff,$diffbase,$answer,$options,$infile,$append,$dirname,$cwd); -my (@files,@ldoptions,@tmpfiles,@ptmpfiles,@difffiles); # , - -Getopt::Long::Configure('pass_through','bundling'); - -GetOptions('revision|r:s' => \@revs, - 'cvs' => \$cvs, - 'rcs' => \$rcs, - 'svn' => \$svn, - 'git' => \$git, - 'dir|d:s' => \$dir, - 'fast' => \$fast, - 'so' => \$so, - 'postscript|ps' => \$postscript, - 'pdf' => \$pdf, - 'force' => \$force, - 'version' => \$version, - 'help|h' => \$help); - -if ( $help ) { - pod2usage(1) ; -} - -if ( $version ) { - die $versionstring ; -} - -if ( $so ) { - $latexdiff='latexdiff-so'; -} -if ( $fast ) { - die "Cannot specify more than one of --fast or --so " if ($so); - $latexdiff='latexdiff-fast'; -} - -if ( $cvs ) { - $vc="CVS"; -} -if ( $rcs ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="RCS"; -} -if ( $svn ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="SVN"; -} -if ( $git ) { - die "Cannot specify more than one of --cvs, --rcs, --svn or --git." if ($vc); - $vc="GIT"; -} - - -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -r option -if ( @revs && ( -f $revs[$#revs] || $revs[$#revs] =~ /^-/ ) ) { - unshift @ARGV,$revs[$#revs]; - $revs[$#revs]=""; -} -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -d option -if ( defined($dir) && ( -f $dir || $dir =~ /^-/ ) ) { - unshift @ARGV,$dir; - $dir=""; -} - -#print "DEBUG: latexdiff-vc command line: ", join(" ",@ARGV), "\n"; - -$file2=pop @ARGV; -( defined($file2) && $file2 =~ /\.(tex|bbl)$/ ) or pod2usage("Must specify at least one tex or bbl file"); - -if (! $vc && scalar(@revs)>0 ) { - # have to guess $vc - # check whether we have a special name - if ( $0 =~ /-cvs$/ ) { - $vc="CVS"; - } elsif ( $0 =~ /-rcs$/ ) { - $vc="RCS"; - } elsif ( $0 =~ /-svn$/ ) { - $vc="SVN"; - } elsif ( $0 =~ /-git$/ ) { - $vc="GIT"; - } elsif ( -e "CVSROOT" || defined($ENV{"CVSROOT"}) ) { - print STDERR "Guess you are using CVS ...\n"; - $vc="CVS"; - } elsif ( -e "$file2,v" ) { - print STDERR "Guess you are using RCS ...\n"; - $vc="RCS"; - } elsif ( -d ".svn" ) { - print STDERR "Guess you are using SVN ...\n"; - $vc="SVN"; - } elsif ( -d ".git" ) { - print STDERR "Guess you are using GIT ...\n"; - $vc="GIT"; - } else { - print STDERR "Cannot figure out version control system, so I default to CVS\n"; - $vc="CVS"; - } -} - -if (defined($dir) && $dir=~/^\.\/?/ ) { - print STDERR "You wrote -dir=. but you do not really like to do that, do you ?\n"; - exit 10 -} - -if ( scalar(@revs)>0 ) { - if ( $vc eq "CVS" ) { - $diffcmd = "cvs diff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "RCS" ) { - $diffcmd = "rcsdiff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "SVN" ) { - $diffcmd = "svn diff -r "; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "GIT" ) { - $diffcmd = "git diff -r --relative --no-prefix "; - $patchcmd = "patch -R -p0"; - # alternatively: - # $diffcmd = "git diff "; - # $patchcmd = "patch -R -p1"; - } else { - print STDERR "Unknown versioning system $vc \n"; - exit 10; - } -} - - -# make file list (last arguments), initial arguments have to be passed to latexdiff -# We assume an argument is a valid file rather than a latexdiff argument -# if it has extension .tex or .bbl - -@files=($file2); -while( $file1=pop @ARGV ) { - if ( $file1 =~ /\.(tex|bbl)$/ ) { - # $file1 looks like a valid file name and is prepended to file list - unshift @files, $file1 ; - } else { - # $file1 looks like an option for latexdiff, push it back to argument stack - unshift @ldoptions, $file1 ; - } -} - -if ( scalar(@revs) == 0 ) { - pod2usage("When -r option is not used, two .tex files (old and new) must be given on the command line") unless @files==2; - # compare two files - $file1=shift @files ; -} - -if ( scalar(@revs) == 2 ) { - $append = "-diff$revs[0]-$revs[1]"; -} elsif ( scalar(@revs) == 1 || $revs[0] ) { - $append = "-diff$revs[0]"; -} else { - $append = "-diff"; -} - -if ( defined ($dir) && ! $dir ) { - # bare -d option => choose directory name - ($dir=$append) =~ s/^-//; -} - -if ( ($vc eq "SVN" || $vc eq "CVS") && scalar(@revs)) { - length($revs[$#revs]) > 0 or $revs[$#revs]="HEAD"; - length($revs[0]) > 0 or $revs[0]="HEAD"; -} - -#exit ; - - -# cycle through all files - -@difffiles=(); -while ( $infile=$file2=shift @files ) { - print STDERR "Working on $infile \n"; - if ( scalar(@revs) == 1 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - push @tmpfiles,$file1; - # compare file with previous version ($revs[0]="") or specified version - ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - # no differences detected, i.e. file is equal to current version - system("\cp $infile $file1"); - } - } elsif ( scalar(@revs) == 2 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - $file2 =~ s/\.(tex|bbl)/-newtmp-$$.$1/ ; - push @tmpfiles,$file2; - ; - if (system("$diffcmd$revs[1] $infile | $patchcmd -o$file2")==0 and -z $file2 ) { - system("\cp $infile $file2"); - } - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - system("\cp $infile $file1"); - }; - } - - if ( -z $file1 || -z $file2) { - print STDERR "One or both of the files to compare are empty. Possibly something went wrong in the retrieval of older versions. Aborting ...\n" ; - exit(10); - } - - # Get name of difference file - if ( defined($dir) ) { - $diff="$dir/$infile" ; - } else { - ($diff=$infile) =~ s/\.(tex|bbl)$/$append.$1/ ; - } - # make directories if needed - $dirname=dirname($diff) ; - system("mkdir -p $dirname") unless ( -e $dirname ); - - # Remaining options are passed to latexdiff - $options = join(" ",@ldoptions); - - if ( -e $diff && ! $force ) { - print STDERR "OK to overwrite existing file $diff (y/n)? "; - $answer = ; - unless ($answer =~ /^y/i ) { - unlink @tmpfiles; - die "Abort ... " ; - } - } - print "Running $latexdiff\n"; - unless ( system("$latexdiff $options $file1 $file2 > $diff") == 0 ) { - print STDERR "Something went wrong in $latexdiff. Deleting $diff and abort\n" ; unlink $diff ; exit(5) - }; - print "Generated difference file $diff\n"; - - if ( ( $postscript or $pdf ) and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff ) ) ) { - # save filename for later processing if postscript or pdf conversion is requested and either two-file mode was used (scalar(@revs)==0) or the diff file contains documentclass statement (ie. is a root document) - push @difffiles, $diff ; - } - - unlink @tmpfiles; -} - -foreach $diff ( @difffiles ) { - chomp($cwd=(`pwd`)); - if (defined($dir)) { - ( $diff =~ s/$dir\/?// ) ; - chdir $dir ; - } - @ptmpfiles=(); - ( $diffbase=$diff) =~ s/\.(tex)$// ; - - # adapt magically changebar styles to [pdftex] display driver if pdf output was selected - if ( $pdf ) { - system("sed \"s/Package\\[dvips\\]/Package[pdftex]/\" $diff > $diff.tmp$$ ; \\mv $diff.tmp$$ $diff"); - } - print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n"; - - if ( system("grep -q \'^[^%]*\\\\bibliography\' $diff") == 0 ) { - if ( $postscript) { - system("latex --interaction=batchmode $diff; bibtex $diffbase"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } elsif ( $pdf ) { - system("pdflatex --interaction=batchmode $diff; bibtex $diffbase"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } - } - - if ( $postscript ) { - my $dvi="$diffbase.dvi"; - my $ps="$diffbase.ps"; - - system("latex --interaction=batchmode $diff; latex $diff; dvips -o $ps $dvi"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; - print "Generated postscript file $ps\n"; - } - elsif ( $pdf ) { - system("pdflatex --interaction=batchmode $diff; pdflatex $diff"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log"; - } - unlink @ptmpfiles; - chdir $cwd; -} - -# greptex returns 1 if regex is not matched in filename -# 0 if there is a match -sub greptex { - my ($regex,$filename)=@_; - my ($i)=0; - open (FH, $filename) or die("Couldn't open $filename: $!"); - while () { - next if /^\s*%/; # skip comment lines - if ( m/$regex/ ) { - close(FH); - return(0); - } - # only scan 25 lines - $i++; - last if $i>25 ; - } - close(FH); - return(1); -} - - -=head1 NAME - -latexdiff-vc - wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) - -=head1 SYNOPSIS - -B [ F ] [ F ] B<-r> [F] [B<-r> F] F [ F ...] - - or - -B [ F ] [ F ][ B<--postscript> | B<--pdf> ] F F - -=head1 DESCRIPTION - -I is a wrapper script that applies I to a -file, or multiple files under version control (CVS, RCS or SVN), and optionally runs the -sequence of C and C or C commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. - -=head1 OPTIONS - -=over 4 - -=item B<--rcs>, B<--svn>, B<--cvs>, or B<--git> - -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. - -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. - -=item B<-r>, B<-r> F or B<--revision>, B<--revision=>F - -Choose revision (under RCS, CVS, SVN or GIT). One or two B<-r> options can be -specified, and they result in different behaviour: - -=over 4 - -=item B -r F ... - -compares F with the most recent version checked into RCS. - -=item B -r F F ... - -compares F with revision F. - -=item B -r F -r F F ... - -compares revisions F and F of F. - -Multiple files can be specified for all of the above options. All files must have the -extension C<.tex>, though. - -=item B F F - -compares two files. - -=back - -The name of the difference file is generated automatically and -reported to stdout. - -=item B<-d> or B<--dir> B<-d> F or B<--dir=>F - -Rather than appending the string C and optionally the version -numbers given to the output-file, this will prepend a directory name C -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname F can be specified, which is prepended instead of C. - -=item B<--fast> or B<--so> - -Use C or C, respectively (instead of C). - -=item B<--ps> or B<--postscript> - -Generate postscript output from difference file. This will run the -sequence C on the difference file (do not use -this option in the rare cases, where three C commands are -required if you care about correct referencing). If the difference -file contains a C<\bibliography> tag, run the sequence C. - -=item B<--pdf> - -Generate pdf output from difference file using C. This will -run the sequence C on the difference file, or -C for files requiring bibtex. - -=item B<--force> - -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - -All other options are passed on to C. - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I uses external commands and is therefore -limited to Unix-like systems. It also requires the RCS version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. - -=head1 BUG REPORTING - - Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(option C<--version>) -. -=head1 AUTHOR - -Copyright (C) 2005,2012 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 -Contributors: S Utcke, H Bruyninckx - -=cut - diff --git a/latexdiff-1.0.2/latexdiff-vc.1 b/latexdiff-1.0.2/latexdiff-vc.1 deleted file mode 100644 index 497b8fe..0000000 --- a/latexdiff-1.0.2/latexdiff-vc.1 +++ /dev/null @@ -1,246 +0,0 @@ -.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF-VC 1" -.TH LATEXDIFF-VC 1 "2012-12-16" "perl v5.12.4" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff\-vc \- wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ] \fB\-r\fR [\fIrev1\fR] [\fB\-r\fR \fIrev2\fR] \fIfile1.tex\fR [ \fIfile2.tex\fR ...] -.PP -.Vb 1 -\& or -.Ve -.PP -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ][ \fB\-\-postscript\fR | \fB\-\-pdf\fR ] \fIold.tex\fR \fInew.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexdiff-vc\fR is a wrapper script that applies \fIlatexdiff\fR to a -file, or multiple files under version control (\s-1CVS\s0, \s-1RCS\s0 or \s-1SVN\s0), and optionally runs the -sequence of \f(CW\*(C`latex\*(C'\fR and \f(CW\*(C`dvips\*(C'\fR or \f(CW\*(C`pdflatex\*(C'\fR commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-\-rcs\fR, \fB\-\-svn\fR, \fB\-\-cvs\fR, or \fB\-\-git\fR" 4 -.IX Item "--rcs, --svn, --cvs, or --git" -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. -.Sp -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. -.IP "\fB\-r\fR, \fB\-r\fR \fIrev\fR or \fB\-\-revision\fR, \fB\-\-revision=\fR\fIrev\fR" 4 -.IX Item "-r, -r rev or --revision, --revision=rev" -Choose revision (under \s-1RCS\s0, \s-1CVS\s0, \s-1SVN\s0 or \s-1GIT\s0). One or two \fB\-r\fR options can be -specified, and they result in different behaviour: -.RS 4 -.IP "\fBlatexdiff-vc\fR \-r \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r file.tex ..." -compares \fIfile.tex\fR with the most recent version checked into \s-1RCS\s0. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 file.tex ..." -compares \fIfile.tex\fR with revision \fIrev1\fR. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \-r \fIrev2\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 -r rev2 file.tex ..." -compares revisions \fIrev1\fR and \fIrev2\fR of \fIfile.tex\fR. -.Sp -Multiple files can be specified for all of the above options. All files must have the -extension \f(CW\*(C`.tex\*(C'\fR, though. -.IP "\fBlatexdiff-vc\fR \fIold.tex\fR \fInew.tex\fR" 4 -.IX Item "latexdiff-vc old.tex new.tex" -compares two files. -.RE -.RS 4 -.Sp -The name of the difference file is generated automatically and -reported to stdout. -.RE -.IP "\fB\-d\fR or \fB\-\-dir\fR \fB\-d\fR \fIpath\fR or \fB\-\-dir=\fR\fIpath\fR" 4 -.IX Item "-d or --dir -d path or --dir=path" -Rather than appending the string \f(CW\*(C`diff\*(C'\fR and optionally the version -numbers given to the output-file, this will prepend a directory name \f(CW\*(C`diff\*(C'\fR -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname \fIpath\fR can be specified, which is prepended instead of \f(CW\*(C`diff\*(C'\fR. -.IP "\fB\-\-fast\fR or \fB\-\-so\fR" 4 -.IX Item "--fast or --so" -Use \f(CW\*(C`latexdiff\-fast\*(C'\fR or \f(CW\*(C`latexdiff\-so\*(C'\fR, respectively (instead of \f(CW\*(C`latexdiff\*(C'\fR). -.IP "\fB\-\-ps\fR or \fB\-\-postscript\fR" 4 -.IX Item "--ps or --postscript" -Generate postscript output from difference file. This will run the -sequence \f(CW\*(C`latex; latex; dvips\*(C'\fR on the difference file (do not use -this option in the rare cases, where three \f(CW\*(C`latex\*(C'\fR commands are -required if you care about correct referencing). If the difference -file contains a \f(CW\*(C`\ebibliography\*(C'\fR tag, run the sequence \f(CW\*(C`latex; -bibtex; latex; latex; dvips\*(C'\fR. -.IP "\fB\-\-pdf\fR" 4 -.IX Item "--pdf" -Generate pdf output from difference file using \f(CW\*(C`pdflatex\*(C'\fR. This will -run the sequence \f(CW\*(C`pdflatex; pdflatex\*(C'\fR on the difference file, or -\&\f(CW\*(C`pdflatex; bibtex; pdflatex; pdflatex\*(C'\fR for files requiring bibtex. -.IP "\fB\-\-force\fR" 4 -.IX Item "--force" -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. -.IP "\fB\-\-help\fR or \fB\-h\fR" 4 -.IX Item "--help or -h" -Show help text -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Show version number -.PP -All other options are passed on to \f(CW\*(C`latexdiff\*(C'\fR. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff-vc\fR uses external commands and is therefore -limited to Unix-like systems. It also requires the \s-1RCS\s0 version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. -.SH "BUG REPORTING" -.IX Header "BUG REPORTING" -.Vb 6 -\& Please submit bug reports through -\&the latexdiff project page I or send -\&to I. Include the serial number of I -\&(option C<\-\-version>) -\&. -\&=head1 AUTHOR -.Ve -.PP -Copyright (C) 2005,2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -Contributors: S Utcke, H Bruyninckx diff --git a/latexdiff-1.0.2/latexdiff.1 b/latexdiff-1.0.2/latexdiff.1 deleted file mode 100644 index 2f075da..0000000 --- a/latexdiff-1.0.2/latexdiff.1 +++ /dev/null @@ -1,758 +0,0 @@ -.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF 1" -.TH LATEXDIFF 1 "2012-12-16" "perl v5.12.4" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff \- determine and markup differences between two latex files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff\fR [ \fB\s-1OPTIONS\s0\fR ] \fIold.tex\fR \fInew.tex\fR > \fIdiff.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Briefly, \fIlatexdiff\fR is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. -.PP -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "\f(CW\*(C`%DIF\ >\*(C'\fR" is appended to each added line, i.e. a -line present in \f(CW\*(C`new.tex\*(C'\fR but not in \f(CW\*(C`old.tex\*(C'\fR. Discarded lines - are deactivated by prepending "\f(CW\*(C`%DIF\ <\*(C'\fR". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file \f(CW\*(C`diff.tex\*(C'\fR will be similar to -\&\f(CW\*(C`new.tex\*(C'\fR. At the end of the preamble, the definitions for \fIlatexdiff\fR markup commands are inserted. -In differencing the main body of the text, \fIlatexdiff\fR attempts to -satisfy the following guidelines (in order of priority): -.IP "1." 3 -If both \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR are valid LaTeX, then the resulting -\&\f(CW\*(C`diff.tex\*(C'\fR should also be valid LateX. (\s-1NB\s0 If a few plain TeX commands -are used within \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR then \f(CW\*(C`diff.tex\*(C'\fR is not -guaranteed to work but usually will). -.IP "2." 3 -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -\&\f(CW\*(C`diff.tex\*(C'\fR. -.IP "3." 3 -If a changed passage contains text or text-producing commands, then -running \f(CW\*(C`diff.tex\*(C'\fR through LateX should produce output where added -and discarded passages are highlighted. -.IP "4." 3 -Where there are insignificant differences, e.g. in the positioning of -line breaks, \f(CW\*(C`diff.tex\*(C'\fR should follow the formatting of \f(CW\*(C`new.tex\*(C'\fR -.PP -For differencing the same algorithm as \fIdiff\fR is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, \f(CW\*(C`\ecaption\*(C'\fR and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write -.PP -.Vb 1 -\& \esection{\etextem{This is an emphasized section title}} -.Ve -.PP -and not -.PP -.Vb 1 -\& \esection {\etextem{This is an emphasized section title}} -.Ve -.PP -or -.PP -.Vb 1 -\& \esection\etextem{This is an emphasized section title} -.Ve -.PP -even though all varieties are the same to LaTeX (but see -\&\fB\-\-allow\-spaces\fR option which allows the second variety). -.PP -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the \s-1PICTUREENV\s0 configuration variable, set by -default to \f(CW\*(C`picture\*(C'\fR and \f(CW\*(C`DIFnomarkup\*(C'\fR environments; see \fB\-\-config\fR -option). The latter environment (\f(CW\*(C`DIFnomarkup\*(C'\fR) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by \f(CW\*(C`\ebegin{DIFnomarkup}\*(C'\fR and \f(CW\*(C`\eend{DIFnomarkup}\*(C'\fR. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, -.PP -\&\f(CW\*(C`\enewenvironment{DIFnomarkup}{}{}\*(C'\fR -.PP -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. -.PP -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. -.PP -All markup commands inserted by \fIlatexdiff\fR begin with "\f(CW\*(C`\eDIF\*(C'\fR". Added -blocks containing words, commands or comments which are in \f(CW\*(C`new.tex\*(C'\fR -but not in \f(CW\*(C`old.tex\*(C'\fR are marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR and \f(CW\*(C`\eDIFaddend\*(C'\fR. -Discarded blocks are marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR. -Within added blocks all text is highlighted with \f(CW\*(C`\eDIFadd\*(C'\fR like this: -\&\f(CW\*(C`\eDIFadd{Added text block}\*(C'\fR -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces \*(L"{\*(R" and \*(L"}\*(R" are never put within -the scope of \f(CW\*(C`\eDIFadd\*(C'\fR. Added comments are marked by prepending -"\f(CW\*(C`%DIF\ >\ \*(C'\fR". -.PP -Within deleted blocks text is highlighted with \f(CW\*(C`\eDIFdel\*(C'\fR. Deleted -comments are marked by prepending "\f(CW\*(C`%DIF\ <\ \*(C'\fR\*(L". Non-safe command -and curly braces within deleted blocks are commented out with -\&\*(R"\f(CW\*(C`%DIFDELCMD\ <\ \*(C'\fR". -.SH "OPTIONS" -.IX Header "OPTIONS" -.SS "Preamble" -.IX Subsection "Preamble" -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. -.IP "\fB\-\-type=markupstyle\fR or \fB\-t markupstyle\fR" 4 -.IX Item "--type=markupstyle or -t markupstyle" -Add code to preamble for selected markup style. This option defines -\&\f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands. -Available styles: -.Sp -\&\f(CW\*(C`UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR\*(C'\fR -.Sp -[ Default: \f(CW\*(C`UNDERLINE\*(C'\fR ] -.IP "\fB\-\-subtype=markstyle\fR or \fB\-s markstyle\fR" 4 -.IX Item "--subtype=markstyle or -s markstyle" -Add code to preamble for selected style for bracketing -commands (e.g. to mark changes in margin). This option defines -\&\f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR commands. -Available styles: \f(CW\*(C`SAFE MARGINAL COLOR DVIPSCOL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`SAFE\*(C'\fR ] -.IP "\fB\-\-floattype=markstyle\fR or \fB\-f markstyle\fR" 4 -.IX Item "--floattype=markstyle or -f markstyle" -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -\&\f(CW\*(C`\eDIF...FL\*(C'\fR commands. -Available styles: \f(CW\*(C`FLOATSAFE TRADITIONALSAFE IDENTICAL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`FLOATSAFE\*(C'\fR ] -.IP "\fB\-\-encoding=enc\fR or \fB\-e enc\fR" 4 -.IX Item "--encoding=enc or -e enc" -Specify encoding of old.tex and new.tex. Typical encodings are -\&\f(CW\*(C`ascii\*(C'\fR, \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR, \f(CW\*(C`latin9\*(C'\fR. A list of available encodings can be -obtained by executing -.Sp -\&\f(CW\*(C`perl \-MEncode \-e \*(Aqprint join ("\en",Encode\-\*(C'\fRencodings( \*(L":all\*(R" )) ;' > -.Sp -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation \f(CW\*(C`\eusepackage[..]{inputenc}\*(C'\fR in which case the -encoding chosen by this command is asssumed. Note that \s-1ASCII\s0 (standard -latex) is a subset of utf8] -.IP "\fB\-\-preamble=file\fR or \fB\-p file\fR" 4 -.IX Item "--preamble=file or -p file" -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -\&\f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFadd{..}, -\&\eDIFdelbegin,\eDIFdelend,\eDIFdel{..},\*(C'\fR -and varieties for use within floats -\&\f(CW\*(C`\eDIFaddbeginFL, \eDIFaddendFL, \eDIFaddFL{..}, -\&\eDIFdelbeginFL, \eDIFdelendFL, \eDIFdelFL{..}\*(C'\fR -(If this option is set \fB\-t\fR, \fB\-s\fR, and \fB\-f\fR options -are ignored.) -.IP "\fB\-\-packages=pkg1,pkg2,..\fR" 4 -.IX Item "--packages=pkg1,pkg2,.." -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for \f(CW\*(C`\eusepackage\*(C'\fR commands. -Use of the \fB\-\-packages\fR option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use \fB\-\-packages=none\fR. -The following packages trigger special behaviour: -.RS 4 -.ie n .IP """amsmath""" 8 -.el .IP "\f(CWamsmath\fR" 8 -.IX Item "amsmath" -Configuration variable amsmath is set to \f(CW\*(C`align*\*(C'\fR (Default: \f(CW\*(C`eqnarray*\*(C'\fR) -.ie n .IP """endfloat""" 8 -.el .IP "\f(CWendfloat\fR" 8 -.IX Item "endfloat" -Ensure that \f(CW\*(C`\ebegin{figure}\*(C'\fR and \f(CW\*(C`\eend{figure}\*(C'\fR always appear by themselves on a line. -.ie n .IP """hyperref""" 8 -.el .IP "\f(CWhyperref\fR" 8 -.IX Item "hyperref" -Change name of \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands to \f(CW\*(C`\eDIFaddtex\*(C'\fR and \f(CW\*(C`\eDIFdeltex\*(C'\fR and -define new \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). -.RE -.RS 4 -.Sp -[ Default: scan the preamble for \f(CW\*(C`\e\eusepackage\*(C'\fR commands to determine - loaded packages.] -.RE -.IP "\fB\-\-show\-preamble\fR" 4 -.IX Item "--show-preamble" -Print generated or included preamble commands to stdout. -.SS "Configuration" -.IX Subsection "Configuration" -.ie n .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-safecmd=exclude-file or -A exclude-file or --exclude-safecmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-safecmd=replace\-file\fR" 4 -.IX Item "--replace-safecmd=replace-file" -.ie n .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-safecmd=append-file or -a append-file or --append-safecmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a \f(CW\*(C`\eDIFadd\*(C'\fR or \f(CW\*(C`\eDIFdel\*(C'\fR command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -\&\*(L"\e\*(R" of the command is not included. -The \fB\-\-exclude\-safecmd\fR and \fB\-\-append\-safecmd\fR options can be combined with the \-\fB\-\-replace\-safecmd\fR -option and can be used repeatedly to add cumulatively to the lists. - \fB\-\-exclude\-safecmd\fR -and \fB\-\-append\-safecmd\fR can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus \*(L"\e,\*(R". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. -.ie n .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-textcmd=exclude-file or -X exclude-file or --exclude-textcmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-textcmd=replace\-file\fR" 4 -.IX Item "--replace-textcmd=replace-file" -.ie n .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-textcmd=append-file or -x append-file or --append-textcmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for \fB\-\-exclude\-safecmd\fR directly above for further details. -.IP "\fB\-\-replace\-context1cmd=replace\-file\fR" 4 -.IX Item "--replace-context1cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-context1cmd=append-file or =item --append-context1cmd=cmd1,cmd2,..." -.PD -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \ecaption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. -.IP "\fB\-\-replace\-context2cmd=replace\-file\fR" 4 -.IX Item "--replace-context2cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=""cmd1,cmd2,...""\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.el .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=``cmd1,cmd2,...''\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.IX Item "--append-context2cmd=append-file or =item --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." -.IP "\fB\-\-config var1=val1,var2=val2,...\fR or \fB\-c var1=val1,..\fR" 4 -.IX Item "--config var1=val1,var2=val2,... or -c var1=val1,.." -.IP "\fB\-c configfile\fR" 4 -.IX Item "-c configfile" -.PD -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): -.Sp -\&\f(CW\*(C`MINWORDSBLOCK\*(C'\fR (integer) -.Sp -\&\f(CW\*(C`FLOATENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`PICTUREENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`MATHARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHARRREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`ARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`COUNTERCMD\*(C'\fR (RegEx) -.IP "\fB\-\-show\-safecmd\fR" 4 -.IX Item "--show-safecmd" -Print list of RegEx matching and excluding safe commands. -.IP "\fB\-\-show\-textcmd\fR" 4 -.IX Item "--show-textcmd" -Print list of RegEx matching and excluding commands with text argument. -.IP "\fB\-\-show\-config\fR" 4 -.IX Item "--show-config" -Show values of configuration variables. -.IP "\fB\-\-show\-all\fR" 4 -.IX Item "--show-all" -Combine all \-\-show commands. -.Sp -\&\s-1NB\s0 For all \-\-show commands, no \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR file needs to be specified, and no -differencing takes place. -.SS "Other configuration options:" -.IX Subsection "Other configuration options:" -.IP "\fB\-\-allow\-spaces\fR" 4 -.IX Item "--allow-spaces" -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). -.IP "\fB\-\-math\-markup=level\fR" 4 -.IX Item "--math-markup=level" -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): -.Sp -\&\f(CW\*(C`off\*(C'\fR or \f(CW0\fR: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. -.Sp -\&\f(CW\*(C`whole\*(C'\fR or \f(CW1\fR: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. -.Sp -\&\f(CW\*(C`coarse\*(C'\fR or \f(CW2\fR: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -.Sp -\&\f(CW\*(C`fine\*(C'\fR or \f(CW3\fR: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. -.IP "\fB\-\-disable\-citation\-markup\fR" 4 -.IX Item "--disable-citation-markup" -Suppress citation markup in styles using ulem (\s-1UNDERLINE\s0, -\&\s-1FONTSTRIKE\s0, \s-1CULINECHBAR\s0) -.IP "\fB\-\-enable\-citation\-markup\fR" 4 -.IX Item "--enable-citation-markup" -Protect citation commands in changed sections with \e\embox command [i.e. use default behaviour for ulem package for other packages] -.SS "Miscellaneous" -.IX Subsection "Miscellaneous" -.RS 4 -Output various status information to stderr during processing. -Default is to work silently. -.Sp -\&\fB\-\-driver=type\fR -.Sp -Choose driver for changebar package (only relevant for styles using - changebar: \s-1CCHANGEBAR\s0 \s-1CFONTCHBAR\s0 \s-1CULINECHBAR\s0 \s-1CHANGEBAR\s0). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] -.Sp -\&\fB\-\-ignore\-warnings\fR -.Sp -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to \f(CW\*(C`latexdiff\*(C'\fR but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. -.Sp -\&\fB\-\-label=label\fR or -\&\fB\-L label\fR -.Sp -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this \f(CW\*(C`\-L labelold \-L labelnew\*(C'\fR. -[Default: use the filename and modification dates for the label] -.Sp -\&\fB\-\-no\-label\fR -.Sp -Suppress inclusion of old and new file names as comment in output file -.Sp -\&\fB\-\-visble\-label\fR -.Sp -Include old and new filenames (or labels set with \-\-label option) as -visible output. -.Sp -\&\fB\-\-flatten\fR -.Sp -Replace \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within body by the content -of the files in their argument. If \f(CW\*(C`\eincludeonly\*(C'\fR is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. -\&\-\-flatten is applied recursively, so inputted files can contain further -\&\f(CW\*(C`\einput\*(C'\fR statements. -.Sp -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. -.Sp -\&\fB\-\-help\fR or -\&\fB\-h\fR -.Sp -Show help text -.Sp -\&\fB\-\-version\fR -.Sp -Show version number -.RE -.SS "Predefined styles" -.IX Subsection "Predefined styles" -.SS "Major types" -.IX Subsection "Major types" -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands \f(CW\*(C`\eDIFadd{...}\*(C'\fR and \f(CW\*(C`\eDIFdel{...}\*(C'\fR . -.ie n .IP """UNDERLINE""" 10 -.el .IP "\f(CWUNDERLINE\fR" 10 -.IX Item "UNDERLINE" -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). -.ie n .IP """CTRADITIONAL""" 10 -.el .IP "\f(CWCTRADITIONAL\fR" 10 -.IX Item "CTRADITIONAL" -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) -.ie n .IP """TRADITIONAL""" 10 -.el .IP "\f(CWTRADITIONAL\fR" 10 -.IX Item "TRADITIONAL" -Like \f(CW\*(C`CTRADITIONAL\*(C'\fR but without the use of color. -.ie n .IP """CFONT""" 10 -.el .IP "\f(CWCFONT\fR" 10 -.IX Item "CFONT" -Added text is blue and set in sans-serif, and discarded text is red and very small size. -.ie n .IP """FONTSTRIKE""" 10 -.el .IP "\f(CWFONTSTRIKE\fR" 10 -.IX Item "FONTSTRIKE" -Added tex is set in sans-serif, discarded text small and struck out -.ie n .IP """CCHANGEBAR""" 10 -.el .IP "\f(CWCCHANGEBAR\fR" 10 -.IX Item "CCHANGEBAR" -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). -.ie n .IP """CFONTCHBAR""" 10 -.el .IP "\f(CWCFONTCHBAR\fR" 10 -.IX Item "CFONTCHBAR" -Like \f(CW\*(C`CFONT\*(C'\fR but with additional changebars (Requires color and changebar packages). -.ie n .IP """CULINECHBAR""" 10 -.el .IP "\f(CWCULINECHBAR\fR" 10 -.IX Item "CULINECHBAR" -Like \f(CW\*(C`UNDERLINE\*(C'\fR but with additional changebars (Requires color, ulem and changebar packages). -.ie n .IP """CHANGEBAR""" 10 -.el .IP "\f(CWCHANGEBAR\fR" 10 -.IX Item "CHANGEBAR" -No mark up of text, but mark margins with changebars (Requires changebar package). -.ie n .IP """INVISIBLE""" 10 -.el .IP "\f(CWINVISIBLE\fR" 10 -.IX Item "INVISIBLE" -No visible markup (but generic markup commands will still be inserted. -.SS "Subtypes" -.IX Subsection "Subtypes" -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR) -.ie n .IP """SAFE""" 10 -.el .IP "\f(CWSAFE\fR" 10 -.IX Item "SAFE" -No additional markup (Recommended choice) -.ie n .IP """MARGIN""" 10 -.el .IP "\f(CWMARGIN\fR" 10 -.IX Item "MARGIN" -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard \f(CW\*(C`\emarginpar\*(C'\fR command \- note that this sometimes moves somewhat -from the intended position. -.ie n .IP """COLOR""" 10 -.el .IP "\f(CWCOLOR\fR" 10 -.IX Item "COLOR" -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). -.ie n .IP """DVIPSCOL""" 10 -.el .IP "\f(CWDVIPSCOL\fR" 10 -.IX Item "DVIPSCOL" -An alternative way of marking added passages in blue, and deleted ones in red. Note -that \f(CW\*(C`DVIPSCOL\*(C'\fR 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). -.SS "Float Types" -.IX Subsection "Float Types" -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. -.ie n .IP """FLOATSAFE""" 10 -.el .IP "\f(CWFLOATSAFE\fR" 10 -.IX Item "FLOATSAFE" -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is \f(CW\*(C`MARGIN\*(C'\fR as \f(CW\*(C`\emarginpar\*(C'\fR does not work properly within floats. -.ie n .IP """TRADITIONALSAFE""" 10 -.el .IP "\f(CWTRADITIONALSAFE\fR" 10 -.IX Item "TRADITIONALSAFE" -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \e[ and \e] and the deleted text is set in scriptscript size. This float type should always be used with the \f(CW\*(C`TRADITIONAL\*(C'\fR and \f(CW\*(C`CTRADITIONAL\*(C'\fR markup types as the \efootnote command does not work properly in floating environments. -.ie n .IP """IDENTICAL""" 10 -.el .IP "\f(CWIDENTICAL\fR" 10 -.IX Item "IDENTICAL" -Make no difference between the main text and floats. -.SS "Configuration Variables" -.IX Subsection "Configuration Variables" -.ie n .IP """MINWORDSBLOCK""" 10 -.el .IP "\f(CWMINWORDSBLOCK\fR" 10 -.IX Item "MINWORDSBLOCK" -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than \f(CW\*(C`MINWORDSBLOCK\*(C'\fR to the preceding added and discarded parts. -.Sp -[ Default: 3 ] -.ie n .IP """FLOATENV""" 10 -.el .IP "\f(CWFLOATENV\fR" 10 -.IX Item "FLOATENV" -Environments whose name matches the regular expression in \f(CW\*(C`FLOATENV\*(C'\fR are -considered floats. Within these environments, the \fIlatexdiff\fR markup commands -are replaced by their \s-1FL\s0 variaties. -.Sp -[ Default: \f(CW\*(C`(?:figure|table|plate)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """PICTUREENV""" 10 -.el .IP "\f(CWPICTUREENV\fR" 10 -.IX Item "PICTUREENV" -Within environments whose name matches the regular expression in \f(CW\*(C`PICTUREENV\*(C'\fR -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). -.Sp -[ Default: \f(CW\*(C`(?:picture|DIFnomarkup)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """MATHENV"",""MATHREPL""" 10 -.el .IP "\f(CWMATHENV\fR,\f(CWMATHREPL\fR" 10 -.IX Item "MATHENV,MATHREPL" -If both \ebegin and \eend for a math environment (environment name matching \f(CW\*(C`MATHENV\*(C'\fR -or \e[ and \e]) -are within the same deleted block, they are replaced by a \ebegin and \eend commands for \f(CW\*(C`MATHREPL\*(C'\fR -rather than being commented out. -.Sp -[ Default: \f(CW\*(C`MATHENV\*(C'\fR=\f(CW\*(C`(?:displaymath|equation)\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`displaymath\*(C'\fR\ ] -.ie n .IP """MATHARRENV"",""MATHARRREPL""" 10 -.el .IP "\f(CWMATHARRENV\fR,\f(CWMATHARRREPL\fR" 10 -.IX Item "MATHARRENV,MATHARRREPL" -as \f(CW\*(C`MATHENV\*(C'\fR,\f(CW\*(C`MATHREPL\*(C'\fR but for equation arrays -.Sp -[ Default: \f(CW\*(C`MATHARRENV\*(C'\fR=\f(CW\*(C`eqnarray\e*?\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`eqnarray\*(C'\fR\ ] -.ie n .IP """ARRENV""" 10 -.el .IP "\f(CWARRENV\fR" 10 -.IX Item "ARRENV" -If a match to \f(CW\*(C`ARRENV\*(C'\fR is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by \f(CW\*(C`\embox{\*(C'\fR...\f(CW\*(C`}\*(C'\fR. This is necessary as underlining does not work within inlined array environments. -.Sp -[ Default: \f(CW\*(C`ARRENV\*(C'\fR=\f(CW\*(C`(?:array|[pbvBV]matrix)\*(C'\fR\ -.ie n .IP """COUNTERCMD""" 10 -.el .IP "\f(CWCOUNTERCMD\fR" 10 -.IX Item "COUNTERCMD" -If a command in a deleted block which is also in the textcmd list matches \f(CW\*(C`COUNTERCMD\*(C'\fR then an -additional command \f(CW\*(C`\eaddtocounter{\*(C'\fR\fIcntcmd\fR\f(CW\*(C`}{\-1}\*(C'\fR, where \fIcntcmd\fR is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. -.Sp -[ Default: \f(CW\*(C`COUNTERCMD\*(C'\fR=\f(CW\*(C`(?:footnote|part|section|subsection\*(C'\fR ... -.Sp -\&\f(CW\*(C`|subsubsection|paragraph|subparagraph)\*(C'\fR ] -.SH "COMMON PROBLEMS" -.IX Header "COMMON PROBLEMS" -.IP "Citations result in overfull boxes" 10 -.IX Item "Citations result in overfull boxes" -There is an incompatibility between the \f(CW\*(C`ulem\*(C'\fR package, which \f(CW\*(C`latexdiff\*(C'\fR uses for underlining and striking out in the \s-1UNDERLINE\s0 style, -the default style. In order to be able to mark up citations properly, they are placed with an \f(CW\*(C`\embox\*(C'\fR 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: -.Sp -1. Use \f(CW\*(C`COLOR\*(C'\fR or \f(CW\*(C`DVIPSCOL\*(C'\fR subtype markup (option \f(CW\*(C`\-s COLOR\*(C'\fR): 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. -.Sp -2. Choose option \f(CW\*(C`\-\-disable\-citation\-markup\*(C'\fR 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) -.IP "Changes in complicated mathematical equations result in latex processing errors" 10 -.IX Item "Changes in complicated mathematical equations result in latex processing errors" -Try options \f(CW\*(C`\-\-math\-markup=whole\*(C'\fR. If even that fails, you can turn off mark up for equations with \f(CW\*(C`\-\-math\-markup=off\*(C'\fR. -.SH "BUGS" -.IX Header "BUGS" -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. -.PP -Please submit bug reports on the latexdiff project page \fIhttp://latexdiff.berlios.de\fR, -send them to user discussion list \f(CW\*(C`latexdiff\-users@lists.berlios,de\*(C'\fR (prior subscription -to list required, also on project webpage) -or send them to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexdiff\fR -(from comments at the top of the source or use \fB\-\-version\fR). 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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexrevise, latexdiff-vc -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff\fR does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than \s-1ASCII\s0 or \s-1UTF\-8\s0 are processed, Perl 5.8 or higher is required. -.PP -The standard version of \fIlatexdiff\fR requires installation of the Perl package -\&\f(CW\*(C`Algorithm::Diff\*(C'\fR (available from \fIwww.cpan.org\fR \- -\&\fIhttp://search.cpan.org/~nedkonz/Algorithm\-Diff\-1.15\fR) but a stand-alone -version, \fIlatexdiff-so\fR, which has this package inlined, is available, too. -\&\fIlatexdiff-fast\fR requires the \fIdiff\fR command to be present. -.SH "AUTHOR" -.IX Header "AUTHOR" -Version 1.0.2 -Copyright (C) 2004\-2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -.PP -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. -.SH "POD ERRORS" -.IX Header "POD ERRORS" -Hey! \fBThe above document had some coding errors, which are explained below:\fR -.IP "Around line 2942:" 4 -.IX Item "Around line 2942:" -=over should be: '=over' or '=over positive_number' -.Sp -You can't have =items (as at line 2948) unless the first thing after the =over is an =item diff --git a/latexdiff-1.0.2/latexrevise b/latexdiff-1.0.2/latexrevise deleted file mode 100755 index 0f333fb..0000000 --- a/latexdiff-1.0.2/latexrevise +++ /dev/null @@ -1,539 +0,0 @@ -#!/usr/bin/env perl -# latexrevise - takes output file of latexdiff and removes either discarded -# or appended passages, then deletes all other latexdiff markup -# -# Copyright (C) 2004 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# Note: version number now keeping up with latexdiff -# Version 1.0.2 Option --version -# Version 1.0.1 no changes to latexrevise -# Version 0.3 Updated for compatibility with latexdiff 0.3 output (DIFAUXCMD removal) -# Version 0.1 First public release - -use Getopt::Long ; -use strict; -use warnings; - -my $versionstring=< \$accept, - 'decline|d'=> \$decline, - 'simplify|s' => \$simplify, - 'comment|c=s' => \$comment, - 'comment-environment|e=s' => \$comenv, - 'markup|m=s' => \$markup, - 'markup-environment|n=s' => \$markenv, - 'no-warnings|q' => \$verbose, - 'version' => \$version, - 'verbose|V' => \$verbose, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - -if ( $version ) { - die $versionstring ; -} - - -if ( ($accept && $decline) || ($accept && $simplify) || ($decline && $simplify) ) { - die '-a,-d and -s options are mutually axclusive. Type latexrevise -h to get more help.'; -} - - - -print STDERR "ACCEPT mode\n" if $verbose && $accept; -print STDERR "DECLINE mode\n" if $verbose && $decline; -print STDERR "SIMPLIFY mode. WARNING: The output will not normally be valid latex,\n" if $verbose && $simplify; - -# Slurp old and new files -{ - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $input=<>; -} - -# split into parts -($preamble,$body,$post)=splitdoc($input,'\begin{document}','\end{document}'); - -if (length $preamble && ( $accept || $decline ) ) { - # - # WORK ON PREAMBLE - # - # (compare subroutine linediff in latexdiff to make sure correct strings are used) - - # remove extra commands added to preamble by latexdiff - $preamble =~ s/${PREAMBLEXTBEG}.*?${PREAMBLEXTEND}\n{0,1}//smg ; - - if ( $accept ) { - # delete mark up in appended lines - $preamble =~ s/^(.*) %DIF > $/$1/mg ; - } elsif ( $decline ) { - # delete appended lines - # $preamble =~ s/^(.*) %DIF > $//mg ; - $preamble =~ s/^(.*) %DIF > \n//mg ; - # delete markup in deleted lines - $preamble =~ s/^%DIF < //mg ; - } - # remove any remaining DIF markups - #$preamble =~ s/%DIF.*$//mg ; - $preamble =~ s/%DIF.*?\n//sg ; -} -#print $preamble ; - -# -# WORK ON BODY -# -if ($accept) { - # remove ADDMARKOPEN, ADDMARKCLOSE tokens - @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/$1/sg; - # remove text flanked by DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}//sg; - # remove markup of added comments - $body =~ s/%${ADDCOMMENT}(.*?)$/%$1/mg ; - # remove deleted comments (full line) - $body =~ s/^%${DELCOMMENT}.*?\n//mg ; - # remove deleted comments (part of line) - $body =~ s/%${DELCOMMENT}.*?$//mg ; -} -elsif ( $decline) { - # remove DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/$1/sg; - # remove text flanked by ADDMARKOPEN, ADDMARKCLOSE tokens - # as latexdiff algorithm keeps the formatting and white spaces - # of the new text, sometimes whitespace might be inserted or - # removed inappropriately. We try to guess whether this has - # happened - - # Mop up tokens. This must be done already now as otherwise - # detection of white-space problems does not work - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - # remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - $cnt += $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - while ( $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/s ) { - $prematch=$`; - $postmatch=$'; - checkpure($1); - if ( $prematch =~ /\w$/s && $postmatch =~ /^\w/ ) { - # apparently no white-space between word=>Insert white space - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/ /s ; - } - elsif ( $prematch =~ /\s$/s && $postmatch =~ /^[.,;:]/ ) { - # space immediately before one of ".,:;" => remove this space - $body =~ s/\s${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s ; - } - else { - # do not insert or remove any extras - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s; - } - } -# Alternative without special cases treatment -# @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; -# checkpure(@matches); -# $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//sg; - # remove markup of deleted comments - $body =~ s/%${DELCOMMENT}(.*?)$/%$1/mg ; - # remove added comments (full line) - $body =~ s/^%${ADDCOMMENT}.*?\n//mg ; - # remove added comments (part of line) - $body =~ s/%${ADDCOMMENT}.*?$//mg ; -} - -# remove any remaining tokens -if ( $accept || $decline || $simplify ) { - # first substitution command deals with special case of added paragraph - $cnt = $body =~ s/${ADDOPEN}($pat4)\n${ADDCLOSE}\n/$1\n/sg; - $cnt += $body =~ s/${ADDOPEN}($pat4)${ADDCLOSE}/$1/sg; - $cnt==0 || warn 'Remaining $ADDOPEN tokens in DECLINE mode\n' unless ( $quiet || $accept || $simplify ); -} -if ($accept || $simplify ) { - # Note: in decline mode these commands have already been removed above - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - #### remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - # $cnt += - $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - #### remove deleted comments - ###$cnt += $body =~ s/${DIFDELCMD}.*?$//mg ; - $cnt==0 || warn 'Remaining $DELOPEN or $DIFDELCMD tokens in ACCEPT mode\n' unless ( $quiet || $simplify ); -} - -# Remove comment commands -if (defined($comment)) { - print STDERR "Removing \\$comment\{..\} sequences ..." if $verbose; - # protect $comments in comments by making them look different - $body =~ s/(%.*)${comment}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${comment}(?:\[${brat0}\])?\{${pat4}\}//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${comment}$2/mg ; -} -if (defined($comenv)) { - print STDERR "Removing $comenv environments ..." if $verbose; - $body =~ s/(%.*)${comenv}/$1${someword}/mg ; -## $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{\$comenv\}.*?\\end\{\$comenv\}//sg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${comenv}\}.*?\\end\{${comenv}\}\s*?\n//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${comenv}/mg ; -} - -if (defined($markup)) { - print STDERR "Removing \\$markup\{..\} cpmmands ..." if $verbose; - # protect $markups in comments by making them look different - $body =~ s/(%.*)${markup}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${markup}(?:\[${brat0}\])?\{(${pat4})\}/$1/sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${markup}$2/mg ; -} -if (defined($markenv)) { - print STDERR "Removing $markenv environments ..." if $verbose; - $body =~ s/(%.*)${markenv}/$1${someword}/mg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${markenv}\}\n?//sg; - $cnt += 0 + $body =~ s/\\end\{${markenv}\}\n?//sg; - print STDERR $cnt/2, " matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${markenv}/mg ; -} - - -if ( length $preamble ) { - print "$preamble\\begin{document}${body}\\end{document}$post"; -} else { - print $body; -} - -# checkpure(@matches) -# checks whether any of the strings in matches contains -# $ADDMARKOPEN, $ADDMARKCLOSE,$DELMARKOPEN, or $DELMARKCLOSE -# If so, die reporting nesting problems, otherwise return to caller -sub checkpure { - while (defined($_=shift)) { - if ( /$ADDMARKOPEN/ || /$ADDMARKCLOSE/ - || /$DELMARKOPEN/ || /$DELMARKCLOSE/ ) { - die <=0 && $j>$i ) { - $part1 = substr($text,0,$i) ; - $part2 = substr($text,$i+$l1,$j-$i-$l1); - $part3 = substr($text,$j+$l2) unless $j+$l2 >= length $text; - } else { - die "$word1 or $word2 not in the correct order or not present as a pair." - } - return ($part1,$part2,$part3); -} - - - -sub usage { - die <<"EOF"; -Usage: $0 [OPTIONS] [diff.tex] > revised.tex - -Read a file diff.tex (output of latexdiff), and remove its markup. -If no filename is given read from standard input. The command can be used -in ACCEPT, DECLINE, or SIMPLIFY mode, and be used to remove user-defined -latex commands from the input (see options -c, -e, -m, -n below). -In ACCEPT mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In DECLINE mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that latexrevise only pays attention to the \\DIFaddbegin, -\\DIFaddend, \\DIFdelbegin, and \\DIFdelend tokens and corresponding FL -varieties. All \\DIFadd and \\DIFdel commands (but not their content) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In SIMPLIFY mode all latexdiff markup is removed from the body of the text (after -\\begin{document}) except for \\DIFaddbegin, \\DIFaddend, \\DIFdelbegin, \\DIFdelend -tokens and the corresponding FL varieties of those commands. The result -will not in general be valid latex-code but might be easier to read and edit in -preparation for a subsequent run in ACCEPT or DECLINE mode. -In SIMPLIFY mode the preamble is left unmodified. - --a ---accept Run in ACCEPT mode (delete all blocks marked by \\DIFdelbegin - and \\DIFdelend). - --d ---decline Run in DECLINE mode (delete all blocks marked by \\DIFaddbegin - and \\DIFaddend). - --s ---simplify Run in SIMPLIFY mode (Keep all \\DIFaddbegin, \\DIFaddend, - \\DIFdelbegin, \\DIFdelend tokens, but remove all other latexdiff - markup from body. - -Note that the three mode options are mutually exclusive. If no mode option is given, -latexrevise simply removes user annotations and markup according to the following four -options. - - --c cmd ---comment=cmd Remove \\cmd{...}. cmd is supposed to mark some explicit - anotations which should be removed from the file before - release. - --e envir ---comment-environment=envir - Remove explicit annotation environments from the text, i.e. remove - \\begin{envir} - ... - \\end{envir} - blocks. - --m cmd ---markup=cmd Remove the markup command cmd but leave its argument, i.e. - turn \\cmd{abc} into abc. - --n envir ---markup-environment=envir - Similarly, remove \\begin{envir} and \\end{envir} commands, - but leave content of the environment in the text. - --q ---no-warnings Do not warn users about \\DIDadd{..} or \\DIFdel statements - which should not be there anymore - --V ---verbose Verbose output - -EOF -} - -=head1 NAME - -latexrevise - selectively remove markup and text from latexdiff output - -=head1 SYNOPSIS - -B [ B ] [ F ] > F - -=head1 DESCRIPTION - -I reads a file C (output of I), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in I, I, or I mode, or can be used to remove user-defined -latex commands from the input (see B<-c>, B<-e>, B<-m>, and B<-n> below). -In I mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In I mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that I only pays attention to the C<\DIFaddbegin>, -C<\DIFaddend>, C<\DIFdelbegin>, and C<\DIFdelend> tokens and corresponding FL -varieties. All C<\DIFadd> and C<\DIFdel> commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In I mode, C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend> -tokens and their corresponding C varieties are kept but all other markup (e.g. C and <\DIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in I or I mode. -In I mode the preamble is left unmodified. - -=head1 OPTIONS - -=over 4 - -=item B<-a> or B<--accept> - -Run in I mode (delete all blocks marked by C<\DIFdelbegin> and C<\DIFdelend>). - -=item B<-d> or B<--decline> - -Run in I mode (delete all blocks marked by C<\DIFaddbegin> -and C<\DIFaddend>). - -=item B<-s> or B<--simplify> - -Run in I mode (Keep all C<\DIFaddbegin>, C<\DIFaddend>, -C<\DIFdelbegin>, C<\DIFdelend> tokens, but remove all other latexdiff -markup from body). - -=back - -Note that the three mode options are mutually exclusive. If no mode option is given, -I simply removes user annotations and markup according to the following four -options. - -=over 4 - -=item B<-c cmd> or B<--comment=cmd> - -Remove C<\cmd{...}> sequences. C is supposed to mark some explicit -anotations which should be removed from the file before -release. - -=item B<-e envir> or B<--comment-environment=envir> - -Remove explicit annotation environments from the text, i.e. remove - - \begin{envir} - ... - \end{envir} - -blocks. - -=item B<-m cmd> or B<--markup=cmd> - -Remove the markup command C<\cmd> but leave its argument, i.e. -turn C<\cmd{abc}> into C. - -=item B<-n envir> or B<--markup-environment=envir> - -Similarly, remove C<\begin{envir}> and C<\end{envir}> commands but -leave content of the environment in the text. - - -=item B<-V> or B<--verbose> - -Verbose output - -=item B<-q> or B<--no-warnings> - -Do not warn users about C<\DIDadd{..}> or C<\DIFdel{..}> statements -which should have been removed already. - -=back - -=head1 BUGS - -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by I please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. - -Note that I gets confused by commented C<\begin{document}> or -C<\end{document}> statements - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting PERL v5 or higher. - -=head1 AUTHOR - -Copyright (C) 2004 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 - -=cut diff --git a/latexdiff-1.0.2/latexrevise.1 b/latexdiff-1.0.2/latexrevise.1 deleted file mode 100644 index b8d0d2d..0000000 --- a/latexdiff-1.0.2/latexrevise.1 +++ /dev/null @@ -1,235 +0,0 @@ -.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXREVISE 1" -.TH LATEXREVISE 1 "2012-12-16" "perl v5.12.4" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexrevise \- selectively remove markup and text from latexdiff output -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexrevise\fR [ \fB\s-1OPTIONS\s0\fR ] [ \fIdiff.tex\fR ] > \fIrevised.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexrevise\fR reads a file \f(CW\*(C`diff.tex\*(C'\fR (output of \fIlatexdiff\fR), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in \fI\s-1ACCEPT\s0\fR, \fI\s-1DECLINE\s0\fR, or \fI\s-1SIMPLIFY\s0\fR mode, or can be used to remove user-defined -latex commands from the input (see \fB\-c\fR, \fB\-e\fR, \fB\-m\fR, and \fB\-n\fR below). -In \fI\s-1ACCEPT\s0\fR mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In \fI\s-1DECLINE\s0\fR mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that \fIlatexrevise\fR only pays attention to the \f(CW\*(C`\eDIFaddbegin\*(C'\fR, -\&\f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR, and \f(CW\*(C`\eDIFdelend\*(C'\fR tokens and corresponding \s-1FL\s0 -varieties. All \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In \fI\s-1SIMPLIFY\s0\fR mode, \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR -tokens and their corresponding \f(CW\*(C`FL\*(C'\fR varieties are kept but all other markup (e.g. \f(CW\*(C`DIFadd\*(C'\fR and <\eDIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in \fI\s-1ACCEPT\s0\fR or \fI\s-1DECLINE\s0\fR mode. -In \fI\s-1SIMPLIFY\s0\fR mode the preamble is left unmodified. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-a\fR or \fB\-\-accept\fR" 4 -.IX Item "-a or --accept" -Run in \fI\s-1ACCEPT\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR). -.IP "\fB\-d\fR or \fB\-\-decline\fR" 4 -.IX Item "-d or --decline" -Run in \fI\s-1DECLINE\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR -and \f(CW\*(C`\eDIFaddend\*(C'\fR). -.IP "\fB\-s\fR or \fB\-\-simplify\fR" 4 -.IX Item "-s or --simplify" -Run in \fI\s-1SIMPLIFY\s0\fR mode (Keep all \f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, -\&\f(CW\*(C`\eDIFdelbegin\*(C'\fR, \f(CW\*(C`\eDIFdelend\*(C'\fR tokens, but remove all other latexdiff -markup from body). -.PP -Note that the three mode options are mutually exclusive. If no mode option is given, -\&\fIlatexrevise\fR simply removes user annotations and markup according to the following four -options. -.IP "\fB\-c cmd\fR or \fB\-\-comment=cmd\fR" 4 -.IX Item "-c cmd or --comment=cmd" -Remove \f(CW\*(C`\ecmd{...}\*(C'\fR sequences. \f(CW\*(C`cmd\*(C'\fR is supposed to mark some explicit -anotations which should be removed from the file before -release. -.IP "\fB\-e envir\fR or \fB\-\-comment\-environment=envir\fR" 4 -.IX Item "-e envir or --comment-environment=envir" -Remove explicit annotation environments from the text, i.e. remove -.Sp -.Vb 3 -\& \ebegin{envir} -\& ... -\& \eend{envir} -.Ve -.Sp -blocks. -.IP "\fB\-m cmd\fR or \fB\-\-markup=cmd\fR" 4 -.IX Item "-m cmd or --markup=cmd" -Remove the markup command \f(CW\*(C`\ecmd\*(C'\fR but leave its argument, i.e. -turn \f(CW\*(C`\ecmd{abc}\*(C'\fR into \f(CW\*(C`abc\*(C'\fR. -.IP "\fB\-n envir\fR or \fB\-\-markup\-environment=envir\fR" 4 -.IX Item "-n envir or --markup-environment=envir" -Similarly, remove \f(CW\*(C`\ebegin{envir}\*(C'\fR and \f(CW\*(C`\eend{envir}\*(C'\fR commands but -leave content of the environment in the text. -.IP "\fB\-V\fR or \fB\-\-verbose\fR" 4 -.IX Item "-V or --verbose" -Verbose output -.IP "\fB\-q\fR or \fB\-\-no\-warnings\fR" 4 -.IX Item "-q or --no-warnings" -Do not warn users about \f(CW\*(C`\eDIDadd{..}\*(C'\fR or \f(CW\*(C`\eDIFdel{..}\*(C'\fR statements -which should have been removed already. -.SH "BUGS" -.IX Header "BUGS" -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page \fIhttp://developer.berlios.de/projects/latexdiff/\fR or send -to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexrevise\fR -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by \fIlatexrevise\fR please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. -.PP -Note that \fIlatexrevise\fR gets confused by commented \f(CW\*(C`\ebegin{document}\*(C'\fR or -\&\f(CW\*(C`\eend{document}\*(C'\fR statements -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexrevise\fR does not make use of external commands and thus should run -on any platform supporting \s-1PERL\s0 v5 or higher. -.SH "AUTHOR" -.IX Header "AUTHOR" -Copyright (C) 2004 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 diff --git a/latexdiff-1.0.3/COPYING b/latexdiff-1.0.3/COPYING deleted file mode 100644 index d6fa915..0000000 --- a/latexdiff-1.0.3/COPYING +++ /dev/null @@ -1,623 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - diff --git a/latexdiff-1.0.3/README b/latexdiff-1.0.3/README deleted file mode 100644 index 7c7ff86..0000000 --- a/latexdiff-1.0.3/README +++ /dev/null @@ -1,107 +0,0 @@ -INTRODUCTION - -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -A rudimentary revision facilility is provided by another Perl script, -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). - -Project webpage: http://latexdiff.berlios.de/ -CTAN page: http://www.ctan.org/tex-archive/support/latexdiff - - -REQUIREMENTS - -Perl 5.8 or higher must be installed. - The latexdiff script makes use of the Perl package Algorithm::Diff (available -from www.cpan.org, current version 1.19). You can either install this package, or -use the standalone version of latexdiff, latexdiff-so, which has version 1.15 of -this package inlined and does not require external installation of -the package. Because latexdiff uses internal functions of Algorithm:Diff whose -calling format or availability can change without notice, the preferred method is -now to use the standalone version. - -As an alternative, latexdiff-fast has a modified version of Algorithm::Diff inlined, -which internally uses the UNIX diff command. This version is much faster but is dependent -on an external "diff" command. Subtle differences in the algorithm of Algorithm::Diff and -UNIX-diff mean that the resulting set of differences will generally not be the same as -for the standard latexdiff. In most practical cases, these differences are minor, though. - -INSTALLATION UNIX/LINUX - -The basic installation procedure is almost trivial: - -1. Copy latexdiff, latexrevise and latexdiff-vc into a directory which - is in the search path and make them executable. If the Algorithm::Diff - package is not installed, use latexdiff-so instead of latexdiff. - -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. - -The attached Makefile contains example commands to carry out above -steps as root for a typical UNIX installation. Type - - make install (for the stand alone version) -or - make install-ext (for the version using the external Algorithm::Diff) -or - make install-fast (for the version using the UNIX 'diff' function for fast differencing) - -to get it rolling. You can type - - make test -or - make test-ext -or - make test-fast - -to test the respective versions on a brief example before installation - - -DOCUMENTATION: - -Usage instructions are in the manual latexdiff-man.pdf as well as the -man pages. - -CHANGELOGS: - -Check out the comment lines at the beginning of the perl scripts (latexdiff, latexdiff-vc, latexrevise) - -CONTRIBUTIONS - -The directory contrib contains code written by others relating to latexdiff. -Currently this directory contains: - -latexdiff-wrap (Author: V. Kuhlmann) An alternative wrapper script which can be used - instead of latexdiff-vc. Its main use is as a template for customised wrapper scripts. - -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 -extend latexdiff in a similar way: J. Paisley, N. Becker, K. Huebner - -LICENSE (also see file COPYING) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License Version 3 as published by -the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details (file LICENSE in the -distribution). - diff --git a/latexdiff-1.0.3/doc/example-diff.tex b/latexdiff-1.0.3/doc/example-diff.tex deleted file mode 100644 index a476481..0000000 --- a/latexdiff-1.0.3/doc/example-diff.tex +++ /dev/null @@ -1,89 +0,0 @@ -\documentclass[12pt,a4paper]{article} -%DIF LATEXDIFF DIFFERENCE FILE -%DIF DEL example-draft.tex Sun Jan 27 23:50:07 2013 -%DIF ADD example-rev.tex Sun Jan 27 23:50:07 2013 - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -\title{latexdiff Example - \DIFdelbegin \DIFdel{Draft }\DIFdelend \DIFaddbegin \DIFadd{Revised }\DIFaddend version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of \DIFaddbegin \DIFadd{the }\DIFaddend latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{\DIFdelbegin \DIFdel{Another }\DIFdelend \DIFaddbegin \DIFadd{Yet another }\DIFaddend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft document. }\DIFdelend More things could be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised document. }\DIFaddend More things could be -said were it not for the constraints of time and space. - -And here is a \DIFdelbegin \DIFdel{tipo}\DIFdelend \DIFaddbegin \DIFadd{typo}\DIFaddend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFdelbegin \DIFdel{Grey }\DIFdelend \DIFaddbegin \DIFadd{White }\DIFaddend \\ -Saruman & \DIFdelbegin \DIFdel{White -}\DIFdelend \DIFaddbegin \DIFadd{Evil -}\DIFaddend \end{tabular} - -And \DIFdelbegin \DIFdel{sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend \DIFaddbegin \DIFadd{now for something completely different, with not a paragraph in sight}\DIFaddend . -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.3/doc/latexdiff-man.tex b/latexdiff-1.0.3/doc/latexdiff-man.tex deleted file mode 100644 index b6bb37e..0000000 --- a/latexdiff-1.0.3/doc/latexdiff-man.tex +++ /dev/null @@ -1,355 +0,0 @@ -\documentclass[a4]{article} -\usepackage{graphicx} -%\def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -%\def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -\setlength{\parindent}{0pt} -%\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}} -\date{\today} - -\begin{document} -\maketitle - -\section*{Preamble} - -{\em latexdiff} is a Perl script, which compares two -latex files and marks up significant differences between them. Various options are available for visual markup using standard -latex packages such as {\em color.sty}. Changes not directly affecting visible -text, for example in formatting commands, are still marked in the -latex source. - -A rudimentary revision facilility is provided by another Perl script, -{\em 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. - -There is no explicit support for annotations as these are trivial to implement. -For example, I include the following command definition in the preamble -\begin{verbatim} -\newcommand{\remark}[1]{{ \bf [ \footnotesize #1 ]}} -\end{verbatim} -and mark up annotations as follows -\begin{verbatim} -... The roadrunner is the fastest running bird \remark{Check this -again with a zoologist!}. The most famous roadrunner ... -\end{verbatim} -Alternatively, instead of a command like \verb#\remark# in the example just given, an -equivalent annotation environment could be defined. -{\em latexrevise} can remove such comments or -environments from the text body. - -%It is planned that the revision capabilities of this system will be -%further expanded, dependent on the amount of feedback received. - -On the following pages you find the {\em man} pages for {\em - latexdiff} and {\em latexrevise} and a simple example. - -\include{latexdiff} -\setcounter{section}{0} - -\include{latexrevise} -\setcounter{section}{0} - -\include{latexdiff-vc} -\setcounter{section}{0} - -\section*{A simple example} - -We start with a draft text, \verb|example-draft.tex|, listed here in -full but also included in the distribution (except that the ``verbatim'' environment had -to be renamed to ``Verbatim'' for the listing). - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. Of course, instead of \verb|xpdf| you can use -\verb|okular, evince, acroread| or any other pdf or postscript viewer. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things -could be said were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} -\end{verbatim} -} - -We can now edit -this text as we would do with any other latex file to create -a new revision of the text, \verb|example-rev.tex|. We should run -\begin{verbatim} -latex example-rev.tex -\end{verbatim} -and look at the resulting \verb|.dvi| file to make sure that all -changes are valid. An example revision is listed here: - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. -More things could be said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} -\end{verbatim} -} - -To compare both revisions, type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -This results in the following difference file (a few newlines have been -added in this listing for legibility reasosn): -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -%DIF 9c9 -%DIF < \title{latexdiff Example - Draft version} -%DIF ------- -\title{latexdiff Example - Revised version} %DIF > -%DIF ------- -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\color{blue}\uline{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{\DIFaddbegin \DIFadd{Yet another }\DIFaddend \DIFdelbegin -\DIFdel{Another }\DIFdelend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft - document. }\DIFdelend More things could - be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised - document. }\DIFaddend More things could be said -were it not for the constraints of time and space. - -And here is a \DIFaddbegin \DIFadd{typo}\DIFaddend \DIFdelbegin -\DIFdel{tipo}\DIFdelend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFaddbegin \DIFadd{White }\DIFaddend \DIFdelbegin -\DIFdel{Grey }\DIFdelend \\ -Saruman & \DIFaddbegin \DIFadd{Evil -}\DIFaddend \DIFdelbegin \DIFdel{White -}\DIFdelend \end{tabular} - -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -No change, -no markup! -\end{document} -\end{verbatim} -} -Type -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -to make the markup visible. This is what it looks like: - -\vspace{1cm} -\framebox[\textwidth]{\includegraphics[width=\textwidth]{example-diff}} -\vspace{1cm} - -If you approve of all the changes in the revision, just continue with -\verb|example-rev.tex| for the next revision. If you like to adopt -most but not all changes you can use \verb|latexrevise| in the -following manner. Simply remove the \verb|\DIFdelbegin| and -\verb|\DIFdelend| tags around the text you would like to keep and -simply remove the text between \verb|\DIFaddbegin| and -\verb|\DIFaddend| tags, if you do not wish to keep them. Say you are happy with all proposed changes for the -example above except in -the last paragraph where you prefer the original draft. You have -to change - -{\scriptsize -\begin{verbatim} -... -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -... -\end{verbatim} -} -into -{\scriptsize -\begin{verbatim} -... -And \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}. -... -\end{verbatim} -} -and run -\begin{verbatim} -latexrevise -a example-rev.tex > example-final.tex -\end{verbatim} -\verb|example-final.tex| is then almost identical to -\verb|example-rev.tex| except for the last paragraph. -\end{document} diff --git a/latexdiff-1.0.3/example/example-draft.tex b/latexdiff-1.0.3/example/example-draft.tex deleted file mode 100644 index 593a170..0000000 --- a/latexdiff-1.0.3/example/example-draft.tex +++ /dev/null @@ -1,59 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things could be said -were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} - - diff --git a/latexdiff-1.0.3/example/example-rev.tex b/latexdiff-1.0.3/example/example-rev.tex deleted file mode 100644 index 4bcaf15..0000000 --- a/latexdiff-1.0.3/example/example-rev.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. More things could be -said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.3/latexdiff b/latexdiff-1.0.3/latexdiff deleted file mode 100755 index febae2d..0000000 --- a/latexdiff-1.0.3/latexdiff +++ /dev/null @@ -1,3415 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if the contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -use Algorithm::Diff qw(traverse_sequences); - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.3/latexdiff-fast b/latexdiff-1.0.3/latexdiff-fast deleted file mode 100755 index e53afc1..0000000 --- a/latexdiff-1.0.3/latexdiff-fast +++ /dev/null @@ -1,3976 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if the contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for differenceing -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that subroutine _longestCommonSubsequence has been replace by -# a routine which internally uses the UNIX diff command for -# the differencing rather than the Perl routines if the -# length of the sequences exceeds some threshold. -# Also, all POD documentation has been stripped out. -# -# (the distribution on which this modification is based is available -# from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The fast-differencing version of latexdiff is provided as a convenience -# for latex users under Unix-like systems which have a 'diff' command. -# If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -# Jonathan Paisley is acknowledged for the idea of using the system diff -# command to achieve shorter running times -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d fast', (q$Revision: 1.15 $ =~ /\d+/g)); - -# Global parameters - -use File::Temp qw/tempfile/; -# if larger number of elements in longestCommonSubsequence smaller than -# this number, then use internal algorithm, otherwise use UNIX diff -use constant THRESHOLD => 100 ; -# Detect whether diff --minimal option is available -# if yes we use it -use constant MINIMAL => ( system('diff','--minimal','/dev/null','/dev/null') >> 8 ==0 ? "--minimal" : "" ) ; - - - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # Check whether to use internal routine (small number of elements) - # or use it as a wrapper for UNIX diff - if ( ( $#$a > $#$b ? $#$a : $#$b) < THRESHOLD ) { - ### print STDERR "DEBUG: regular longestCommonSubsequence\n"; - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - } - else { - my ($fha,$fhb,$fna,$fnb,$ele,$key); - my ($alines,$blines,$alb,$alf,$blb,$blf); - my ($minimal)=MINIMAL; - # large number of elements, use system diff - ### print STDERR "DEBUG: fast (diff) longestCommonSubsequence\n"; - - ($fha,$fna)=tempfile("DiffA-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence A"; - ($fhb,$fnb)=tempfile("DiffB-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence B"; - # prepare sequence A - foreach $ele ( @$a ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fha "$key\n" ; - } - close($fha); - # prepare sequence B - foreach $ele ( @$b ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fhb "$key\n" ; - } - close($fhb); - - open(DIFFPIPE, "diff $minimal $fna $fnb |") or die "_longestCommonSubsequence: Cannot launch diff process. $!" ; - # The diff line numbering begins with 1, but Perl subscripts start with 0 - # We follow the diff numbering but substract 1 when assigning to matchVector - $aStart++; $bStart++ ; $aFinish++ ; $bFinish++ ; - while( ) { - if ( ($alines,$blines) = ( m/^(\d*(?:,\d*)?)?c(\d*(?:,\d*)?)?$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - ($blb,$blf)=split(/,/,$blines); - $alf=$alb unless defined($alf); - $blf=$blb unless defined($blf); - while($aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - # check for consistency - $bStart==$blb or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in changed sequence"; - $aStart=$alf+1; - $bStart=$blf+1; - } - elsif ( ($alb,$blines) = ( m/^(\d*)a(\d*(?:,\d*)?)$/ ) ) { - ($blb,$blf)=split(/,/,$blines); - $blf=$blb unless defined($blf); - while ( $bStart < $blb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $aStart==$alb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in appended sequence near elements $aStart and $bStart"; - $bStart=$blf+1; - } - elsif ( ($alines,$blb) = ( m/^(\d*(?:,\d*)?)d(\d*)$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - $alf=$alb unless defined($alf); - while ( $aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$blb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in deleted sequence near elements $aStart and $bStart"; - $aStart=$alf+1; - } - elsif ( m/^Binary files/ ) { - # if diff reports it is a binary file force --text mode. I do not like - # to always use this option because it is probably only available in GNU diff - open(DIFFPIPE, "diff --text $fna $fnb |") or die "Cannot launch diff process. $!" ; - } - # Default: just skip line - } - while ($aStart <= $aFinish ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$bFinish+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency at end"; - close DIFFPIPE; - # check whether a system error has occurred or return status is greater than or equal to 5 - if ( $! || ($? >> 8) > 5) { - print STDERR "diff process failed with exit code ", ($? >> 8), " $!\n"; - die; - } - unlink $fna,$fnb ; - } - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.3/latexdiff-so b/latexdiff-1.0.3/latexdiff-so deleted file mode 100755 index e1f1d9b..0000000 --- a/latexdiff-1.0.3/latexdiff-so +++ /dev/null @@ -1,3872 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if the contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for stand-alone version replaces -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that all POD documentation has been stripped out. -# I encourage you to download and install the Algorithm::Diff -# package and use the standard latexdiff version instead -# (current distribution available from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The stand-alone version of latexdiff is provided as a convenience -# for latex users with no knowledge of PERL who do not wish to install -# additional packages to be able to use latexdiff. If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d so', (q$Revision: 1.15 $ =~ /\d+/g)); - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing - -if ( uc($type) ne "UNDERLINE" && uc($type) ne "FONTSTRIKE" && uc($type) ne "CULINECHBAR" ) { - push (@SAFECMDLIST, qr/^cite.*$/); -} else { - ### Experimental: disable text and emph commands - push (@SAFECMDLIST, qr/^cite.*$/) unless $disablecitmark; - push(@SAFECMDEXCL, qr/^emph$/, qr/^text..$/); - # replace \cite{..} by \mbox{\cite{..}} in added or deleted blocks in post-processing - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # deleted cite commands - $CITE2CMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite-type commands which should be reinstated in deleted blocks - } else { - $CITECMD='(?:cite\w*|nocite)' unless $disablecitmark ; # \cite commands which need to be protected within an mbox in UNDERLINE and other modes using ulem - } -} -$CITECMD='(?:cite\w*|nocite)' if $enablecitmark ; # as above for explicit selection - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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.'(?:(?:\['.$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*/ ; - - - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - %packages=list_packages(@newpreamble) unless %packages; - if (defined $packages{"hyperref"} ) { - print STDERR "hyperref package detected.\n" if $verbose ; - $latexdiffpreamble =~ s/\{\\DIFadd\}/{\\DIFaddtex}/g; - $latexdiffpreamble =~ s/\{\\DIFdel\}/{\\DIFdeltex}/g; - $latexdiffpreamble .= join "\n",(extrapream("HYPERREF"),""); - } - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - push @diffpreamble,$latexdiffpreamble; - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -if (defined $packages{"amsmath"} or defined $packages{"amsart"} or defined $packages{"amsbook"} ) { - print STDERR "amsmath package detected.\n" if $verbose ; - $MATHARRREPL='align*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %packages=list_packages(@preamble) -# scans the arguments for \documentclass 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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\'); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \LEFTBRACE and \} to \RIGHTBRACE -# #. change begin and end commands within comments to BEGINDIF, ENDDIF -# so they don't disturb the pattern matching (if there are several \begin or \end in one line -# 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 and \end in comments -# Change \QLEFTBRACE, \QRIGHTBRACE to \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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}(?:\[$brat0\]${extraspace}){0,2}\{$pat6\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - if ($CITECMD) { - my $addblockbefore=$addblock; - $addblock=~ s/(\\($CITECMD)${extraspace}(?:\[$brat0\]${extraspace}){0,2}\{$pat2\})(\s*)/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/msg ; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - ### old place for BEGINDIF, ENDDIF replacement - # change begin and end commands within comments such that they - # don't disturb the pattern matching (if there are several \begin or \end in one line - # this substitution is insufficient but that appears unlikely) - # This needs to be repeated here to also get rid of DIFdelcmd-protected environments - s/(%.*)\\begin\{(.*)$/$1\\BEGINDIF\{$2/mg ; - s/(%.*)\\end\{(.*)$/$1\\ENDDIF\{$2/mg ; - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visble-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -For further information, consult http://latexdiff.berlios.de -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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 on the latexdiff project page I, -send them to user discussion list C (prior subscription -to list required, also on project webpage) -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.2 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - - -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.3/latexdiff-vc b/latexdiff-1.0.3/latexdiff-vc deleted file mode 100755 index 56696da..0000000 --- a/latexdiff-1.0.3/latexdiff-vc +++ /dev/null @@ -1,493 +0,0 @@ -#!/usr/bin/env perl -# -# latexdiff-vc - wrapper script for applying latexdiff to rcs managed files -# and for automatised creation of postscript or pdf from difference file -# -# Copyright (C) 2005-13 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# -# Contributors: S Utcke, H Bruyninckx -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# version 1.0.3: Bug fix: replace use of system('cp...') with File::Copy::copy (Patch contributed by D. Bremner) -# Quotes around system call file arguments to allow filenames with spaces (Patch contributed by ssteve) -# version 1.0.2: - option --so to use latexdiff-so -# version 1.0.1 (change version numbering to match that of latexdiff) -# - Option --fast to use latexdiff-fast, -# - git support (thanks to Bjorn Magnus Mathisen, Santi Béjar, Pietro Battiston and Stefan Alfredson for patches) - UNTESTED -# version 0.25: -# - bbl is allowed as alternative extension (instead of .tex) -# version 0.26a -# - Bug fix: it copes now correctly with the possibility that there are no changes between current -# and archived version -use Getopt::Long ; -use Pod::Usage qw/pod2usage/ ; -use File::Temp qw/tempdir/ ; -use File::Basename qw/dirname/; -use File::Copy; - -use strict ; -use warnings ; - -my $versionstring=< 1); -# Variables -my ($file1,$file2,$diff,$diffbase,$answer,$options,$infile,$append,$dirname,$cwd); -my (@files,@ldoptions,@tmpfiles,@ptmpfiles,@difffiles); # , - -Getopt::Long::Configure('pass_through','bundling'); - -GetOptions('revision|r:s' => \@revs, - 'cvs' => \$cvs, - 'rcs' => \$rcs, - 'svn' => \$svn, - 'git' => \$git, - 'dir|d:s' => \$dir, - 'fast' => \$fast, - 'so' => \$so, - 'postscript|ps' => \$postscript, - 'pdf' => \$pdf, - 'force' => \$force, - 'version' => \$version, - 'help|h' => \$help); - -if ( $help ) { - pod2usage(1) ; -} - -if ( $version ) { - die $versionstring ; -} - -if ( $so ) { - $latexdiff='latexdiff-so'; -} -if ( $fast ) { - die "Cannot specify more than one of --fast or --so " if ($so); - $latexdiff='latexdiff-fast'; -} - -if ( $cvs ) { - $vc="CVS"; -} -if ( $rcs ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="RCS"; -} -if ( $svn ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="SVN"; -} -if ( $git ) { - die "Cannot specify more than one of --cvs, --rcs, --svn or --git." if ($vc); - $vc="GIT"; -} - - -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -r option -if ( @revs && ( -f $revs[$#revs] || $revs[$#revs] =~ /^-/ ) ) { - unshift @ARGV,$revs[$#revs]; - $revs[$#revs]=""; -} -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -d option -if ( defined($dir) && ( -f $dir || $dir =~ /^-/ ) ) { - unshift @ARGV,$dir; - $dir=""; -} - -#print "DEBUG: latexdiff-vc command line: ", join(" ",@ARGV), "\n"; - -$file2=pop @ARGV; -( defined($file2) && $file2 =~ /\.(tex|bbl)$/ ) or pod2usage("Must specify at least one tex or bbl file"); - -if (! $vc && scalar(@revs)>0 ) { - # have to guess $vc - # check whether we have a special name - if ( $0 =~ /-cvs$/ ) { - $vc="CVS"; - } elsif ( $0 =~ /-rcs$/ ) { - $vc="RCS"; - } elsif ( $0 =~ /-svn$/ ) { - $vc="SVN"; - } elsif ( $0 =~ /-git$/ ) { - $vc="GIT"; - } elsif ( -e "CVSROOT" || defined($ENV{"CVSROOT"}) ) { - print STDERR "Guess you are using CVS ...\n"; - $vc="CVS"; - } elsif ( -e "$file2,v" ) { - print STDERR "Guess you are using RCS ...\n"; - $vc="RCS"; - } elsif ( -d ".svn" ) { - print STDERR "Guess you are using SVN ...\n"; - $vc="SVN"; - } elsif ( -d ".git" ) { - print STDERR "Guess you are using GIT ...\n"; - $vc="GIT"; - } else { - print STDERR "Cannot figure out version control system, so I default to CVS\n"; - $vc="CVS"; - } -} - -if (defined($dir) && $dir=~/^\.\/?/ ) { - print STDERR "You wrote -dir=. but you do not really like to do that, do you ?\n"; - exit 10 -} - -if ( scalar(@revs)>0 ) { - if ( $vc eq "CVS" ) { - $diffcmd = "cvs diff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "RCS" ) { - $diffcmd = "rcsdiff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "SVN" ) { - $diffcmd = "svn diff -r "; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "GIT" ) { - $diffcmd = "git diff -r --relative --no-prefix "; - $patchcmd = "patch -R -p0"; - # alternatively: - # $diffcmd = "git diff "; - # $patchcmd = "patch -R -p1"; - } else { - print STDERR "Unknown versioning system $vc \n"; - exit 10; - } -} - - -# make file list (last arguments), initial arguments have to be passed to latexdiff -# We assume an argument is a valid file rather than a latexdiff argument -# if it has extension .tex or .bbl - -@files=($file2); -while( $file1=pop @ARGV ) { - if ( $file1 =~ /\.(tex|bbl)$/ ) { - # $file1 looks like a valid file name and is prepended to file list - unshift @files, $file1 ; - } else { - # $file1 looks like an option for latexdiff, push it back to argument stack - unshift @ldoptions, $file1 ; - } -} - -if ( scalar(@revs) == 0 ) { - pod2usage("When -r option is not used, two .tex files (old and new) must be given on the command line") unless @files==2; - # compare two files - $file1=shift @files ; -} - -if ( scalar(@revs) == 2 ) { - $append = "-diff$revs[0]-$revs[1]"; -} elsif ( scalar(@revs) == 1 || $revs[0] ) { - $append = "-diff$revs[0]"; -} else { - $append = "-diff"; -} - -if ( defined ($dir) && ! $dir ) { - # bare -d option => choose directory name - ($dir=$append) =~ s/^-//; -} - -if ( ($vc eq "SVN" || $vc eq "CVS") && scalar(@revs)) { - length($revs[$#revs]) > 0 or $revs[$#revs]="HEAD"; - length($revs[0]) > 0 or $revs[0]="HEAD"; -} - -#exit ; - - -# cycle through all files - -@difffiles=(); -while ( $infile=$file2=shift @files ) { - print STDERR "Working on $infile \n"; - if ( scalar(@revs) == 1 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - push @tmpfiles,$file1; - # compare file with previous version ($revs[0]="") or specified version - ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; - if (system("$diffcmd$revs[0] \"$infile\" | $patchcmd -o\"$file1\"")==0 and -z $file1 ) { - # no differences detected, i.e. file is equal to current version - copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; - } - } elsif ( scalar(@revs) == 2 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - $file2 =~ s/\.(tex|bbl)/-newtmp-$$.$1/ ; - push @tmpfiles,$file2; - if (system("$diffcmd$revs[1] $infile | $patchcmd -o$file2")==0 and -z $file2 ) { - copy($infile,$file2) || die "copy($infile,$file2) failed: $!"; - } - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; - }; - } - - if ( -z $file1 || -z $file2) { - print STDERR "One or both of the files to compare are empty. Possibly something went wrong in the retrieval of older versions. Aborting ...\n" ; - exit(10); - } - - # Get name of difference file - if ( defined($dir) ) { - $diff="$dir/$infile" ; - } else { - ($diff=$infile) =~ s/\.(tex|bbl)$/$append.$1/ ; - } - # make directories if needed - $dirname=dirname($diff) ; - system("mkdir -p $dirname") unless ( -e $dirname ); - - # Remaining options are passed to latexdiff - $options = join(" ",@ldoptions); - - if ( -e $diff && ! $force ) { - print STDERR "OK to overwrite existing file $diff (y/n)? "; - $answer = ; - unless ($answer =~ /^y/i ) { - unlink @tmpfiles; - die "Abort ... " ; - } - } - print "Running $latexdiff\n"; - unless ( system("$latexdiff $options \"$file1\" \"$file2\" > \"$diff\"") == 0 ) { - print STDERR "Something went wrong in $latexdiff. Deleting $diff and abort\n" ; unlink $diff ; exit(5) - }; - print "Generated difference file $diff\n"; - - if ( ( $postscript or $pdf ) and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff ) ) ) { - # save filename for later processing if postscript or pdf conversion is requested and either two-file mode was used (scalar(@revs)==0) or the diff file contains documentclass statement (ie. is a root document) - push @difffiles, $diff ; - } - - unlink @tmpfiles; -} - -foreach $diff ( @difffiles ) { - chomp($cwd=(`pwd`)); - if (defined($dir)) { - ( $diff =~ s/$dir\/?// ) ; - chdir $dir ; - } - @ptmpfiles=(); - ( $diffbase=$diff) =~ s/\.(tex)$// ; - - # adapt magically changebar styles to [pdftex] display driver if pdf output was selected - if ( $pdf ) { - system("sed \"s/Package\\[dvips\\]/Package[pdftex]/\" \"$diff\" > \"$diff.tmp$$\" ; \\mv \"$diff.tmp$$\" \"$diff\""); - } - print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n"; - - if ( system("grep -q \'^[^%]*\\\\bibliography\' \"$diff\"") == 0 ) { - if ( $postscript) { - system("latex --interaction=batchmode \"$diff\"; bibtex \"$diffbase\""); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } elsif ( $pdf ) { - system("pdflatex --interaction=batchmode \"$diff\"; bibtex \"$diffbase\""); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } - } - - if ( $postscript ) { - my $dvi="$diffbase.dvi"; - my $ps="$diffbase.ps"; - - system("latex --interaction=batchmode \"$diff\"; latex \"$diff\"; dvips -o $ps $dvi"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; - print "Generated postscript file $ps\n"; - } - elsif ( $pdf ) { - system("pdflatex --interaction=batchmode \"$diff\"; pdflatex \"$diff\""); - push @ptmpfiles, "$diffbase.aux","$diffbase.log"; - } - unlink @ptmpfiles; - chdir $cwd; -} - -# greptex returns 1 if regex is not matched in filename -# 0 if there is a match -sub greptex { - my ($regex,$filename)=@_; - my ($i)=0; - open (FH, $filename) or die("Couldn't open $filename: $!"); - while () { - next if /^\s*%/; # skip comment lines - if ( m/$regex/ ) { - close(FH); - return(0); - } - # only scan 25 lines - $i++; - last if $i>25 ; - } - close(FH); - return(1); -} - - -=head1 NAME - -latexdiff-vc - wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) - -=head1 SYNOPSIS - -B [ F ] [ F ] B<-r> [F] [B<-r> F] F [ F ...] - - or - -B [ F ] [ F ][ B<--postscript> | B<--pdf> ] F F - -=head1 DESCRIPTION - -I is a wrapper script that applies I to a -file, or multiple files under version control (CVS, RCS or SVN), and optionally runs the -sequence of C and C or C commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. - -=head1 OPTIONS - -=over 4 - -=item B<--rcs>, B<--svn>, B<--cvs>, or B<--git> - -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. - -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. - -=item B<-r>, B<-r> F or B<--revision>, B<--revision=>F - -Choose revision (under RCS, CVS, SVN or GIT). One or two B<-r> options can be -specified, and they result in different behaviour: - -=over 4 - -=item B -r F ... - -compares F with the most recent version checked into RCS. - -=item B -r F F ... - -compares F with revision F. - -=item B -r F -r F F ... - -compares revisions F and F of F. - -Multiple files can be specified for all of the above options. All files must have the -extension C<.tex>, though. - -=item B F F - -compares two files. - -=back - -The name of the difference file is generated automatically and -reported to stdout. - -=item B<-d> or B<--dir> B<-d> F or B<--dir=>F - -Rather than appending the string C and optionally the version -numbers given to the output-file, this will prepend a directory name C -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname F can be specified, which is prepended instead of C. - -=item B<--fast> or B<--so> - -Use C or C, respectively (instead of C). - -=item B<--ps> or B<--postscript> - -Generate postscript output from difference file. This will run the -sequence C on the difference file (do not use -this option in the rare cases, where three C commands are -required if you care about correct referencing). If the difference -file contains a C<\bibliography> tag, run the sequence C. - -=item B<--pdf> - -Generate pdf output from difference file using C. This will -run the sequence C on the difference file, or -C for files requiring bibtex. - -=item B<--force> - -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - -All other options are passed on to C. - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I uses external commands and is therefore -limited to Unix-like systems. It also requires the RCS version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. - -=head1 BUG REPORTING - - Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(option C<--version>) -. -=head1 AUTHOR - -Copyright (C) 2005,2012 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 -Contributors: S Utcke, H Bruyninckx - -=cut - diff --git a/latexdiff-1.0.3/latexdiff-vc.1 b/latexdiff-1.0.3/latexdiff-vc.1 deleted file mode 100644 index 6b8806d..0000000 --- a/latexdiff-1.0.3/latexdiff-vc.1 +++ /dev/null @@ -1,246 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF-VC 1" -.TH LATEXDIFF-VC 1 "2013-06-10" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff\-vc \- wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ] \fB\-r\fR [\fIrev1\fR] [\fB\-r\fR \fIrev2\fR] \fIfile1.tex\fR [ \fIfile2.tex\fR ...] -.PP -.Vb 1 -\& or -.Ve -.PP -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ][ \fB\-\-postscript\fR | \fB\-\-pdf\fR ] \fIold.tex\fR \fInew.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexdiff-vc\fR is a wrapper script that applies \fIlatexdiff\fR to a -file, or multiple files under version control (\s-1CVS\s0, \s-1RCS\s0 or \s-1SVN\s0), and optionally runs the -sequence of \f(CW\*(C`latex\*(C'\fR and \f(CW\*(C`dvips\*(C'\fR or \f(CW\*(C`pdflatex\*(C'\fR commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-\-rcs\fR, \fB\-\-svn\fR, \fB\-\-cvs\fR, or \fB\-\-git\fR" 4 -.IX Item "--rcs, --svn, --cvs, or --git" -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. -.Sp -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. -.IP "\fB\-r\fR, \fB\-r\fR \fIrev\fR or \fB\-\-revision\fR, \fB\-\-revision=\fR\fIrev\fR" 4 -.IX Item "-r, -r rev or --revision, --revision=rev" -Choose revision (under \s-1RCS\s0, \s-1CVS\s0, \s-1SVN\s0 or \s-1GIT\s0). One or two \fB\-r\fR options can be -specified, and they result in different behaviour: -.RS 4 -.IP "\fBlatexdiff-vc\fR \-r \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r file.tex ..." -compares \fIfile.tex\fR with the most recent version checked into \s-1RCS\s0. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 file.tex ..." -compares \fIfile.tex\fR with revision \fIrev1\fR. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \-r \fIrev2\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 -r rev2 file.tex ..." -compares revisions \fIrev1\fR and \fIrev2\fR of \fIfile.tex\fR. -.Sp -Multiple files can be specified for all of the above options. All files must have the -extension \f(CW\*(C`.tex\*(C'\fR, though. -.IP "\fBlatexdiff-vc\fR \fIold.tex\fR \fInew.tex\fR" 4 -.IX Item "latexdiff-vc old.tex new.tex" -compares two files. -.RE -.RS 4 -.Sp -The name of the difference file is generated automatically and -reported to stdout. -.RE -.IP "\fB\-d\fR or \fB\-\-dir\fR \fB\-d\fR \fIpath\fR or \fB\-\-dir=\fR\fIpath\fR" 4 -.IX Item "-d or --dir -d path or --dir=path" -Rather than appending the string \f(CW\*(C`diff\*(C'\fR and optionally the version -numbers given to the output-file, this will prepend a directory name \f(CW\*(C`diff\*(C'\fR -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname \fIpath\fR can be specified, which is prepended instead of \f(CW\*(C`diff\*(C'\fR. -.IP "\fB\-\-fast\fR or \fB\-\-so\fR" 4 -.IX Item "--fast or --so" -Use \f(CW\*(C`latexdiff\-fast\*(C'\fR or \f(CW\*(C`latexdiff\-so\*(C'\fR, respectively (instead of \f(CW\*(C`latexdiff\*(C'\fR). -.IP "\fB\-\-ps\fR or \fB\-\-postscript\fR" 4 -.IX Item "--ps or --postscript" -Generate postscript output from difference file. This will run the -sequence \f(CW\*(C`latex; latex; dvips\*(C'\fR on the difference file (do not use -this option in the rare cases, where three \f(CW\*(C`latex\*(C'\fR commands are -required if you care about correct referencing). If the difference -file contains a \f(CW\*(C`\ebibliography\*(C'\fR tag, run the sequence \f(CW\*(C`latex; -bibtex; latex; latex; dvips\*(C'\fR. -.IP "\fB\-\-pdf\fR" 4 -.IX Item "--pdf" -Generate pdf output from difference file using \f(CW\*(C`pdflatex\*(C'\fR. This will -run the sequence \f(CW\*(C`pdflatex; pdflatex\*(C'\fR on the difference file, or -\&\f(CW\*(C`pdflatex; bibtex; pdflatex; pdflatex\*(C'\fR for files requiring bibtex. -.IP "\fB\-\-force\fR" 4 -.IX Item "--force" -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. -.IP "\fB\-\-help\fR or \fB\-h\fR" 4 -.IX Item "--help or -h" -Show help text -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Show version number -.PP -All other options are passed on to \f(CW\*(C`latexdiff\*(C'\fR. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff-vc\fR uses external commands and is therefore -limited to Unix-like systems. It also requires the \s-1RCS\s0 version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. -.SH "BUG REPORTING" -.IX Header "BUG REPORTING" -.Vb 6 -\& Please submit bug reports through -\&the latexdiff project page I or send -\&to I. Include the serial number of I -\&(option C<\-\-version>) -\&. -\&=head1 AUTHOR -.Ve -.PP -Copyright (C) 2005,2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -Contributors: S Utcke, H Bruyninckx diff --git a/latexdiff-1.0.3/latexdiff.1 b/latexdiff-1.0.3/latexdiff.1 deleted file mode 100644 index 03007f9..0000000 --- a/latexdiff-1.0.3/latexdiff.1 +++ /dev/null @@ -1,758 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF 1" -.TH LATEXDIFF 1 "2013-06-09" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff \- determine and markup differences between two latex files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff\fR [ \fB\s-1OPTIONS\s0\fR ] \fIold.tex\fR \fInew.tex\fR > \fIdiff.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Briefly, \fIlatexdiff\fR is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. -.PP -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "\f(CW\*(C`%DIF\ >\*(C'\fR" is appended to each added line, i.e. a -line present in \f(CW\*(C`new.tex\*(C'\fR but not in \f(CW\*(C`old.tex\*(C'\fR. Discarded lines - are deactivated by prepending "\f(CW\*(C`%DIF\ <\*(C'\fR". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file \f(CW\*(C`diff.tex\*(C'\fR will be similar to -\&\f(CW\*(C`new.tex\*(C'\fR. At the end of the preamble, the definitions for \fIlatexdiff\fR markup commands are inserted. -In differencing the main body of the text, \fIlatexdiff\fR attempts to -satisfy the following guidelines (in order of priority): -.IP "1." 3 -If both \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR are valid LaTeX, then the resulting -\&\f(CW\*(C`diff.tex\*(C'\fR should also be valid LateX. (\s-1NB\s0 If a few plain TeX commands -are used within \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR then \f(CW\*(C`diff.tex\*(C'\fR is not -guaranteed to work but usually will). -.IP "2." 3 -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -\&\f(CW\*(C`diff.tex\*(C'\fR. -.IP "3." 3 -If a changed passage contains text or text-producing commands, then -running \f(CW\*(C`diff.tex\*(C'\fR through LateX should produce output where added -and discarded passages are highlighted. -.IP "4." 3 -Where there are insignificant differences, e.g. in the positioning of -line breaks, \f(CW\*(C`diff.tex\*(C'\fR should follow the formatting of \f(CW\*(C`new.tex\*(C'\fR -.PP -For differencing the same algorithm as \fIdiff\fR is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, \f(CW\*(C`\ecaption\*(C'\fR and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write -.PP -.Vb 1 -\& \esection{\etextem{This is an emphasized section title}} -.Ve -.PP -and not -.PP -.Vb 1 -\& \esection {\etextem{This is an emphasized section title}} -.Ve -.PP -or -.PP -.Vb 1 -\& \esection\etextem{This is an emphasized section title} -.Ve -.PP -even though all varieties are the same to LaTeX (but see -\&\fB\-\-allow\-spaces\fR option which allows the second variety). -.PP -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the \s-1PICTUREENV\s0 configuration variable, set by -default to \f(CW\*(C`picture\*(C'\fR and \f(CW\*(C`DIFnomarkup\*(C'\fR environments; see \fB\-\-config\fR -option). The latter environment (\f(CW\*(C`DIFnomarkup\*(C'\fR) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by \f(CW\*(C`\ebegin{DIFnomarkup}\*(C'\fR and \f(CW\*(C`\eend{DIFnomarkup}\*(C'\fR. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, -.PP -\&\f(CW\*(C`\enewenvironment{DIFnomarkup}{}{}\*(C'\fR -.PP -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. -.PP -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. -.PP -All markup commands inserted by \fIlatexdiff\fR begin with "\f(CW\*(C`\eDIF\*(C'\fR". Added -blocks containing words, commands or comments which are in \f(CW\*(C`new.tex\*(C'\fR -but not in \f(CW\*(C`old.tex\*(C'\fR are marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR and \f(CW\*(C`\eDIFaddend\*(C'\fR. -Discarded blocks are marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR. -Within added blocks all text is highlighted with \f(CW\*(C`\eDIFadd\*(C'\fR like this: -\&\f(CW\*(C`\eDIFadd{Added text block}\*(C'\fR -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces \*(L"{\*(R" and \*(L"}\*(R" are never put within -the scope of \f(CW\*(C`\eDIFadd\*(C'\fR. Added comments are marked by prepending -"\f(CW\*(C`%DIF\ >\ \*(C'\fR". -.PP -Within deleted blocks text is highlighted with \f(CW\*(C`\eDIFdel\*(C'\fR. Deleted -comments are marked by prepending "\f(CW\*(C`%DIF\ <\ \*(C'\fR\*(L". Non-safe command -and curly braces within deleted blocks are commented out with -\&\*(R"\f(CW\*(C`%DIFDELCMD\ <\ \*(C'\fR". -.SH "OPTIONS" -.IX Header "OPTIONS" -.SS "Preamble" -.IX Subsection "Preamble" -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. -.IP "\fB\-\-type=markupstyle\fR or \fB\-t markupstyle\fR" 4 -.IX Item "--type=markupstyle or -t markupstyle" -Add code to preamble for selected markup style. This option defines -\&\f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands. -Available styles: -.Sp -\&\f(CW\*(C`UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR\*(C'\fR -.Sp -[ Default: \f(CW\*(C`UNDERLINE\*(C'\fR ] -.IP "\fB\-\-subtype=markstyle\fR or \fB\-s markstyle\fR" 4 -.IX Item "--subtype=markstyle or -s markstyle" -Add code to preamble for selected style for bracketing -commands (e.g. to mark changes in margin). This option defines -\&\f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR commands. -Available styles: \f(CW\*(C`SAFE MARGINAL COLOR DVIPSCOL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`SAFE\*(C'\fR ] -.IP "\fB\-\-floattype=markstyle\fR or \fB\-f markstyle\fR" 4 -.IX Item "--floattype=markstyle or -f markstyle" -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -\&\f(CW\*(C`\eDIF...FL\*(C'\fR commands. -Available styles: \f(CW\*(C`FLOATSAFE TRADITIONALSAFE IDENTICAL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`FLOATSAFE\*(C'\fR ] -.IP "\fB\-\-encoding=enc\fR or \fB\-e enc\fR" 4 -.IX Item "--encoding=enc or -e enc" -Specify encoding of old.tex and new.tex. Typical encodings are -\&\f(CW\*(C`ascii\*(C'\fR, \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR, \f(CW\*(C`latin9\*(C'\fR. A list of available encodings can be -obtained by executing -.Sp -\&\f(CW\*(C`perl \-MEncode \-e \*(Aqprint join ("\en",Encode\-\*(C'\fRencodings( \*(L":all\*(R" )) ;' > -.Sp -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation \f(CW\*(C`\eusepackage[..]{inputenc}\*(C'\fR in which case the -encoding chosen by this command is asssumed. Note that \s-1ASCII\s0 (standard -latex) is a subset of utf8] -.IP "\fB\-\-preamble=file\fR or \fB\-p file\fR" 4 -.IX Item "--preamble=file or -p file" -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -\&\f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFadd{..}, -\&\eDIFdelbegin,\eDIFdelend,\eDIFdel{..},\*(C'\fR -and varieties for use within floats -\&\f(CW\*(C`\eDIFaddbeginFL, \eDIFaddendFL, \eDIFaddFL{..}, -\&\eDIFdelbeginFL, \eDIFdelendFL, \eDIFdelFL{..}\*(C'\fR -(If this option is set \fB\-t\fR, \fB\-s\fR, and \fB\-f\fR options -are ignored.) -.IP "\fB\-\-packages=pkg1,pkg2,..\fR" 4 -.IX Item "--packages=pkg1,pkg2,.." -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for \f(CW\*(C`\eusepackage\*(C'\fR commands. -Use of the \fB\-\-packages\fR option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use \fB\-\-packages=none\fR. -The following packages trigger special behaviour: -.RS 4 -.ie n .IP """amsmath""" 8 -.el .IP "\f(CWamsmath\fR" 8 -.IX Item "amsmath" -Configuration variable amsmath is set to \f(CW\*(C`align*\*(C'\fR (Default: \f(CW\*(C`eqnarray*\*(C'\fR) -.ie n .IP """endfloat""" 8 -.el .IP "\f(CWendfloat\fR" 8 -.IX Item "endfloat" -Ensure that \f(CW\*(C`\ebegin{figure}\*(C'\fR and \f(CW\*(C`\eend{figure}\*(C'\fR always appear by themselves on a line. -.ie n .IP """hyperref""" 8 -.el .IP "\f(CWhyperref\fR" 8 -.IX Item "hyperref" -Change name of \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands to \f(CW\*(C`\eDIFaddtex\*(C'\fR and \f(CW\*(C`\eDIFdeltex\*(C'\fR and -define new \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). -.RE -.RS 4 -.Sp -[ Default: scan the preamble for \f(CW\*(C`\e\eusepackage\*(C'\fR commands to determine - loaded packages.] -.RE -.IP "\fB\-\-show\-preamble\fR" 4 -.IX Item "--show-preamble" -Print generated or included preamble commands to stdout. -.SS "Configuration" -.IX Subsection "Configuration" -.ie n .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-safecmd=exclude-file or -A exclude-file or --exclude-safecmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-safecmd=replace\-file\fR" 4 -.IX Item "--replace-safecmd=replace-file" -.ie n .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-safecmd=append-file or -a append-file or --append-safecmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a \f(CW\*(C`\eDIFadd\*(C'\fR or \f(CW\*(C`\eDIFdel\*(C'\fR command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -\&\*(L"\e\*(R" of the command is not included. -The \fB\-\-exclude\-safecmd\fR and \fB\-\-append\-safecmd\fR options can be combined with the \-\fB\-\-replace\-safecmd\fR -option and can be used repeatedly to add cumulatively to the lists. - \fB\-\-exclude\-safecmd\fR -and \fB\-\-append\-safecmd\fR can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus \*(L"\e,\*(R". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. -.ie n .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-textcmd=exclude-file or -X exclude-file or --exclude-textcmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-textcmd=replace\-file\fR" 4 -.IX Item "--replace-textcmd=replace-file" -.ie n .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-textcmd=append-file or -x append-file or --append-textcmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for \fB\-\-exclude\-safecmd\fR directly above for further details. -.IP "\fB\-\-replace\-context1cmd=replace\-file\fR" 4 -.IX Item "--replace-context1cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-context1cmd=append-file or =item --append-context1cmd=cmd1,cmd2,..." -.PD -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \ecaption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. -.IP "\fB\-\-replace\-context2cmd=replace\-file\fR" 4 -.IX Item "--replace-context2cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=""cmd1,cmd2,...""\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.el .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=``cmd1,cmd2,...''\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.IX Item "--append-context2cmd=append-file or =item --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." -.IP "\fB\-\-config var1=val1,var2=val2,...\fR or \fB\-c var1=val1,..\fR" 4 -.IX Item "--config var1=val1,var2=val2,... or -c var1=val1,.." -.IP "\fB\-c configfile\fR" 4 -.IX Item "-c configfile" -.PD -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): -.Sp -\&\f(CW\*(C`MINWORDSBLOCK\*(C'\fR (integer) -.Sp -\&\f(CW\*(C`FLOATENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`PICTUREENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`MATHARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHARRREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`ARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`COUNTERCMD\*(C'\fR (RegEx) -.IP "\fB\-\-show\-safecmd\fR" 4 -.IX Item "--show-safecmd" -Print list of RegEx matching and excluding safe commands. -.IP "\fB\-\-show\-textcmd\fR" 4 -.IX Item "--show-textcmd" -Print list of RegEx matching and excluding commands with text argument. -.IP "\fB\-\-show\-config\fR" 4 -.IX Item "--show-config" -Show values of configuration variables. -.IP "\fB\-\-show\-all\fR" 4 -.IX Item "--show-all" -Combine all \-\-show commands. -.Sp -\&\s-1NB\s0 For all \-\-show commands, no \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR file needs to be specified, and no -differencing takes place. -.SS "Other configuration options:" -.IX Subsection "Other configuration options:" -.IP "\fB\-\-allow\-spaces\fR" 4 -.IX Item "--allow-spaces" -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). -.IP "\fB\-\-math\-markup=level\fR" 4 -.IX Item "--math-markup=level" -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): -.Sp -\&\f(CW\*(C`off\*(C'\fR or \f(CW0\fR: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. -.Sp -\&\f(CW\*(C`whole\*(C'\fR or \f(CW1\fR: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. -.Sp -\&\f(CW\*(C`coarse\*(C'\fR or \f(CW2\fR: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -.Sp -\&\f(CW\*(C`fine\*(C'\fR or \f(CW3\fR: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. -.IP "\fB\-\-disable\-citation\-markup\fR" 4 -.IX Item "--disable-citation-markup" -Suppress citation markup in styles using ulem (\s-1UNDERLINE\s0, -\&\s-1FONTSTRIKE\s0, \s-1CULINECHBAR\s0) -.IP "\fB\-\-enable\-citation\-markup\fR" 4 -.IX Item "--enable-citation-markup" -Protect citation commands in changed sections with \e\embox command [i.e. use default behaviour for ulem package for other packages] -.SS "Miscellaneous" -.IX Subsection "Miscellaneous" -.RS 4 -Output various status information to stderr during processing. -Default is to work silently. -.Sp -\&\fB\-\-driver=type\fR -.Sp -Choose driver for changebar package (only relevant for styles using - changebar: \s-1CCHANGEBAR\s0 \s-1CFONTCHBAR\s0 \s-1CULINECHBAR\s0 \s-1CHANGEBAR\s0). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] -.Sp -\&\fB\-\-ignore\-warnings\fR -.Sp -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to \f(CW\*(C`latexdiff\*(C'\fR but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. -.Sp -\&\fB\-\-label=label\fR or -\&\fB\-L label\fR -.Sp -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this \f(CW\*(C`\-L labelold \-L labelnew\*(C'\fR. -[Default: use the filename and modification dates for the label] -.Sp -\&\fB\-\-no\-label\fR -.Sp -Suppress inclusion of old and new file names as comment in output file -.Sp -\&\fB\-\-visble\-label\fR -.Sp -Include old and new filenames (or labels set with \-\-label option) as -visible output. -.Sp -\&\fB\-\-flatten\fR -.Sp -Replace \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within body by the content -of the files in their argument. If \f(CW\*(C`\eincludeonly\*(C'\fR is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. -\&\-\-flatten is applied recursively, so inputted files can contain further -\&\f(CW\*(C`\einput\*(C'\fR statements. -.Sp -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. -.Sp -\&\fB\-\-help\fR or -\&\fB\-h\fR -.Sp -Show help text -.Sp -\&\fB\-\-version\fR -.Sp -Show version number -.RE -.SS "Predefined styles" -.IX Subsection "Predefined styles" -.SS "Major types" -.IX Subsection "Major types" -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands \f(CW\*(C`\eDIFadd{...}\*(C'\fR and \f(CW\*(C`\eDIFdel{...}\*(C'\fR . -.ie n .IP """UNDERLINE""" 10 -.el .IP "\f(CWUNDERLINE\fR" 10 -.IX Item "UNDERLINE" -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). -.ie n .IP """CTRADITIONAL""" 10 -.el .IP "\f(CWCTRADITIONAL\fR" 10 -.IX Item "CTRADITIONAL" -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) -.ie n .IP """TRADITIONAL""" 10 -.el .IP "\f(CWTRADITIONAL\fR" 10 -.IX Item "TRADITIONAL" -Like \f(CW\*(C`CTRADITIONAL\*(C'\fR but without the use of color. -.ie n .IP """CFONT""" 10 -.el .IP "\f(CWCFONT\fR" 10 -.IX Item "CFONT" -Added text is blue and set in sans-serif, and discarded text is red and very small size. -.ie n .IP """FONTSTRIKE""" 10 -.el .IP "\f(CWFONTSTRIKE\fR" 10 -.IX Item "FONTSTRIKE" -Added tex is set in sans-serif, discarded text small and struck out -.ie n .IP """CCHANGEBAR""" 10 -.el .IP "\f(CWCCHANGEBAR\fR" 10 -.IX Item "CCHANGEBAR" -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). -.ie n .IP """CFONTCHBAR""" 10 -.el .IP "\f(CWCFONTCHBAR\fR" 10 -.IX Item "CFONTCHBAR" -Like \f(CW\*(C`CFONT\*(C'\fR but with additional changebars (Requires color and changebar packages). -.ie n .IP """CULINECHBAR""" 10 -.el .IP "\f(CWCULINECHBAR\fR" 10 -.IX Item "CULINECHBAR" -Like \f(CW\*(C`UNDERLINE\*(C'\fR but with additional changebars (Requires color, ulem and changebar packages). -.ie n .IP """CHANGEBAR""" 10 -.el .IP "\f(CWCHANGEBAR\fR" 10 -.IX Item "CHANGEBAR" -No mark up of text, but mark margins with changebars (Requires changebar package). -.ie n .IP """INVISIBLE""" 10 -.el .IP "\f(CWINVISIBLE\fR" 10 -.IX Item "INVISIBLE" -No visible markup (but generic markup commands will still be inserted. -.SS "Subtypes" -.IX Subsection "Subtypes" -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR) -.ie n .IP """SAFE""" 10 -.el .IP "\f(CWSAFE\fR" 10 -.IX Item "SAFE" -No additional markup (Recommended choice) -.ie n .IP """MARGIN""" 10 -.el .IP "\f(CWMARGIN\fR" 10 -.IX Item "MARGIN" -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard \f(CW\*(C`\emarginpar\*(C'\fR command \- note that this sometimes moves somewhat -from the intended position. -.ie n .IP """COLOR""" 10 -.el .IP "\f(CWCOLOR\fR" 10 -.IX Item "COLOR" -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). -.ie n .IP """DVIPSCOL""" 10 -.el .IP "\f(CWDVIPSCOL\fR" 10 -.IX Item "DVIPSCOL" -An alternative way of marking added passages in blue, and deleted ones in red. Note -that \f(CW\*(C`DVIPSCOL\*(C'\fR 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). -.SS "Float Types" -.IX Subsection "Float Types" -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. -.ie n .IP """FLOATSAFE""" 10 -.el .IP "\f(CWFLOATSAFE\fR" 10 -.IX Item "FLOATSAFE" -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is \f(CW\*(C`MARGIN\*(C'\fR as \f(CW\*(C`\emarginpar\*(C'\fR does not work properly within floats. -.ie n .IP """TRADITIONALSAFE""" 10 -.el .IP "\f(CWTRADITIONALSAFE\fR" 10 -.IX Item "TRADITIONALSAFE" -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \e[ and \e] and the deleted text is set in scriptscript size. This float type should always be used with the \f(CW\*(C`TRADITIONAL\*(C'\fR and \f(CW\*(C`CTRADITIONAL\*(C'\fR markup types as the \efootnote command does not work properly in floating environments. -.ie n .IP """IDENTICAL""" 10 -.el .IP "\f(CWIDENTICAL\fR" 10 -.IX Item "IDENTICAL" -Make no difference between the main text and floats. -.SS "Configuration Variables" -.IX Subsection "Configuration Variables" -.ie n .IP """MINWORDSBLOCK""" 10 -.el .IP "\f(CWMINWORDSBLOCK\fR" 10 -.IX Item "MINWORDSBLOCK" -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than \f(CW\*(C`MINWORDSBLOCK\*(C'\fR to the preceding added and discarded parts. -.Sp -[ Default: 3 ] -.ie n .IP """FLOATENV""" 10 -.el .IP "\f(CWFLOATENV\fR" 10 -.IX Item "FLOATENV" -Environments whose name matches the regular expression in \f(CW\*(C`FLOATENV\*(C'\fR are -considered floats. Within these environments, the \fIlatexdiff\fR markup commands -are replaced by their \s-1FL\s0 variaties. -.Sp -[ Default: \f(CW\*(C`(?:figure|table|plate)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """PICTUREENV""" 10 -.el .IP "\f(CWPICTUREENV\fR" 10 -.IX Item "PICTUREENV" -Within environments whose name matches the regular expression in \f(CW\*(C`PICTUREENV\*(C'\fR -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). -.Sp -[ Default: \f(CW\*(C`(?:picture|DIFnomarkup)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """MATHENV"",""MATHREPL""" 10 -.el .IP "\f(CWMATHENV\fR,\f(CWMATHREPL\fR" 10 -.IX Item "MATHENV,MATHREPL" -If both \ebegin and \eend for a math environment (environment name matching \f(CW\*(C`MATHENV\*(C'\fR -or \e[ and \e]) -are within the same deleted block, they are replaced by a \ebegin and \eend commands for \f(CW\*(C`MATHREPL\*(C'\fR -rather than being commented out. -.Sp -[ Default: \f(CW\*(C`MATHENV\*(C'\fR=\f(CW\*(C`(?:displaymath|equation)\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`displaymath\*(C'\fR\ ] -.ie n .IP """MATHARRENV"",""MATHARRREPL""" 10 -.el .IP "\f(CWMATHARRENV\fR,\f(CWMATHARRREPL\fR" 10 -.IX Item "MATHARRENV,MATHARRREPL" -as \f(CW\*(C`MATHENV\*(C'\fR,\f(CW\*(C`MATHREPL\*(C'\fR but for equation arrays -.Sp -[ Default: \f(CW\*(C`MATHARRENV\*(C'\fR=\f(CW\*(C`eqnarray\e*?\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`eqnarray\*(C'\fR\ ] -.ie n .IP """ARRENV""" 10 -.el .IP "\f(CWARRENV\fR" 10 -.IX Item "ARRENV" -If a match to \f(CW\*(C`ARRENV\*(C'\fR is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by \f(CW\*(C`\embox{\*(C'\fR...\f(CW\*(C`}\*(C'\fR. This is necessary as underlining does not work within inlined array environments. -.Sp -[ Default: \f(CW\*(C`ARRENV\*(C'\fR=\f(CW\*(C`(?:array|[pbvBV]matrix)\*(C'\fR\ -.ie n .IP """COUNTERCMD""" 10 -.el .IP "\f(CWCOUNTERCMD\fR" 10 -.IX Item "COUNTERCMD" -If a command in a deleted block which is also in the textcmd list matches \f(CW\*(C`COUNTERCMD\*(C'\fR then an -additional command \f(CW\*(C`\eaddtocounter{\*(C'\fR\fIcntcmd\fR\f(CW\*(C`}{\-1}\*(C'\fR, where \fIcntcmd\fR is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. -.Sp -[ Default: \f(CW\*(C`COUNTERCMD\*(C'\fR=\f(CW\*(C`(?:footnote|part|section|subsection\*(C'\fR ... -.Sp -\&\f(CW\*(C`|subsubsection|paragraph|subparagraph)\*(C'\fR ] -.SH "COMMON PROBLEMS" -.IX Header "COMMON PROBLEMS" -.IP "Citations result in overfull boxes" 10 -.IX Item "Citations result in overfull boxes" -There is an incompatibility between the \f(CW\*(C`ulem\*(C'\fR package, which \f(CW\*(C`latexdiff\*(C'\fR uses for underlining and striking out in the \s-1UNDERLINE\s0 style, -the default style. In order to be able to mark up citations properly, they are placed with an \f(CW\*(C`\embox\*(C'\fR 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: -.Sp -1. Use \f(CW\*(C`COLOR\*(C'\fR or \f(CW\*(C`DVIPSCOL\*(C'\fR subtype markup (option \f(CW\*(C`\-s COLOR\*(C'\fR): 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. -.Sp -2. Choose option \f(CW\*(C`\-\-disable\-citation\-markup\*(C'\fR 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) -.IP "Changes in complicated mathematical equations result in latex processing errors" 10 -.IX Item "Changes in complicated mathematical equations result in latex processing errors" -Try options \f(CW\*(C`\-\-math\-markup=whole\*(C'\fR. If even that fails, you can turn off mark up for equations with \f(CW\*(C`\-\-math\-markup=off\*(C'\fR. -.SH "BUGS" -.IX Header "BUGS" -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. -.PP -Please submit bug reports on the latexdiff project page \fIhttp://latexdiff.berlios.de\fR, -send them to user discussion list \f(CW\*(C`latexdiff\-users@lists.berlios,de\*(C'\fR (prior subscription -to list required, also on project webpage) -or send them to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexdiff\fR -(from comments at the top of the source or use \fB\-\-version\fR). 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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexrevise, latexdiff-vc -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff\fR does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than \s-1ASCII\s0 or \s-1UTF\-8\s0 are processed, Perl 5.8 or higher is required. -.PP -The standard version of \fIlatexdiff\fR requires installation of the Perl package -\&\f(CW\*(C`Algorithm::Diff\*(C'\fR (available from \fIwww.cpan.org\fR \- -\&\fIhttp://search.cpan.org/~nedkonz/Algorithm\-Diff\-1.15\fR) but a stand-alone -version, \fIlatexdiff-so\fR, which has this package inlined, is available, too. -\&\fIlatexdiff-fast\fR requires the \fIdiff\fR command to be present. -.SH "AUTHOR" -.IX Header "AUTHOR" -Version 1.0.2 -Copyright (C) 2004\-2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -.PP -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who send in bug reports, feature suggestions, and other feedback. -.SH "POD ERRORS" -.IX Header "POD ERRORS" -Hey! \fBThe above document had some coding errors, which are explained below:\fR -.IP "Around line 2956:" 4 -.IX Item "Around line 2956:" -=over should be: '=over' or '=over positive_number' -.Sp -You can't have =items (as at line 2962) unless the first thing after the =over is an =item diff --git a/latexdiff-1.0.3/latexrevise b/latexdiff-1.0.3/latexrevise deleted file mode 100755 index 0f333fb..0000000 --- a/latexdiff-1.0.3/latexrevise +++ /dev/null @@ -1,539 +0,0 @@ -#!/usr/bin/env perl -# latexrevise - takes output file of latexdiff and removes either discarded -# or appended passages, then deletes all other latexdiff markup -# -# Copyright (C) 2004 F J Tilmann (tilmann@gfz-potsdam.de, ftilmann@users.berlios.de) -# -# Project webpages: http://latexdiff.berlios.de/ -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# Note: version number now keeping up with latexdiff -# Version 1.0.2 Option --version -# Version 1.0.1 no changes to latexrevise -# Version 0.3 Updated for compatibility with latexdiff 0.3 output (DIFAUXCMD removal) -# Version 0.1 First public release - -use Getopt::Long ; -use strict; -use warnings; - -my $versionstring=< \$accept, - 'decline|d'=> \$decline, - 'simplify|s' => \$simplify, - 'comment|c=s' => \$comment, - 'comment-environment|e=s' => \$comenv, - 'markup|m=s' => \$markup, - 'markup-environment|n=s' => \$markenv, - 'no-warnings|q' => \$verbose, - 'version' => \$version, - 'verbose|V' => \$verbose, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - -if ( $version ) { - die $versionstring ; -} - - -if ( ($accept && $decline) || ($accept && $simplify) || ($decline && $simplify) ) { - die '-a,-d and -s options are mutually axclusive. Type latexrevise -h to get more help.'; -} - - - -print STDERR "ACCEPT mode\n" if $verbose && $accept; -print STDERR "DECLINE mode\n" if $verbose && $decline; -print STDERR "SIMPLIFY mode. WARNING: The output will not normally be valid latex,\n" if $verbose && $simplify; - -# Slurp old and new files -{ - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $input=<>; -} - -# split into parts -($preamble,$body,$post)=splitdoc($input,'\begin{document}','\end{document}'); - -if (length $preamble && ( $accept || $decline ) ) { - # - # WORK ON PREAMBLE - # - # (compare subroutine linediff in latexdiff to make sure correct strings are used) - - # remove extra commands added to preamble by latexdiff - $preamble =~ s/${PREAMBLEXTBEG}.*?${PREAMBLEXTEND}\n{0,1}//smg ; - - if ( $accept ) { - # delete mark up in appended lines - $preamble =~ s/^(.*) %DIF > $/$1/mg ; - } elsif ( $decline ) { - # delete appended lines - # $preamble =~ s/^(.*) %DIF > $//mg ; - $preamble =~ s/^(.*) %DIF > \n//mg ; - # delete markup in deleted lines - $preamble =~ s/^%DIF < //mg ; - } - # remove any remaining DIF markups - #$preamble =~ s/%DIF.*$//mg ; - $preamble =~ s/%DIF.*?\n//sg ; -} -#print $preamble ; - -# -# WORK ON BODY -# -if ($accept) { - # remove ADDMARKOPEN, ADDMARKCLOSE tokens - @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/$1/sg; - # remove text flanked by DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}//sg; - # remove markup of added comments - $body =~ s/%${ADDCOMMENT}(.*?)$/%$1/mg ; - # remove deleted comments (full line) - $body =~ s/^%${DELCOMMENT}.*?\n//mg ; - # remove deleted comments (part of line) - $body =~ s/%${DELCOMMENT}.*?$//mg ; -} -elsif ( $decline) { - # remove DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/$1/sg; - # remove text flanked by ADDMARKOPEN, ADDMARKCLOSE tokens - # as latexdiff algorithm keeps the formatting and white spaces - # of the new text, sometimes whitespace might be inserted or - # removed inappropriately. We try to guess whether this has - # happened - - # Mop up tokens. This must be done already now as otherwise - # detection of white-space problems does not work - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - # remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - $cnt += $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - while ( $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/s ) { - $prematch=$`; - $postmatch=$'; - checkpure($1); - if ( $prematch =~ /\w$/s && $postmatch =~ /^\w/ ) { - # apparently no white-space between word=>Insert white space - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/ /s ; - } - elsif ( $prematch =~ /\s$/s && $postmatch =~ /^[.,;:]/ ) { - # space immediately before one of ".,:;" => remove this space - $body =~ s/\s${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s ; - } - else { - # do not insert or remove any extras - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s; - } - } -# Alternative without special cases treatment -# @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; -# checkpure(@matches); -# $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//sg; - # remove markup of deleted comments - $body =~ s/%${DELCOMMENT}(.*?)$/%$1/mg ; - # remove added comments (full line) - $body =~ s/^%${ADDCOMMENT}.*?\n//mg ; - # remove added comments (part of line) - $body =~ s/%${ADDCOMMENT}.*?$//mg ; -} - -# remove any remaining tokens -if ( $accept || $decline || $simplify ) { - # first substitution command deals with special case of added paragraph - $cnt = $body =~ s/${ADDOPEN}($pat4)\n${ADDCLOSE}\n/$1\n/sg; - $cnt += $body =~ s/${ADDOPEN}($pat4)${ADDCLOSE}/$1/sg; - $cnt==0 || warn 'Remaining $ADDOPEN tokens in DECLINE mode\n' unless ( $quiet || $accept || $simplify ); -} -if ($accept || $simplify ) { - # Note: in decline mode these commands have already been removed above - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - #### remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - # $cnt += - $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - #### remove deleted comments - ###$cnt += $body =~ s/${DIFDELCMD}.*?$//mg ; - $cnt==0 || warn 'Remaining $DELOPEN or $DIFDELCMD tokens in ACCEPT mode\n' unless ( $quiet || $simplify ); -} - -# Remove comment commands -if (defined($comment)) { - print STDERR "Removing \\$comment\{..\} sequences ..." if $verbose; - # protect $comments in comments by making them look different - $body =~ s/(%.*)${comment}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${comment}(?:\[${brat0}\])?\{${pat4}\}//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${comment}$2/mg ; -} -if (defined($comenv)) { - print STDERR "Removing $comenv environments ..." if $verbose; - $body =~ s/(%.*)${comenv}/$1${someword}/mg ; -## $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{\$comenv\}.*?\\end\{\$comenv\}//sg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${comenv}\}.*?\\end\{${comenv}\}\s*?\n//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${comenv}/mg ; -} - -if (defined($markup)) { - print STDERR "Removing \\$markup\{..\} cpmmands ..." if $verbose; - # protect $markups in comments by making them look different - $body =~ s/(%.*)${markup}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${markup}(?:\[${brat0}\])?\{(${pat4})\}/$1/sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${markup}$2/mg ; -} -if (defined($markenv)) { - print STDERR "Removing $markenv environments ..." if $verbose; - $body =~ s/(%.*)${markenv}/$1${someword}/mg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${markenv}\}\n?//sg; - $cnt += 0 + $body =~ s/\\end\{${markenv}\}\n?//sg; - print STDERR $cnt/2, " matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${markenv}/mg ; -} - - -if ( length $preamble ) { - print "$preamble\\begin{document}${body}\\end{document}$post"; -} else { - print $body; -} - -# checkpure(@matches) -# checks whether any of the strings in matches contains -# $ADDMARKOPEN, $ADDMARKCLOSE,$DELMARKOPEN, or $DELMARKCLOSE -# If so, die reporting nesting problems, otherwise return to caller -sub checkpure { - while (defined($_=shift)) { - if ( /$ADDMARKOPEN/ || /$ADDMARKCLOSE/ - || /$DELMARKOPEN/ || /$DELMARKCLOSE/ ) { - die <=0 && $j>$i ) { - $part1 = substr($text,0,$i) ; - $part2 = substr($text,$i+$l1,$j-$i-$l1); - $part3 = substr($text,$j+$l2) unless $j+$l2 >= length $text; - } else { - die "$word1 or $word2 not in the correct order or not present as a pair." - } - return ($part1,$part2,$part3); -} - - - -sub usage { - die <<"EOF"; -Usage: $0 [OPTIONS] [diff.tex] > revised.tex - -Read a file diff.tex (output of latexdiff), and remove its markup. -If no filename is given read from standard input. The command can be used -in ACCEPT, DECLINE, or SIMPLIFY mode, and be used to remove user-defined -latex commands from the input (see options -c, -e, -m, -n below). -In ACCEPT mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In DECLINE mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that latexrevise only pays attention to the \\DIFaddbegin, -\\DIFaddend, \\DIFdelbegin, and \\DIFdelend tokens and corresponding FL -varieties. All \\DIFadd and \\DIFdel commands (but not their content) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In SIMPLIFY mode all latexdiff markup is removed from the body of the text (after -\\begin{document}) except for \\DIFaddbegin, \\DIFaddend, \\DIFdelbegin, \\DIFdelend -tokens and the corresponding FL varieties of those commands. The result -will not in general be valid latex-code but might be easier to read and edit in -preparation for a subsequent run in ACCEPT or DECLINE mode. -In SIMPLIFY mode the preamble is left unmodified. - --a ---accept Run in ACCEPT mode (delete all blocks marked by \\DIFdelbegin - and \\DIFdelend). - --d ---decline Run in DECLINE mode (delete all blocks marked by \\DIFaddbegin - and \\DIFaddend). - --s ---simplify Run in SIMPLIFY mode (Keep all \\DIFaddbegin, \\DIFaddend, - \\DIFdelbegin, \\DIFdelend tokens, but remove all other latexdiff - markup from body. - -Note that the three mode options are mutually exclusive. If no mode option is given, -latexrevise simply removes user annotations and markup according to the following four -options. - - --c cmd ---comment=cmd Remove \\cmd{...}. cmd is supposed to mark some explicit - anotations which should be removed from the file before - release. - --e envir ---comment-environment=envir - Remove explicit annotation environments from the text, i.e. remove - \\begin{envir} - ... - \\end{envir} - blocks. - --m cmd ---markup=cmd Remove the markup command cmd but leave its argument, i.e. - turn \\cmd{abc} into abc. - --n envir ---markup-environment=envir - Similarly, remove \\begin{envir} and \\end{envir} commands, - but leave content of the environment in the text. - --q ---no-warnings Do not warn users about \\DIDadd{..} or \\DIFdel statements - which should not be there anymore - --V ---verbose Verbose output - -EOF -} - -=head1 NAME - -latexrevise - selectively remove markup and text from latexdiff output - -=head1 SYNOPSIS - -B [ B ] [ F ] > F - -=head1 DESCRIPTION - -I reads a file C (output of I), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in I, I, or I mode, or can be used to remove user-defined -latex commands from the input (see B<-c>, B<-e>, B<-m>, and B<-n> below). -In I mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In I mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that I only pays attention to the C<\DIFaddbegin>, -C<\DIFaddend>, C<\DIFdelbegin>, and C<\DIFdelend> tokens and corresponding FL -varieties. All C<\DIFadd> and C<\DIFdel> commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In I mode, C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend> -tokens and their corresponding C varieties are kept but all other markup (e.g. C and <\DIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in I or I mode. -In I mode the preamble is left unmodified. - -=head1 OPTIONS - -=over 4 - -=item B<-a> or B<--accept> - -Run in I mode (delete all blocks marked by C<\DIFdelbegin> and C<\DIFdelend>). - -=item B<-d> or B<--decline> - -Run in I mode (delete all blocks marked by C<\DIFaddbegin> -and C<\DIFaddend>). - -=item B<-s> or B<--simplify> - -Run in I mode (Keep all C<\DIFaddbegin>, C<\DIFaddend>, -C<\DIFdelbegin>, C<\DIFdelend> tokens, but remove all other latexdiff -markup from body). - -=back - -Note that the three mode options are mutually exclusive. If no mode option is given, -I simply removes user annotations and markup according to the following four -options. - -=over 4 - -=item B<-c cmd> or B<--comment=cmd> - -Remove C<\cmd{...}> sequences. C is supposed to mark some explicit -anotations which should be removed from the file before -release. - -=item B<-e envir> or B<--comment-environment=envir> - -Remove explicit annotation environments from the text, i.e. remove - - \begin{envir} - ... - \end{envir} - -blocks. - -=item B<-m cmd> or B<--markup=cmd> - -Remove the markup command C<\cmd> but leave its argument, i.e. -turn C<\cmd{abc}> into C. - -=item B<-n envir> or B<--markup-environment=envir> - -Similarly, remove C<\begin{envir}> and C<\end{envir}> commands but -leave content of the environment in the text. - - -=item B<-V> or B<--verbose> - -Verbose output - -=item B<-q> or B<--no-warnings> - -Do not warn users about C<\DIDadd{..}> or C<\DIFdel{..}> statements -which should have been removed already. - -=back - -=head1 BUGS - -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page I or send -to I. Include the serial number of I -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by I please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. - -Note that I gets confused by commented C<\begin{document}> or -C<\end{document}> statements - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting PERL v5 or higher. - -=head1 AUTHOR - -Copyright (C) 2004 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 - -=cut diff --git a/latexdiff-1.0.3/latexrevise.1 b/latexdiff-1.0.3/latexrevise.1 deleted file mode 100644 index 8b14197..0000000 --- a/latexdiff-1.0.3/latexrevise.1 +++ /dev/null @@ -1,235 +0,0 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.ie \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.el \{\ -. de IX -.. -.\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXREVISE 1" -.TH LATEXREVISE 1 "2013-01-27" "perl v5.14.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexrevise \- selectively remove markup and text from latexdiff output -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexrevise\fR [ \fB\s-1OPTIONS\s0\fR ] [ \fIdiff.tex\fR ] > \fIrevised.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexrevise\fR reads a file \f(CW\*(C`diff.tex\*(C'\fR (output of \fIlatexdiff\fR), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in \fI\s-1ACCEPT\s0\fR, \fI\s-1DECLINE\s0\fR, or \fI\s-1SIMPLIFY\s0\fR mode, or can be used to remove user-defined -latex commands from the input (see \fB\-c\fR, \fB\-e\fR, \fB\-m\fR, and \fB\-n\fR below). -In \fI\s-1ACCEPT\s0\fR mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In \fI\s-1DECLINE\s0\fR mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that \fIlatexrevise\fR only pays attention to the \f(CW\*(C`\eDIFaddbegin\*(C'\fR, -\&\f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR, and \f(CW\*(C`\eDIFdelend\*(C'\fR tokens and corresponding \s-1FL\s0 -varieties. All \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In \fI\s-1SIMPLIFY\s0\fR mode, \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR -tokens and their corresponding \f(CW\*(C`FL\*(C'\fR varieties are kept but all other markup (e.g. \f(CW\*(C`DIFadd\*(C'\fR and <\eDIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in \fI\s-1ACCEPT\s0\fR or \fI\s-1DECLINE\s0\fR mode. -In \fI\s-1SIMPLIFY\s0\fR mode the preamble is left unmodified. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-a\fR or \fB\-\-accept\fR" 4 -.IX Item "-a or --accept" -Run in \fI\s-1ACCEPT\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR). -.IP "\fB\-d\fR or \fB\-\-decline\fR" 4 -.IX Item "-d or --decline" -Run in \fI\s-1DECLINE\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR -and \f(CW\*(C`\eDIFaddend\*(C'\fR). -.IP "\fB\-s\fR or \fB\-\-simplify\fR" 4 -.IX Item "-s or --simplify" -Run in \fI\s-1SIMPLIFY\s0\fR mode (Keep all \f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, -\&\f(CW\*(C`\eDIFdelbegin\*(C'\fR, \f(CW\*(C`\eDIFdelend\*(C'\fR tokens, but remove all other latexdiff -markup from body). -.PP -Note that the three mode options are mutually exclusive. If no mode option is given, -\&\fIlatexrevise\fR simply removes user annotations and markup according to the following four -options. -.IP "\fB\-c cmd\fR or \fB\-\-comment=cmd\fR" 4 -.IX Item "-c cmd or --comment=cmd" -Remove \f(CW\*(C`\ecmd{...}\*(C'\fR sequences. \f(CW\*(C`cmd\*(C'\fR is supposed to mark some explicit -anotations which should be removed from the file before -release. -.IP "\fB\-e envir\fR or \fB\-\-comment\-environment=envir\fR" 4 -.IX Item "-e envir or --comment-environment=envir" -Remove explicit annotation environments from the text, i.e. remove -.Sp -.Vb 3 -\& \ebegin{envir} -\& ... -\& \eend{envir} -.Ve -.Sp -blocks. -.IP "\fB\-m cmd\fR or \fB\-\-markup=cmd\fR" 4 -.IX Item "-m cmd or --markup=cmd" -Remove the markup command \f(CW\*(C`\ecmd\*(C'\fR but leave its argument, i.e. -turn \f(CW\*(C`\ecmd{abc}\*(C'\fR into \f(CW\*(C`abc\*(C'\fR. -.IP "\fB\-n envir\fR or \fB\-\-markup\-environment=envir\fR" 4 -.IX Item "-n envir or --markup-environment=envir" -Similarly, remove \f(CW\*(C`\ebegin{envir}\*(C'\fR and \f(CW\*(C`\eend{envir}\*(C'\fR commands but -leave content of the environment in the text. -.IP "\fB\-V\fR or \fB\-\-verbose\fR" 4 -.IX Item "-V or --verbose" -Verbose output -.IP "\fB\-q\fR or \fB\-\-no\-warnings\fR" 4 -.IX Item "-q or --no-warnings" -Do not warn users about \f(CW\*(C`\eDIDadd{..}\*(C'\fR or \f(CW\*(C`\eDIFdel{..}\*(C'\fR statements -which should have been removed already. -.SH "BUGS" -.IX Header "BUGS" -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports through -the latexdiff project page \fIhttp://developer.berlios.de/projects/latexdiff/\fR or send -to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexrevise\fR -(from comments at the top of the source). If you come across latexdiff -output which is not processed correctly by \fIlatexrevise\fR please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. -.PP -Note that \fIlatexrevise\fR gets confused by commented \f(CW\*(C`\ebegin{document}\*(C'\fR or -\&\f(CW\*(C`\eend{document}\*(C'\fR statements -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexrevise\fR does not make use of external commands and thus should run -on any platform supporting \s-1PERL\s0 v5 or higher. -.SH "AUTHOR" -.IX Header "AUTHOR" -Copyright (C) 2004 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 diff --git a/latexdiff-1.0.4/COPYING b/latexdiff-1.0.4/COPYING deleted file mode 100644 index d6fa915..0000000 --- a/latexdiff-1.0.4/COPYING +++ /dev/null @@ -1,623 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - diff --git a/latexdiff-1.0.4/Makefile b/latexdiff-1.0.4/Makefile deleted file mode 100644 index 4546730..0000000 --- a/latexdiff-1.0.4/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# Modify these paths to the requirements of your own system -# For the current setting you will need root permission but -# it is perfectly acceptable to choose user directories -# -INSTALLPATH = /usr/local -INSTALLMANPATH = $(INSTALLPATH)/man -INSTALLEXECPATH = $(INSTALLPATH)/bin - -default: - @echo "To install stand-alone version type: make install" - @echo " (Note the standard version requires prior installation" - @echo " of the PERL package Algorithm::Diff available from " - @echo " the PERL archive www.cpan.org)" - @echo " " - @echo "To install fast version (using UNIX diff) type: make install fast " - @echo " " - @echo "To install the version which uses the system Algorithm::Diff package type: make install-ext" - @echo " " - -install: install-so - -install-ext: install-latexdiff install-latexrevise install-latexdiff-vc install-man - -install-so: install-latexdiff-so install-latexrevise install-latexdiff-vc install-man - -install-fast: install-latexdiff-fast install-latexrevise install-latexdiff-vc install-man - -install-man: - install latexrevise.1 latexdiff.1 latexdiff-vc.1 $(INSTALLMANPATH)/man1 - -install-latexdiff: - install latexdiff $(INSTALLEXECPATH) - -install-latexdiff-so: - if [ -e $(INSTALLEXECPATH)/latexdiff ]; then rm $(INSTALLEXECPATH)/latexdiff; fi - install latexdiff-so $(INSTALLEXECPATH) - cd $(INSTALLEXECPATH); ln -s latexdiff-so latexdiff - -install-latexdiff-fast: - if [ -e $(INSTALLEXECPATH)/latexdiff ]; then rm $(INSTALLEXECPATH)/latexdiff; fi - install latexdiff-fast $(INSTALLEXECPATH) - cd $(INSTALLEXECPATH); ln -s latexdiff-fast latexdiff - -install-latexrevise: - install latexrevise $(INSTALLEXECPATH) - -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 - -test-ext: - @echo "latexdiff example/example-draft.tex example/example-rev.tex (system Algorithm::Diff)" - ./latexdiff -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" - -test-so: - @echo "latexdiff example/example-draft.tex example/example-rev.tex (stand-alone version)" - ./latexdiff-so -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" - -test-fast: - @echo "latexdiff example/example-draft.tex example/example-rev.tex (stand-alone version)" - ./latexdiff-fast -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" diff --git a/latexdiff-1.0.4/README b/latexdiff-1.0.4/README deleted file mode 100644 index e9e1893..0000000 --- a/latexdiff-1.0.4/README +++ /dev/null @@ -1,108 +0,0 @@ -INTRODUCTION - -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -A rudimentary revision facilility is provided by another Perl script, -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). - -Project webpage: http://latexdiff.berlios.de/ -CTAN page: http://www.ctan.org/tex-archive/support/latexdiff - - -REQUIREMENTS - -Perl 5.8 or higher must be installed. - The latexdiff script makes use of the Perl package Algorithm::Diff (available -from www.cpan.org, current version 1.19). You can either install this package, or -use the standalone version of latexdiff, latexdiff-so, which has version 1.15 of -this package inlined and does not require external installation of -the package. Because latexdiff uses internal functions of Algorithm:Diff whose -calling format or availability can change without notice, the preferred method is -now to use the standalone version. - -As an alternative, latexdiff-fast has a modified version of Algorithm::Diff inlined, -which internally uses the UNIX diff command. This version is much faster but is dependent -on an external "diff" command. Subtle differences in the algorithm of Algorithm::Diff and -UNIX-diff mean that the resulting set of differences will generally not be the same as -for the standard latexdiff. In most practical cases, these differences are minor, though. - -INSTALLATION UNIX/LINUX - -The basic installation procedure is almost trivial: - -1. Copy latexdiff, latexrevise and latexdiff-vc into a directory which - is in the search path and make them executable. If the Algorithm::Diff - package is not installed, use latexdiff-so instead of latexdiff. - -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. - -The attached trivial Makefile contains example commands to carry out above -steps as root for a typical UNIX installation. Type - - make install (for the stand alone version) -or - make install-ext (for the version using the external Algorithm::Diff) -or - make install-fast (for the version using the UNIX 'diff' function for fast differencing) - -to get it rolling. You can type - - make test -or - make test-ext -or - make test-fast - -to test the respective versions on a brief example before installation. It will often be -as easy to carry out these steps manually instead of using the Makefile. - - -DOCUMENTATION: - -Usage instructions are in the manual latexdiff-man.pdf as well as the -man pages. - -CHANGELOGS: - -Check out the comment lines at the beginning of the perl scripts (latexdiff, latexdiff-vc, latexrevise) - -CONTRIBUTIONS - -The directory contrib contains code written by others relating to latexdiff. -Currently this directory contains: - -latexdiff-wrap (Author: V. Kuhlmann) An alternative wrapper script which can be used - instead of latexdiff-vc. Its main use is as a template for customised wrapper scripts. - -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 -extend latexdiff in a similar way: J. Paisley, N. Becker, K. Huebner - -LICENSE (also see file COPYING) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License Version 3 as published by -the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details (file LICENSE in the -distribution). - diff --git a/latexdiff-1.0.4/contrib/README.latexchanges b/latexdiff-1.0.4/contrib/README.latexchanges deleted file mode 100644 index 4a02765..0000000 --- a/latexdiff-1.0.4/contrib/README.latexchanges +++ /dev/null @@ -1,13 +0,0 @@ -latexchanges.py (Jan-Ake Larsson): -Here's a wrapper I wrote for latexdiff, intended as a drop-in -replacement for latex, when you have several numbered (or dated) -versions of a manuscript. My coauthors don't as a rule know what CVS or -SVN is, they simply use a number or date for the different versions. - -latexchanges replaces the current DVI with one that includes a -latexdiff to the last version. The last version is selected as the -TEX file in the same directory with the same prefix (up to a number -or a dot), that has an mtime immediately preceding the given TEX -file. - - diff --git a/latexdiff-1.0.4/contrib/latexchanges.py b/latexdiff-1.0.4/contrib/latexchanges.py deleted file mode 100644 index de7acbe..0000000 --- a/latexdiff-1.0.4/contrib/latexchanges.py +++ /dev/null @@ -1,67 +0,0 @@ -#! /bin/env python -# latexchanges -# -# Wrapper for latexdiff, intended as a drop-in replacement for latex, -# when you have several numbered (or dated) versions of a manuscript. -# My coauthors don't as a rule know what CVS or SVN is, they simply -# use a number or date for the different versions. -# -# latexchanges replaces the current DVI with one that includes a -# latexdiff to the last version. The last version is selected as the -# TEX file in the same directory with the same prefix (up to a number -# or a dot), that has an mtime immediately preceding the given TEX -# file. -# -# (I should probably add CVS version numbering too, at some point.) -# -# Copyright (C) 2009 by Jan-\AA{}ke Larsson -# Released under the terms of the GNU General Public License (GPL) -# Version 2. See http://www.gnu.org/ for details. -# -# Please do provide patches and bug reports, but remember: if it -# breaks, you get to keep the pieces. -# -# Jan-\AA{}ke Larsson -# Sept 16 2009 - -from os import listdir,system,stat -from sys import argv -from re import split - -name="" -newarg=[] - -# Find filename argument -for i in range(1,len(argv)): - if argv[i][-4:]==".tex": - basename=split('[0-9.]',argv[i])[0] - name=argv[i][:-4] - newarg.append(name+".changes.tex") - else: - newarg.append(argv[i]) - -if name: - print "Filename",name+".tex" - print "Prefix is",basename - # Find last archived version - mtime=stat(name+".tex").st_mtime - old_mtime=0 - ls=listdir(".") - for j in ls: - if j.startswith(basename) and j.endswith(".tex")\ - and not j.endswith(".changes.tex"): - tmptime=stat(j).st_mtime - if mtime>tmptime and old_mtime0: - print "Comparing with",oldname - system ("/bin/cp "+name+".aux "+name+".changes.aux") - system ("/bin/cp "+name+".bbl "+name+".changes.bbl") - system ("latexdiff "+oldname+" "+name+".tex > "+name+".changes.tex") - system ("latex "+" ".join(newarg)) - system ("cp "+name+".changes.dvi "+name+".dvi") - else: - system ("latex "+" ".join(argv[1:])) diff --git a/latexdiff-1.0.4/contrib/latexdiff-wrap b/latexdiff-1.0.4/contrib/latexdiff-wrap deleted file mode 100755 index 894b424..0000000 --- a/latexdiff-1.0.4/contrib/latexdiff-wrap +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/bash -# -# latexdiff-wrap -# -# Wrapper for latexdiff, to -# * provide support for documents consiting of more than 1 latex file -# * provide my common arguments -# -# Copyright (C) by Volker Kuhlmann -# Released under the terms of the GNU General Public License (GPL) Version 2. -# See http://www.gnu.org/ for details. -# -# Volker Kuhlmann -# 5, 6, 7, 12, 16, 17 Oct 2005 -# 31 Jan; 5, 7, 13, 15 Feb 2006 -# - -VERSION="0.6, 15 Feb 2006" -AUTHOR="Volker Kuhlmann " -COPYRIGHT="Copyright (C) 2005-2006" - - -#### -#### Constants and initialised variables -# -diffcmd="latexdiff" -diffrc="$HOME/texmf/latexdiff" -#diffargs="-e latin1 --ignore-warnings -p latexdiff-preamble.sty" -diffargs="-e latin1 --ignore-warnings" -diffargs="$diffargs --append-safecmd $diffrc/safe-cmds" -diffargs="$diffargs --append-textcmd $diffrc/text-cmds" -# Note: Can't use multiple --append-safecmd -# show current command lists: -#diffcmd="$diffcmd --show-safecmd --show-textcmd --show-config" - - -#### -#### Version, Usage, Help -# -show_version() { - echo "${0##*/} version $VERSION -$COPYRIGHT by $AUTHOR" -} - -show_usage() { - echo " -Usage: ${0##*/} OLDDIR NEWDIR DIFFDIR [DIFFARGS --] FILE.tex [...] - ${0##*/} --show [DIFFARGS] -Version $VERSION -$COPYRIGHT by $AUTHOR -" -} - -show_help() { - show_usage - echo "\ -For each FILE.tex, build a new file DIFFDIR/FILE.tex with markup of the changes -which were made from OLDDIR/FILE.tex to NEWDIR/FILE.tex. -Any path given with FILE.tex is stripped off. -Any DIFFARGS are added to the latexdiff call, if present (remember to follow -them with a double-hyphen on its own before the FILE arguments). - -With --show, shows the settings latexdiff would be running with, including the -changes applied by the user. -" -} - -# For scripts not using function library only: -Version() { show_version; exitwith ErrVersion; } -Usage() { show_help; exitwith ErrUsage; } -Help() { test "$1" && exitwith ErrHelp show_help; show_help; exitwith ErrOK; } - - -#### -#### Error/Exit codes -# -exitwith() { - exec 1>&2 # write stdout on stderr instead - case "$1" in - ErrOK) - exit 0;; - ErrVersion|ErrUsage|ErrHelp) - # Output generated by function (program) $2, if given - test -n "$2" && "$2" - exit 1;; - # more codes in here - # more codes in here - ErrBadoption) - echo "Bad option '$2'." - echo "Call with -h for help." - exit 9;; - ErrMissingParameter) - echo "A required parameter for option $2 is missing." - echo "Call with -h for help." - exit 9;; - *) - echo "Internal error: exitwith() called with illegal error code '$1'." - exit 19;; - esac -} - - -#### -#### Parse command line parameters -# - -# If the next arg starts with a "-", collect additional argument for latexdiff -# until "--". -scanextraargs() { - addargs=() - case "$1" in -*) - while [ $# -gt 0 -a "$1" != "--" ]; do - addargs=( "${addargs[@]}" "$1" ) - shift - done - test "$1" == "--" && shift - ;; esac - fileargs=( "$@" ) -} - -case "$1" in - --version) Version;; - --usage) Usage;; - --help|-h|-help) Help;; - --show) - shift - scanextraargs "$@" - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - --show-safecmd --show-textcmd --show-config - ) | fmt - exit $? ;; -esac - -olddir="${1%/}" -newdir="${2%/}" -diffdir="${3%/}" - -if ! [ -d "$olddir" -a -d "$newdir" -a -d "$diffdir" ]; then - Help 1>&2 err -fi - -shift 3 - -scanextraargs "$@" -set -- "${fileargs[@]}" - - - -#### -#### Functions -# -#set -x -Log() { echo 1>&2 "+ $@"; "$@"; } - - -#### -#### Main -# - -# Create output directory, just in case. -(set -x -mkdir -p "$diffdir" -) -while [ $# -gt 0 ]; do - file="${1##*/}" - echo Examining: "$file" - # No point running latexdiff if both files are identical, - # but run latexdiff on top-level LaTeX file in any case. - if cmp --quiet "$olddir/$file" "$newdir/$file" \ - && ! grep -lq '\\begin.*{document}' "$newdir/$file"; then - (set -x - cp -p "$olddir/$file" "$diffdir" - ) - else - # Delete file, to make sure it's not clobbered by redirecting stdout - # in case it's a symlink to te original. - test -f "$diffdir/$file" && (set -x - rm "$diffdir/$file" - ) - # Run latexdiff if both input files are present. - run=1 - test -f "$olddir/$file" || { echo 1>&2 "No file: $olddir/$file"; run=; } - test -f "$newdir/$file" || { echo 1>&2 "No file: $newdir/$file"; run=; } - test -n "$run" && \ - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - "$olddir/$file" "$newdir/$file" > "$diffdir/$file" - ) - fi - shift -done diff --git a/latexdiff-1.0.4/contrib/latexdiff.spec b/latexdiff-1.0.4/contrib/latexdiff.spec deleted file mode 100644 index 9255a69..0000000 --- a/latexdiff-1.0.4/contrib/latexdiff.spec +++ /dev/null @@ -1,58 +0,0 @@ -Summary: Diff for LaTeX files -Name: latexdiff -Version: 0.5 -Release: 1 -License: GPL -Group: Productivity/Publishing/TeX/Utilities -URL: http://www.tug.org/tex-archive/help/Catalogue/entries/latexdiff.html -Source0: %{name}.zip -BuildArch: noarch -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -# only required for 'make install-ext' -# Requires: perl-Algorithm-Diff - - -%description -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -(C) 2004 Frederik Tilmann - - -%prep -%setup -n %{name} - - -%build -# quick had to adapt the Makefile -%{__mv} Makefile Makefile.old -%{__sed} \ - -e "s;INSTALLPATH = /usr/local;INSTALLPATH = \${DESTDIR}%{_prefix};" \ - -e "s;INSTALLMANPATH = \$(INSTALLPATH)/man;INSTALLMANPATH = \${DESTDIR}%{_mandir};" \ - Makefile.old > Makefile - - -%install -%{__mkdir_p} $RPM_BUILD_ROOT%{_bindir} -%{__mkdir_p} $RPM_BUILD_ROOT%{_mandir}/man1 - -%makeinstall - - -%clean -[ "${RPM_BUILD_ROOT}" != "/" ] && [ -d "${RPM_BUILD_ROOT}" ] && %{__rm} -rf "${RPM_BUILD_ROOT}" - - -%files -%defattr(-,root,root) -%doc example CHANGES LICENSE README -%{_bindir}/* -%{_mandir}/man*/* - -%changelog -* Thu Jan 4 2007 Till Dörges - 0.5-1 -- Initial build. diff --git a/latexdiff-1.0.4/doc/example-diff.tex b/latexdiff-1.0.4/doc/example-diff.tex deleted file mode 100644 index 7166571..0000000 --- a/latexdiff-1.0.4/doc/example-diff.tex +++ /dev/null @@ -1,89 +0,0 @@ -\documentclass[12pt,a4paper]{article} -%DIF LATEXDIFF DIFFERENCE FILE -%DIF DEL example-draft.tex Thu Jun 12 00:01:26 2014 -%DIF ADD example-rev.tex Thu Jun 12 00:01:26 2014 - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -\title{latexdiff Example - \DIFdelbegin \DIFdel{Draft }\DIFdelend \DIFaddbegin \DIFadd{Revised }\DIFaddend version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of \DIFaddbegin \DIFadd{the }\DIFaddend latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{\DIFdelbegin \DIFdel{Another }\DIFdelend \DIFaddbegin \DIFadd{Yet another }\DIFaddend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft document. }\DIFdelend More things could be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised document. }\DIFaddend More things could be -said were it not for the constraints of time and space. - -And here is a \DIFdelbegin \DIFdel{tipo}\DIFdelend \DIFaddbegin \DIFadd{typo}\DIFaddend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFdelbegin \DIFdel{Grey }\DIFdelend \DIFaddbegin \DIFadd{White }\DIFaddend \\ -Saruman & \DIFdelbegin \DIFdel{White -}\DIFdelend \DIFaddbegin \DIFadd{Evil -}\DIFaddend \end{tabular} - -And \DIFdelbegin \DIFdel{sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend \DIFaddbegin \DIFadd{now for something completely different, with not a paragraph in sight}\DIFaddend . -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.4/doc/latexdiff-man.pdf b/latexdiff-1.0.4/doc/latexdiff-man.pdf deleted file mode 100644 index a3d640a..0000000 Binary files a/latexdiff-1.0.4/doc/latexdiff-man.pdf and /dev/null differ diff --git a/latexdiff-1.0.4/doc/latexdiff-man.tex b/latexdiff-1.0.4/doc/latexdiff-man.tex deleted file mode 100644 index b6bb37e..0000000 --- a/latexdiff-1.0.4/doc/latexdiff-man.tex +++ /dev/null @@ -1,355 +0,0 @@ -\documentclass[a4]{article} -\usepackage{graphicx} -%\def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -%\def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -\setlength{\parindent}{0pt} -%\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}} -\date{\today} - -\begin{document} -\maketitle - -\section*{Preamble} - -{\em latexdiff} is a Perl script, which compares two -latex files and marks up significant differences between them. Various options are available for visual markup using standard -latex packages such as {\em color.sty}. Changes not directly affecting visible -text, for example in formatting commands, are still marked in the -latex source. - -A rudimentary revision facilility is provided by another Perl script, -{\em 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. - -There is no explicit support for annotations as these are trivial to implement. -For example, I include the following command definition in the preamble -\begin{verbatim} -\newcommand{\remark}[1]{{ \bf [ \footnotesize #1 ]}} -\end{verbatim} -and mark up annotations as follows -\begin{verbatim} -... The roadrunner is the fastest running bird \remark{Check this -again with a zoologist!}. The most famous roadrunner ... -\end{verbatim} -Alternatively, instead of a command like \verb#\remark# in the example just given, an -equivalent annotation environment could be defined. -{\em latexrevise} can remove such comments or -environments from the text body. - -%It is planned that the revision capabilities of this system will be -%further expanded, dependent on the amount of feedback received. - -On the following pages you find the {\em man} pages for {\em - latexdiff} and {\em latexrevise} and a simple example. - -\include{latexdiff} -\setcounter{section}{0} - -\include{latexrevise} -\setcounter{section}{0} - -\include{latexdiff-vc} -\setcounter{section}{0} - -\section*{A simple example} - -We start with a draft text, \verb|example-draft.tex|, listed here in -full but also included in the distribution (except that the ``verbatim'' environment had -to be renamed to ``Verbatim'' for the listing). - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. Of course, instead of \verb|xpdf| you can use -\verb|okular, evince, acroread| or any other pdf or postscript viewer. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things -could be said were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} -\end{verbatim} -} - -We can now edit -this text as we would do with any other latex file to create -a new revision of the text, \verb|example-rev.tex|. We should run -\begin{verbatim} -latex example-rev.tex -\end{verbatim} -and look at the resulting \verb|.dvi| file to make sure that all -changes are valid. An example revision is listed here: - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. -More things could be said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} -\end{verbatim} -} - -To compare both revisions, type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -This results in the following difference file (a few newlines have been -added in this listing for legibility reasosn): -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -%DIF 9c9 -%DIF < \title{latexdiff Example - Draft version} -%DIF ------- -\title{latexdiff Example - Revised version} %DIF > -%DIF ------- -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\color{blue}\uline{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{\DIFaddbegin \DIFadd{Yet another }\DIFaddend \DIFdelbegin -\DIFdel{Another }\DIFdelend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft - document. }\DIFdelend More things could - be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised - document. }\DIFaddend More things could be said -were it not for the constraints of time and space. - -And here is a \DIFaddbegin \DIFadd{typo}\DIFaddend \DIFdelbegin -\DIFdel{tipo}\DIFdelend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFaddbegin \DIFadd{White }\DIFaddend \DIFdelbegin -\DIFdel{Grey }\DIFdelend \\ -Saruman & \DIFaddbegin \DIFadd{Evil -}\DIFaddend \DIFdelbegin \DIFdel{White -}\DIFdelend \end{tabular} - -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -No change, -no markup! -\end{document} -\end{verbatim} -} -Type -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -to make the markup visible. This is what it looks like: - -\vspace{1cm} -\framebox[\textwidth]{\includegraphics[width=\textwidth]{example-diff}} -\vspace{1cm} - -If you approve of all the changes in the revision, just continue with -\verb|example-rev.tex| for the next revision. If you like to adopt -most but not all changes you can use \verb|latexrevise| in the -following manner. Simply remove the \verb|\DIFdelbegin| and -\verb|\DIFdelend| tags around the text you would like to keep and -simply remove the text between \verb|\DIFaddbegin| and -\verb|\DIFaddend| tags, if you do not wish to keep them. Say you are happy with all proposed changes for the -example above except in -the last paragraph where you prefer the original draft. You have -to change - -{\scriptsize -\begin{verbatim} -... -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -... -\end{verbatim} -} -into -{\scriptsize -\begin{verbatim} -... -And \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}. -... -\end{verbatim} -} -and run -\begin{verbatim} -latexrevise -a example-rev.tex > example-final.tex -\end{verbatim} -\verb|example-final.tex| is then almost identical to -\verb|example-rev.tex| except for the last paragraph. -\end{document} diff --git a/latexdiff-1.0.4/example/example-draft.tex b/latexdiff-1.0.4/example/example-draft.tex deleted file mode 100644 index 593a170..0000000 --- a/latexdiff-1.0.4/example/example-draft.tex +++ /dev/null @@ -1,59 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things could be said -were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} - - diff --git a/latexdiff-1.0.4/example/example-rev.tex b/latexdiff-1.0.4/example/example-rev.tex deleted file mode 100644 index 4bcaf15..0000000 --- a/latexdiff-1.0.4/example/example-rev.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. More things could be -said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.0.4/latexdiff b/latexdiff-1.0.4/latexdiff deleted file mode 100755 index 717a093..0000000 --- a/latexdiff-1.0.4/latexdiff +++ /dev/null @@ -1,3540 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository/issue tracker: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# ToDo: -# -# 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) -# - new subtype LABEL which gives each change a label. This can later be used to only display pages where changes -# have been made (instructions for that are put as comments into the diff'ed file) inspired by answer on http://tex.stackexchange.com/questions/166049/invisible-markers-in-pdfs-using-pdflatex -# - Configuration variables take into accout some commands from additional packages: -# tikzpicture environment now treated as PICTUREENV, and \smallmatrix in ARRENV (amsmath) -# - --flatten: support for \subfile command (subfiles package) (in response to http://tex.stackexchange.com/questions/167620/latexdiff-with-subfiles ) -# - --flatten: \bibliography commands expand if corresponding bbl file present -# - angled bracket optional commands now parsed correctly (patch #3570) submitted by Dave Kleinschmidt (thanks) -# - \RequirePackage now treated as synonym of \usepackage with respect to setting packages -# - special rules for apacite package (redefine citation commands) -# - recognise /dev/null as 'file-like' arguments for --preamble and --config options -# - fix units package incompatibility with ulem for text maths statements $ ..$ (thanks to Stuart Prescott for reporting this) -# - amsmath environment cases treated correctly (Bug fix #19029) (thanks to Jalar) -# - {,} in comments no longer confuse latexdiff (Bug fix #19146) -# - \% in one-letter sub/Superscripts was not converted correctly -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if they contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript -# (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -use Algorithm::Diff qw(traverse_sequences); - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# insert preamble directly after documentclass - experimental feature, set to 0 in final distribution -# Note that this failed with mini example (or other files, where packages used in latexdiff preamble -# are called again with incompatible options in preamble of resulting file) -$earlylatexdiffpreamble=0; - -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config || lc $config eq '/dev/null' ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - my $abrat0 = '(?:[^<>])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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*/ ; - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - - - - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - 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" ;} - 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; - } - - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - if ( $earlylatexdiffpreamble) { - # insert latexdiff command directly after documentclass at beginning of preamble - # note that grep is only run for its side effect - ( grep { s/^([^%]*\\documentclass.*)$/$1$latexdiffpreamble/ } @diffpreamble )==1 or die "Could not find documentclass statement in preamble"; - } else { - # insert latexdiff commands at the end of preamble (default behaviour) - push @diffpreamble,$latexdiffpreamble; - } - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing -# and $packages{"apacite"}!~/natbibpapa/ -my ($citpat,$citpatsafe); - -if ( defined $packages{"apacite"} ) { - print STDERR "DEBUG apacite citation commands\n" if $debug; - $citpatsafe=qr/^(?:mask)?(?:full|short)?cite(?:A|author|year)?(?:NP)?$/; - $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); -} 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 - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # 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 - -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*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - # replace bibliography with bbl file if it exists - $text=~s/(^(?:[^%\n]|\\%)*)\\bibliography{(.*?)}/{ - if ( -f $bblfile ){ - $replacement=read_file_with_encoding(File::Spec->catfile($bblfile), $encoding); - } else { - warn "Bibliography file $bblfile cannot be found. No flattening of \\bibliography done. Run bibtex on old and new files first"; - $replacement="\\bibliography{$2}"; - } - $begline=(defined($1)? $1 : "") ; - "$begline$replacement"; - }/exgm; - # replace subfile with contents (subfile package) - $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type || lc $type eq '/dev/null' ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\',@UNSAFEMATHCMD); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE -# #. 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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) - $delblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } - -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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; - $addblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visible-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=item C - -Redefine the commands recognised as citation commands. - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 - -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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, -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.4 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who sent in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - -%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) -% 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 -% 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} -\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 -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END TRADITIONALSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.4/latexdiff-fast b/latexdiff-1.0.4/latexdiff-fast deleted file mode 100755 index 22f2f8f..0000000 --- a/latexdiff-1.0.4/latexdiff-fast +++ /dev/null @@ -1,4101 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository/issue tracker: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# ToDo: -# -# 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) -# - new subtype LABEL which gives each change a label. This can later be used to only display pages where changes -# have been made (instructions for that are put as comments into the diff'ed file) inspired by answer on http://tex.stackexchange.com/questions/166049/invisible-markers-in-pdfs-using-pdflatex -# - Configuration variables take into accout some commands from additional packages: -# tikzpicture environment now treated as PICTUREENV, and \smallmatrix in ARRENV (amsmath) -# - --flatten: support for \subfile command (subfiles package) (in response to http://tex.stackexchange.com/questions/167620/latexdiff-with-subfiles ) -# - --flatten: \bibliography commands expand if corresponding bbl file present -# - angled bracket optional commands now parsed correctly (patch #3570) submitted by Dave Kleinschmidt (thanks) -# - \RequirePackage now treated as synonym of \usepackage with respect to setting packages -# - special rules for apacite package (redefine citation commands) -# - recognise /dev/null as 'file-like' arguments for --preamble and --config options -# - fix units package incompatibility with ulem for text maths statements $ ..$ (thanks to Stuart Prescott for reporting this) -# - amsmath environment cases treated correctly (Bug fix #19029) (thanks to Jalar) -# - {,} in comments no longer confuse latexdiff (Bug fix #19146) -# - \% in one-letter sub/Superscripts was not converted correctly -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if they contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript -# (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for differenceing -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that subroutine _longestCommonSubsequence has been replace by -# a routine which internally uses the UNIX diff command for -# the differencing rather than the Perl routines if the -# length of the sequences exceeds some threshold. -# Also, all POD documentation has been stripped out. -# -# (the distribution on which this modification is based is available -# from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The fast-differencing version of latexdiff is provided as a convenience -# for latex users under Unix-like systems which have a 'diff' command. -# If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -# Jonathan Paisley is acknowledged for the idea of using the system diff -# command to achieve shorter running times -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d fast', (q$Revision: 1.15 $ =~ /\d+/g)); - -# Global parameters - -use File::Temp qw/tempfile/; -# if larger number of elements in longestCommonSubsequence smaller than -# this number, then use internal algorithm, otherwise use UNIX diff -use constant THRESHOLD => 100 ; -# Detect whether diff --minimal option is available -# if yes we use it -use constant MINIMAL => ( system('diff','--minimal','/dev/null','/dev/null') >> 8 ==0 ? "--minimal" : "" ) ; - - - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # Check whether to use internal routine (small number of elements) - # or use it as a wrapper for UNIX diff - if ( ( $#$a > $#$b ? $#$a : $#$b) < THRESHOLD ) { - ### print STDERR "DEBUG: regular longestCommonSubsequence\n"; - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - } - else { - my ($fha,$fhb,$fna,$fnb,$ele,$key); - my ($alines,$blines,$alb,$alf,$blb,$blf); - my ($minimal)=MINIMAL; - # large number of elements, use system diff - ### print STDERR "DEBUG: fast (diff) longestCommonSubsequence\n"; - - ($fha,$fna)=tempfile("DiffA-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence A"; - ($fhb,$fnb)=tempfile("DiffB-XXXX") or die "_longestCommonSubsequence: Cannot open tempfile for sequence B"; - # prepare sequence A - foreach $ele ( @$a ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fha "$key\n" ; - } - close($fha); - # prepare sequence B - foreach $ele ( @$b ) { - $key=&$keyGen( $ele, @_ ); - $key =~ s/\\/\\\\/g ; - $key =~ s/\n/\\n/sg ; - print $fhb "$key\n" ; - } - close($fhb); - - open(DIFFPIPE, "diff $minimal $fna $fnb |") or die "_longestCommonSubsequence: Cannot launch diff process. $!" ; - # The diff line numbering begins with 1, but Perl subscripts start with 0 - # We follow the diff numbering but substract 1 when assigning to matchVector - $aStart++; $bStart++ ; $aFinish++ ; $bFinish++ ; - while( ) { - if ( ($alines,$blines) = ( m/^(\d*(?:,\d*)?)?c(\d*(?:,\d*)?)?$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - ($blb,$blf)=split(/,/,$blines); - $alf=$alb unless defined($alf); - $blf=$blb unless defined($blf); - while($aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - # check for consistency - $bStart==$blb or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in changed sequence"; - $aStart=$alf+1; - $bStart=$blf+1; - } - elsif ( ($alb,$blines) = ( m/^(\d*)a(\d*(?:,\d*)?)$/ ) ) { - ($blb,$blf)=split(/,/,$blines); - $blf=$blb unless defined($blf); - while ( $bStart < $blb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $aStart==$alb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in appended sequence near elements $aStart and $bStart"; - $bStart=$blf+1; - } - elsif ( ($alines,$blb) = ( m/^(\d*(?:,\d*)?)d(\d*)$/ ) ) { - ($alb,$alf)=split(/,/,$alines); - $alf=$alb unless defined($alf); - while ( $aStart < $alb ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$blb+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency in deleted sequence near elements $aStart and $bStart"; - $aStart=$alf+1; - } - elsif ( m/^Binary files/ ) { - # if diff reports it is a binary file force --text mode. I do not like - # to always use this option because it is probably only available in GNU diff - open(DIFFPIPE, "diff --text $fna $fnb |") or die "Cannot launch diff process. $!" ; - } - # Default: just skip line - } - while ($aStart <= $aFinish ) { - $matchVector->[ -1 + $aStart++ ] = -1 + $bStart++ ; - } - $bStart==$bFinish+1 or die "_longestCommonSubsequence: Fatal error in interpreting diff output: Inconsistency at end"; - close DIFFPIPE; - # check whether a system error has occurred or return status is greater than or equal to 5 - if ( $! || ($? >> 8) > 5) { - print STDERR "diff process failed with exit code ", ($? >> 8), " $!\n"; - die; - } - unlink $fna,$fnb ; - } - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# insert preamble directly after documentclass - experimental feature, set to 0 in final distribution -# Note that this failed with mini example (or other files, where packages used in latexdiff preamble -# are called again with incompatible options in preamble of resulting file) -$earlylatexdiffpreamble=0; - -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config || lc $config eq '/dev/null' ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - my $abrat0 = '(?:[^<>])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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*/ ; - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - - - - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - 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" ;} - 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; - } - - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - if ( $earlylatexdiffpreamble) { - # insert latexdiff command directly after documentclass at beginning of preamble - # note that grep is only run for its side effect - ( grep { s/^([^%]*\\documentclass.*)$/$1$latexdiffpreamble/ } @diffpreamble )==1 or die "Could not find documentclass statement in preamble"; - } else { - # insert latexdiff commands at the end of preamble (default behaviour) - push @diffpreamble,$latexdiffpreamble; - } - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing -# and $packages{"apacite"}!~/natbibpapa/ -my ($citpat,$citpatsafe); - -if ( defined $packages{"apacite"} ) { - print STDERR "DEBUG apacite citation commands\n" if $debug; - $citpatsafe=qr/^(?:mask)?(?:full|short)?cite(?:A|author|year)?(?:NP)?$/; - $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); -} 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 - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # 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 - -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*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - # replace bibliography with bbl file if it exists - $text=~s/(^(?:[^%\n]|\\%)*)\\bibliography{(.*?)}/{ - if ( -f $bblfile ){ - $replacement=read_file_with_encoding(File::Spec->catfile($bblfile), $encoding); - } else { - warn "Bibliography file $bblfile cannot be found. No flattening of \\bibliography done. Run bibtex on old and new files first"; - $replacement="\\bibliography{$2}"; - } - $begline=(defined($1)? $1 : "") ; - "$begline$replacement"; - }/exgm; - # replace subfile with contents (subfile package) - $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type || lc $type eq '/dev/null' ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\',@UNSAFEMATHCMD); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE -# #. 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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) - $delblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } - -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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; - $addblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visible-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=item C - -Redefine the commands recognised as citation commands. - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 - -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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, -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.4 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who sent in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - -%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) -% 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 -% 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} -\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 -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END TRADITIONALSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.4/latexdiff-so b/latexdiff-1.0.4/latexdiff-so deleted file mode 100755 index 6cd69fd..0000000 --- a/latexdiff-1.0.4/latexdiff-so +++ /dev/null @@ -1,3997 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository/issue tracker: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# ToDo: -# -# 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) -# - new subtype LABEL which gives each change a label. This can later be used to only display pages where changes -# have been made (instructions for that are put as comments into the diff'ed file) inspired by answer on http://tex.stackexchange.com/questions/166049/invisible-markers-in-pdfs-using-pdflatex -# - Configuration variables take into accout some commands from additional packages: -# tikzpicture environment now treated as PICTUREENV, and \smallmatrix in ARRENV (amsmath) -# - --flatten: support for \subfile command (subfiles package) (in response to http://tex.stackexchange.com/questions/167620/latexdiff-with-subfiles ) -# - --flatten: \bibliography commands expand if corresponding bbl file present -# - angled bracket optional commands now parsed correctly (patch #3570) submitted by Dave Kleinschmidt (thanks) -# - \RequirePackage now treated as synonym of \usepackage with respect to setting packages -# - special rules for apacite package (redefine citation commands) -# - recognise /dev/null as 'file-like' arguments for --preamble and --config options -# - fix units package incompatibility with ulem for text maths statements $ ..$ (thanks to Stuart Prescott for reporting this) -# - amsmath environment cases treated correctly (Bug fix #19029) (thanks to Jalar) -# - {,} in comments no longer confuse latexdiff (Bug fix #19146) -# - \% in one-letter sub/Superscripts was not converted correctly -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if they contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript -# (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -# Inserted block for stand-alone version replaces -# use Algorithm::Diff qw(traverse_sequences); -# in standard version -# The following BEGIN block contains a verbatim copy of -# Ned Konz' Algorithm::Diff package version 1.15 except -# that all POD documentation has been stripped out. -# I encourage you to download and install the Algorithm::Diff -# package and use the standard latexdiff version instead -# (current distribution available from http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15 -# the most recent version can be found via http://search.cpan.org/search?module=Algorithm::Diff ) -# Please note that the LICENCSE for Algorithm::Diff : -# "Copyright (c) 2000-2002 Ned Konz. All rights reserved. -# This program is free software; -# you can redistribute it and/or modify it under the same terms -# as Perl itself." -# The stand-alone version of latexdiff is provided as a convenience -# for latex users with no knowledge of PERL who do not wish to install -# additional packages to be able to use latexdiff. If you believe -# the inlining of Algorithm::Diff violates its license please contact -# me and I will modify the latexdiff distribution accordingly. -# Frederik Tilmann (tilmann@esc.cam.ac.uk) -BEGIN { -package Algorithm::Diff; -use strict; -use vars qw($VERSION @EXPORT_OK @ISA @EXPORT); -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(); -@EXPORT_OK = qw(LCS diff traverse_sequences traverse_balanced sdiff); -$VERSION = sprintf('%d.%02d so', (q$Revision: 1.15 $ =~ /\d+/g)); - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, -# by Ned Konz, perl@bike-nomad.com - - -# Create a hash that maps each element of $aCollection to the set of positions -# it occupies in $aCollection, restricted to the elements within the range of -# indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the array. If -# that place is already occupied by aValue, do nothing, and return undef. If -# the place does not exist (i.e., it is off the end of the array), add it to -# the end, otherwise replace the element at that point with aValue. -# It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so try to -# make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $keyGen = shift; # code ref - my $compare; # code ref - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $bStart, $bFinish, $matchVector ) = - ( 0, $#$a, 0, $#$b, [] ); - - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - } - - # Now compute the equivalence classes of positions of elements - my $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { $ma++ } while ( $ma <= $#$matchVector && !defined $matchVector->[$ma] ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub LCS -{ - my $a = shift; # array ref - my $matchVector = _longestCommonSubsequence( $a, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { push ( @$hunk, [ '-', $_[0], $a->[ $_[0] ] ] ) }; - my $add = sub { push ( @$hunk, [ '+', $_[1], $b->[ $_[1] ] ] ) }; - my $match = sub { push ( @$retval, $hunk ) if scalar(@$hunk); $hunk = [] }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -1; -} -import Algorithm::Diff qw(traverse_sequences); -# End of inserted block for stand-alone version - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# 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; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# insert preamble directly after documentclass - experimental feature, set to 0 in final distribution -# Note that this failed with mini example (or other files, where packages used in latexdiff preamble -# are called again with incompatible options in preamble of resulting file) -$earlylatexdiffpreamble=0; - -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - 'append-context1cmd=s' => \@appendcontext1list, - 'replace-context2cmd=s' => \$replacecontext2, - 'append-context2cmd=s' => \@appendcontext2list, - 'show-preamble' => \$showpreamble, - 'show-safecmd' => \$showsafe, - 'show-textcmd' => \$showtext, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - 'enable-citation-markup' => \$enablecitmark, - 'disable-citation-markup' => \$disablecitmark, - 'verbose|V' => \$verbose, - 'ignore-warnings' => \$ignorewarnings, - 'driver=s'=> \$driver, - 'flatten' => \$flatten, - 'version' => \$version, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -print STDERR $versionstring if $verbose; - -if (defined($showall)){ - $showpreamble=$showsafe=$showtext=$showconfig=1; -} - -if (defined($mathmarkup)) { - $mathmarkup=~tr/a-z/A-Z/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -foreach $excludesafe ( @excludesafelist ) { - init_regex_arr_ext(\@SAFECMDEXCL, $excludesafe); -} - -# setting up @TEXTCMDLIST and @TEXTCMDEXCL -if (defined($replacetext)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config || lc $config eq '/dev/null' ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - my $abrat0 = '(?:[^<>])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - my $mathpunct='[+=<>\-\|]'; - my $and = '&'; - my $coords= '[\-.,\s\d]*'; -# 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*/ ; - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - - - - -my @auxlines; -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - 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" ;} - 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; - } - - print STDERR "Differencing preamble.\n" if $verbose; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - if ( $earlylatexdiffpreamble) { - # insert latexdiff command directly after documentclass at beginning of preamble - # note that grep is only run for its side effect - ( grep { s/^([^%]*\\documentclass.*)$/$1$latexdiffpreamble/ } @diffpreamble )==1 or die "Could not find documentclass statement in preamble"; - } else { - # insert latexdiff commands at the end of preamble (default behaviour) - push @diffpreamble,$latexdiffpreamble; - } - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing -# and $packages{"apacite"}!~/natbibpapa/ -my ($citpat,$citpatsafe); - -if ( defined $packages{"apacite"} ) { - print STDERR "DEBUG apacite citation commands\n" if $debug; - $citpatsafe=qr/^(?:mask)?(?:full|short)?cite(?:A|author|year)?(?:NP)?$/; - $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); -} 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 - if ( uc($subtype) eq "COLOR" or uc($subtype) eq "DVIPSCOL" ) { - # remove \cite command again from list of safe commands - pop @SAFECMDLIST; - # 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 - -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*'; -} - -print STDERR "Preprocessing body. " if $verbose; -my ($oldleadin,$newleadin)=preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$diffbo" ; -} - -$diffall .= "$newleadin$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -# %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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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; - # replace bibliography with bbl file if it exists - $text=~s/(^(?:[^%\n]|\\%)*)\\bibliography{(.*?)}/{ - if ( -f $bblfile ){ - $replacement=read_file_with_encoding(File::Spec->catfile($bblfile), $encoding); - } else { - warn "Bibliography file $bblfile cannot be found. No flattening of \\bibliography done. Run bibtex on old and new files first"; - $replacement="\\bibliography{$2}"; - } - $begline=(defined($1)? $1 : "") ; - "$begline$replacement"; - }/exgm; - # replace subfile with contents (subfile package) - $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $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; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type || lc $type eq '/dev/null' ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2.tex"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2.tex"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# Each element of words is either -# a word (including trailing spaces and punctuation) -# a latex command -sub splitlatex { - my ($string) = @_ ; - # if input is empty, return empty list - length($string)>0 or return (); - - my @retval=($string =~ m/$pat/osg); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\([\w\d\*]+)((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# 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), -# braces, ampersands, or comments -# mark comments with $comment -# exclude all other exceptions from scope of open, close like this -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# split this block to flatten out sequences joined in pass1 - @$block=splitlatex(join "",@$block); - foreach (@$block) { - $word=$_; - if ( $word =~ s/^%/%$comment/ ) { - # a comment - if ($cmd==1) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - push (@$retval,$word); - next; - } - if (! $noncomment) { - push (@$retval,$openmark); - $noncomment=1; - } - # negative lookahead pattern (?!) in second clause is put in to avoid mathcing \( .. \) 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)) ) { - # 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - local @SAFECMDLIST=(".*"); - local @SAFECMDEXCL=('\\','\\\\',@UNSAFEMATHCMD); - push(@$retval,$command,marktags("","",$open,$close,"","",$comment,\@argtext)#@argtext - ,$closingbracket); - } else { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - # just an ordinary word or word in SAFECMD - push (@$retval,$open) if $cmd==-1 ; - push (@$retval,$closecmd,$open) if $cmd==1 ; - push (@$retval,$word); - $cmd=0; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE -# #. 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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 \{,\} -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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) - $delblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } - -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - 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; - $addblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 - [ 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 - [ Default: SAFE ] - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - - ---config var1=val1,var2=val2,... --c var1=val1,.. Set configuration variables. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - 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 - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - 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] - -Miscelleneous options - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visible-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] - -=item B<--floattype=markstyle> or -B<-f markstyle> - -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -C<\DIF...FL> commands. -Available styles: C - -[ Default: C ] - -=item B<--encoding=enc> or -B<-e enc> - -Specify encoding of old.tex and new.tex. Typical encodings are -C, C, C, C. A list of available encodings can be -obtained by executing - -Cencodings( ":all" )) ;' > - -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation C<\usepackage[..]{inputenc}> in which case the -encoding chosen by this command is asssumed. Note that ASCII (standard -latex) is a subset of utf8] - -=item B<--preamble=file> or -B<-p file> - -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -C<\DIFaddbegin, \DIFaddend, \DIFadd{..}, -\DIFdelbegin,\DIFdelend,\DIFdel{..},> -and varieties for use within floats -C<\DIFaddbeginFL, \DIFaddendFL, \DIFaddFL{..}, -\DIFdelbeginFL, \DIFdelendFL, \DIFdelFL{..}> -(If this option is set B<-t>, B<-s>, and B<-f> options -are ignored.) - -=item B<--packages=pkg1,pkg2,..> - -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for C<\usepackage> commands. -Use of the B<--packages> option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use B<--packages=none>. -The following packages trigger special behaviour: - -=over 8 - -=item C - -Configuration variable amsmath is set to C (Default: C) - -=item C - -Ensure that C<\begin{figure}> and C<\end{figure}> always appear by themselves on a line. - -=item C - -Change name of C<\DIFadd> and C<\DIFdel> commands to C<\DIFaddtex> and C<\DIFdeltex> and -define new C<\DIFadd> and C<\DIFdel> commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). - -=item C - -Redefine the commands recognised as citation commands. - -=back - -[ Default: scan the preamble for C<\\usepackage> commands to determine - loaded packages.] - - - -=item B<--show-preamble> - -Print generated or included preamble commands to stdout. - -=back - -=head2 Configuration - -=over 4 - -=item B<--exclude-safecmd=exclude-file> or -B<-A exclude-file> or B<--exclude-safecmd="cmd1,cmd2,..."> - -=item B<--replace-safecmd=replace-file> - -=item B<--append-safecmd=append-file> or -B<-a append-file> or B<--append-safecmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a C<\DIFadd> or C<\DIFdel> command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -"\" of the command is not included. -The B<--exclude-safecmd> and B<--append-safecmd> options can be combined with the -B<--replace-safecmd> -option and can be used repeatedly to add cumulatively to the lists. - B<--exclude-safecmd> -and B<--append-safecmd> can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus "\,". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. - -=item B<--exclude-textcmd=exclude-file> or -B<-X exclude-file> or B<--exclude-textcmd="cmd1,cmd2,..."> - -=item B<--replace-textcmd=replace-file> - -=item B<--append-textcmd=append-file> or -B<-x append-file> or B<--append-textcmd="cmd1,cmd2,..."> - -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for B<--exclude-safecmd> directly above for further details. - - -=item B<--replace-context1cmd=replace-file> - -=item B<--append-context1cmd=append-file> or -=item B<--append-context1cmd="cmd1,cmd2,..."> - -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \caption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. - -=item B<--replace-context2cmd=replace-file> - -=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<--config var1=val1,var2=val2,...> or B<-c var1=val1,..> - -=item B<-c configfile> - -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): - -C (integer) - -C (RegEx) - -C (RegEx) - -C (RegEx) - -C (String) - -C (RegEx) - -C (String) - -C (RegEx) - -C (RegEx) - -=item B<--show-safecmd> - -Print list of RegEx matching and excluding safe commands. - -=item B<--show-textcmd> - -Print list of RegEx matching and excluding commands with text argument. - -=item B<--show-config> - -Show values of configuration variables. - -=item B<--show-all> - -Combine all --show commands. - -NB For all --show commands, no C or C file needs to be specified, and no -differencing takes place. - -=back - -=head2 Other configuration options: - -=over 4 - -=item B<--allow-spaces> - -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). - -=item B<--math-markup=level> - -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): - -C or C<0>: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. - -C or C<1>: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. - -C or C<2>: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] - -C or C<3>: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. - -=item B<--disable-citation-markup> - -Suppress citation markup in styles using ulem (UNDERLINE, -FONTSTRIKE, CULINECHBAR) - -=item B<--enable-citation-markup> - -Protect citation commands in changed sections with \\mbox command [i.e. use default behaviour for ulem package for other packages] - -=back - -=head2 Miscellaneous - -=over 4 - -=item B<--verbose> or B<-V> - -Output various status information to stderr during processing. -Default is to work silently. - -=item B<--driver=type> - -Choose driver for changebar package (only relevant for styles using - changebar: CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] - -=item B<--ignore-warnings> - -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to C but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. - -=item B<--label=label> or -B<-L label> - -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this C<-L labelold -L labelnew>. -[Default: use the filename and modification dates for the label] - -=item B<--no-label> - -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 -visible output. - -=item B<--flatten> - -Replace C<\input> and C<\include> commands within body by the content -of the files in their argument. If C<\includeonly> is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. C<\input> and C<\include> commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. ---flatten is applied recursively, so inputted files can contain further -C<\input> statements. - -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - - - -=head2 Predefined styles - -=head2 Major types - -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands C<\DIFadd{...}> and C<\DIFdel{...}> . - -=over 10 - -=item C - -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). - -=item C - -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) - -=item C - -Like C but without the use of color. - -=item C - -Added text is blue and set in sans-serif, and discarded text is red and very small size. - -=item C - -Added tex is set in sans-serif, discarded text small and struck out - -=item C - -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color and changebar packages). - -=item C - -Like C but with additional changebars (Requires color, ulem and changebar packages). - -=item C - -No mark up of text, but mark margins with changebars (Requires changebar package). - -=item C - -No visible markup (but generic markup commands will still be inserted. - -=back - -=head2 Subtypes - -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend>) - -=over 10 - -=item C - -No additional markup (Recommended choice) - -=item C - -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard C<\marginpar> command - note that this sometimes moves somewhat -from the intended position. - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). - -=item C - -An alternative way of marking added passages in blue, and deleted ones in red. Note -that C 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). - -=back - -=head2 Float Types - -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. - -=over 10 - -=item C - -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is C as C<\marginpar> does not work properly within floats. - -=item C - -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \[ and \] and the deleted text is set in scriptscript size. This float type should always be used with the C and C markup types as the \footnote command does not work properly in floating environments. - -=item C - -Make no difference between the main text and floats. - -=back - - -=head2 Configuration Variables - -=over 10 - -=item C - -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than C to the preceding added and discarded parts. - -[ Default: 3 ] - -=item C - -Environments whose name matches the regular expression in C are -considered floats. Within these environments, the I markup commands -are replaced by their FL variaties. - -[ Default: S >] - -=item C - -Within environments whose name matches the regular expression in C -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). - -[ Default: S >] - -=item C,C - -If both \begin and \end for a math environment (environment name matching C -or \[ and \]) -are within the same deleted block, they are replaced by a \begin and \end commands for C -rather than being commented out. - -[ Default: C=S >, C=S >] - -=item C,C - -as C,C but for equation arrays - -[ Default: C=S >, C=S >] - -=item C - -If a match to C is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by C<\mbox{>...C<}>. This is necessary as underlining does not work within inlined array environments. - -[ Default: C=S > - -=item C - -If a command in a deleted block which is also in the textcmd list matches C then an -additional command C<\addtocounter{>FC<}{-1}>, where F is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. - -[ Default: C=C<(?:footnote|part|section|subsection> ... - -C<|subsubsection|paragraph|subparagraph)> ] - -=back - -=head1 COMMON PROBLEMS - -=over 10 - -=item Citations result in overfull boxes - -There is an incompatibility between the C package, which C 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: - -1. Use C or C 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. - -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) - -=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>. - -=back - -=head1 BUGS - -Option allow-spaces not implemented entirely consistently. It breaks -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, -or send them to I. Include the serial number of I -(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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. - -=head1 SEE ALSO - -L, L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than ASCII or UTF-8 are processed, Perl 5.8 or higher is required. - -The standard version of I requires installation of the Perl package -C (available from I - -I) but a stand-alone -version, I, which has this package inlined, is available, too. -I requires the I command to be present. - -=head1 AUTHOR - -Version 1.0.4 -Copyright (C) 2004-2012 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 - -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who sent in bug reports, feature suggestions, and other feedback. - -=cut - -__END__ -%%BEGIN SAFE COMMANDS -% Regex matching commands which can safely be in the -% argument of a \DIFadd or \DIFdel command (leave out the \) -arabic -dashbox -emph -fbox -framebox -hspace -math.* -makebox -mbox -pageref -ref -symbol -raisebox -rule -text.* -shortstack -usebox -dag -ddag -copyright -pounds -S -P -oe -OE -ae -AE -aa -AA -o -O -l -L -frac -ss -sqrt -ldots -cdots -vdots -ddots -alpha -beta -gamma -delta -epsilon -varepsilon -zeta -eta -theta -vartheta -iota -kappa -lambda -mu -nu -xi -pi -varpi -rho -varrho -sigma -varsigma -tau -upsilon -phi -varphi -chi -psi -omega -Gamma -Delta -Theta -Lambda -Xi -Pi -Sigma -Upsilon -Phi -Psi -Omega -ps -mp -times -div -ast -star -circ -bullet -cdot -cap -cup -uplus -sqcap -vee -wedge -setminus -wr -diamond -(?:big)?triangle.* -lhd -rhd -unlhd -unrhd -oplus -ominus -otimes -oslash -odot -bigcirc -d?dagger -amalg -leq -prec -preceq -ll -(?:sq)?su[bp]set(?:eq)? -in -vdash -geq -succ(?:eq)? -gg -ni -dashv -equiv -sim(?:eq)? -asymp -approx -cong -neq -doteq -propto -models -perp -mid -parallel -bowtie -Join -smile -frown -.*arrow -(?:long)?mapsto -.*harpoon.* -leadsto -aleph -hbar -imath -jmath -ell -wp -Re -Im -mho -prime -emptyset -nabla -surd -top -bot -angle -forall -exists -neg -flat -natural -sharp -backslash -partial -infty -Box -Diamond -triangle -clubsuit -diamondsuit -heartsuit -spadesuit -sum -prod -coprod -int -oint -big(?:sq)?c[au]p -bigvee -bigwedge -bigodot -bigotimes -bigoplus -biguplus -(?:arc)?(?:cos|sin|tan|cot)h? -csc -arg -deg -det -dim -exp -gcd -hom -inf -ker -lg -lim -liminf -limsup -ln -log -max -min -Pr -sec -sup -[Hclbdruvt] -(SUPER|SUB)SCRIPTNB -(SUPER|SUB)SCRIPT -PERCENTAGE -DOLLAR -%%END SAFE COMMANDS - -%%BEGIN TEXT COMMANDS -% Regex matching commands with a text argument (leave out the \) -addcontents.* -cc -closing -chapter -dashbox -emph -encl -fbox -framebox -footnote -footnotetext -framebox -part -(sub){0,2}section\*? -(sub)?paragraph\*? -makebox -mbox -opening -parbox -raisebox -savebox -sbox -shortstack -signature -text.* -value -underline -sqrt -(SUPER|SUB)SCRIPT -%%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 -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 -title -author -date -institute -%%END CONTEXT2 COMMANDS - - -%% TYPES (Commands for highlighting changed blocks) - -%DIF UNDERLINE PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue}\uwave{#1}}} -\providecommand{\DIFdel}[1]{{\protect\color{red}\sout{#1}}} -%DIF END UNDERLINE PREAMBLE - -%DIF CTRADITIONAL PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} [..\footnote{removed: #1} ]}} -%DIF END CTRADITIONAL PREAMBLE - -%DIF TRADITIONAL PREAMBLE -\RequirePackage[stable]{footmisc} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{[..\footnote{removed: #1} ]}} -%DIF END TRADITIONAL PREAMBLE - -%DIF CFONT PREAMBLE -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{{\protect\color{blue} \sf #1}} -\providecommand{\DIFdel}[1]{{\protect\color{red} \scriptsize #1}} -%DIF END CFONT PREAMBLE - -%DIF FONTSTRIKE PREAMBLE -\RequirePackage[normalem]{ulem} -\providecommand{\DIFadd}[1]{{\sf #1}} -\providecommand{\DIFdel}[1]{{\footnotesize \sout{#1}}} -%DIF END FONTSTRIKE PREAMBLE - -%DIF CCHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}#1}\protect\cbdelete} -%DIF END CCHANGEBAR PREAMBLE - -%DIF CFONTCHBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\RequirePackage{color}\definecolor{RED}{rgb}{1,0,0}\definecolor{BLUE}{rgb}{0,0,1} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\sf #1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\scriptsize #1}\protect\cbdelete} -%DIF END CFONTCHBAR PREAMBLE - -%DIF CULINECHBAR PREAMBLE -\RequirePackage[normalem]{ulem} -\RequirePackage[dvips]{changebar} -\RequirePackage{color} -\providecommand{\DIFadd}[1]{\protect\cbstart{\protect\color{blue}\uwave{#1}}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete{\protect\color{red}\sout{#1}}\protect\cbdelete} -%DIF END CULINECHBAR PREAMBLE - -%DIF CHANGEBAR PREAMBLE -\RequirePackage[dvips]{changebar} -\providecommand{\DIFadd}[1]{\protect\cbstart{#1}\protect\cbend} -\providecommand{\DIFdel}[1]{\protect\cbdelete} -%DIF END CHANGEBAR PREAMBLE - -%DIF INVISIBLE PREAMBLE -\providecommand{\DIFadd}[1]{#1} -\providecommand{\DIFdel}[1]{} -%DIF END INVISIBLE PREAMBLE - - -%% SUBTYPES (Markers for beginning and end of changed blocks) - -%DIF SAFE PREAMBLE -\providecommand{\DIFaddbegin}{} -\providecommand{\DIFaddend}{} -\providecommand{\DIFdelbegin}{} -\providecommand{\DIFdelend}{} -%DIF END SAFE PREAMBLE - -%DIF MARGIN PREAMBLE -\providecommand{\DIFaddbegin}{\protect\marginpar{a[}} -\providecommand{\DIFaddend}{\protect\marginpar{]}} -\providecommand{\DIFdelbegin}{\protect\marginpar{d[}} -\providecommand{\DIFdelend}{\protect\marginpar{]}} -%DIF END BRACKET PREAMBLE - -%DIF DVIPSCOL PREAMBLE -%Note: only works with dvips converter -\RequirePackage{color} -\RequirePackage{dvipscol} -\providecommand{\DIFaddbegin}{\protect\nogroupcolor{blue}} -\providecommand{\DIFaddend}{\protect\nogroupcolor{black}} -\providecommand{\DIFdelbegin}{\protect\nogroupcolor{red}} -\providecommand{\DIFdelend}{\protect\nogroupcolor{black}} -%DIF END DVIPSCOL PREAMBLE - -%DIF COLOR PREAMBLE -\RequirePackage{color} -\providecommand{\DIFaddbegin}{\protect\color{blue}} -\providecommand{\DIFaddend}{\protect\color{black}} -\providecommand{\DIFdelbegin}{\protect\color{red}} -\providecommand{\DIFdelend}{\protect\color{black}} -%DIF END COLOR PREAMBLE - -%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) -% 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 -% 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} -\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 -%% FLOAT TYPES - -%DIF FLOATSAFE PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END FLOATSAFE PREAMBLE - -%DIF IDENTICAL PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} -\providecommand{\DIFaddbeginFL}{\DIFaddbegin} -\providecommand{\DIFaddendFL}{\DIFaddend} -\providecommand{\DIFdelbeginFL}{\DIFdelbegin} -\providecommand{\DIFdelendFL}{\DIFdelend} -%DIF END IDENTICAL PREAMBLE - -%DIF TRADITIONALSAFE PREAMBLE -% procidecommand color to make this work for TRADITIONAL and CTRADITIONAL -\providecommand{\color}[1]{} -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} -\providecommand{\DIFdel}[1]{{\protect\color{red}[..{\scriptsize {removed: #1}} ]}} -\providecommand{\DIFaddbeginFL}{} -\providecommand{\DIFaddendFL}{} -\providecommand{\DIFdelbeginFL}{} -\providecommand{\DIFdelendFL}{} -%DIF END TRADITIONALSAFE PREAMBLE - -%% SPECIAL PACKAGE PREAMBLE COMMANDS - -% Standard \DIFadd and \DIFdel are redefined as \DIFaddtex and \DIFdeltex -% when hyperref package is included. -%DIF HYPERREF PREAMBLE -\providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} -\providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} -%DIF END HYPERREF PACKAGE diff --git a/latexdiff-1.0.4/latexdiff-vc b/latexdiff-1.0.4/latexdiff-vc deleted file mode 100755 index d38fc14..0000000 --- a/latexdiff-1.0.4/latexdiff-vc +++ /dev/null @@ -1,507 +0,0 @@ -#!/usr/bin/env perl -# -# latexdiff-vc - wrapper script for applying latexdiff to rcs managed files -# and for automatised creation of postscript or pdf from difference file -# -# Copyright (C) 2005-13 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# -# Contributors: S Utcke, H Bruyninckx -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# -# version 1.0.4alpha: -# - [ Patch #3486 contributed by cbarbu] add additional compilation for styles using chbar + avoid pdf/postscripts repeat in the code -# version 1.0.3: Bug fix: replace use of system('cp...') with File::Copy::copy (Patch contributed by D. Bremner) -# Quotes around system call file arguments to allow filenames with spaces (Patch contributed by ssteve) -# version 1.0.2: - option --so to use latexdiff-so -# version 1.0.1 (change version numbering to match that of latexdiff) -# - Option --fast to use latexdiff-fast, -# - git support (thanks to Bjorn Magnus Mathisen, Santi Béjar, Pietro Battiston and Stefan Alfredson for patches) - UNTESTED -# version 0.25: -# - bbl is allowed as alternative extension (instead of .tex) -# version 0.26a -# - Bug fix: it copes now correctly with the possibility that there are no changes between current -# and archived version -use Getopt::Long ; -use Pod::Usage qw/pod2usage/ ; -use File::Temp qw/tempdir/ ; -use File::Basename qw/dirname/; -use File::Copy; - -use strict ; -use warnings ; - -my $versionstring=< 1); -# Variables -my ($file1,$file2,$diff,$diffbase,$answer,$options,$infile,$append,$dirname,$cwd); -my (@files,@ldoptions,@tmpfiles,@ptmpfiles,@difffiles,$extracomp); # , - -Getopt::Long::Configure('pass_through','bundling'); - -GetOptions('revision|r:s' => \@revs, - 'cvs' => \$cvs, - 'rcs' => \$rcs, - 'svn' => \$svn, - 'git' => \$git, - 'dir|d:s' => \$dir, - 'fast' => \$fast, - 'so' => \$so, - 'postscript|ps' => \$postscript, - 'pdf' => \$pdf, - 'force' => \$force, - 'version' => \$version, - 'help|h' => \$help); - -$extracomp = join(" ",grep(/BAR/,@ARGV)); # special latexdiff options requiring additional compilation - -if ( $help ) { - pod2usage(1) ; -} - -if ( $version ) { - die $versionstring ; -} - -if ( $so ) { - $latexdiff='latexdiff-so'; -} -if ( $fast ) { - die "Cannot specify more than one of --fast or --so " if ($so); - $latexdiff='latexdiff-fast'; -} - -if ( $cvs ) { - $vc="CVS"; -} -if ( $rcs ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="RCS"; -} -if ( $svn ) { - die "Cannot specify more than one of --cvs, --rcs --svn or --git." if ($vc); - $vc="SVN"; -} -if ( $git ) { - die "Cannot specify more than one of --cvs, --rcs, --svn or --git." if ($vc); - $vc="GIT"; -} - - -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -r option -if ( @revs && ( -f $revs[$#revs] || $revs[$#revs] =~ /^-/ ) ) { - unshift @ARGV,$revs[$#revs]; - $revs[$#revs]=""; -} -# check whether the first file name or first passed-through option for latexdiff got misinterpreted as an option to an empty -d option -if ( defined($dir) && ( -f $dir || $dir =~ /^-/ ) ) { - unshift @ARGV,$dir; - $dir=""; -} - -#print "DEBUG: latexdiff-vc command line: ", join(" ",@ARGV), "\n"; - -$file2=pop @ARGV; -( defined($file2) && $file2 =~ /\.(tex|bbl)$/ ) or pod2usage("Must specify at least one tex or bbl file"); - -if (! $vc && scalar(@revs)>0 ) { - # have to guess $vc - # check whether we have a special name - if ( $0 =~ /-cvs$/ ) { - $vc="CVS"; - } elsif ( $0 =~ /-rcs$/ ) { - $vc="RCS"; - } elsif ( $0 =~ /-svn$/ ) { - $vc="SVN"; - } elsif ( $0 =~ /-git$/ ) { - $vc="GIT"; - } elsif ( -e "$file2,v" ) { - print STDERR "Guess you are using RCS ...\n"; - $vc="RCS"; - } elsif ( -d ".svn" ) { - print STDERR "Guess you are using SVN ...\n"; - $vc="SVN"; - } elsif ( -d ".git" ) { - print STDERR "Guess you are using GIT ...\n"; - $vc="GIT"; - } elsif ( -e "CVSROOT" || defined($ENV{"CVSROOT"}) ) { - print STDERR "Guess you are using CVS ...\n"; - $vc="CVS"; - } else { - print STDERR "Cannot figure out version control system, so I default to CVS\n"; - $vc="CVS"; - } -} - -if (defined($dir) && $dir=~/^\.\/?/ ) { - print STDERR "You wrote -dir=. but you do not really like to do that, do you ?\n"; - exit 10 -} - -if ( scalar(@revs)>0 ) { - if ( $vc eq "CVS" ) { - $diffcmd = "cvs diff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "RCS" ) { - $diffcmd = "rcsdiff -u -r"; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "SVN" ) { - $diffcmd = "svn diff -r "; - $patchcmd = "patch -R -p0"; - } elsif ( $vc eq "GIT" ) { - $diffcmd = "git diff -r --relative --no-prefix "; - $patchcmd = "patch -R -p0"; - # alternatively: - # $diffcmd = "git diff "; - # $patchcmd = "patch -R -p1"; - } else { - print STDERR "Unknown versioning system $vc \n"; - exit 10; - } -} - - -# make file list (last arguments), initial arguments have to be passed to latexdiff -# We assume an argument is a valid file rather than a latexdiff argument -# if it has extension .tex or .bbl - -@files=($file2); -while( $file1=pop @ARGV ) { - if ( $file1 =~ /\.(tex|bbl)$/ ) { - # $file1 looks like a valid file name and is prepended to file list - unshift @files, $file1 ; - } else { - # $file1 looks like an option for latexdiff, push it back to argument stack - unshift @ldoptions, $file1 ; - } -} - -if ( scalar(@revs) == 0 ) { - pod2usage("When -r option is not used, two .tex files (old and new) must be given on the command line") unless @files==2; - # compare two files - $file1=shift @files ; -} - -if ( scalar(@revs) == 2 ) { - $append = "-diff$revs[0]-$revs[1]"; -} elsif ( scalar(@revs) == 1 || $revs[0] ) { - $append = "-diff$revs[0]"; -} else { - $append = "-diff"; -} - -if ( defined ($dir) && ! $dir ) { - # bare -d option => choose directory name - ($dir=$append) =~ s/^-//; -} - -if ( ($vc eq "SVN" || $vc eq "CVS") && scalar(@revs)) { - length($revs[$#revs]) > 0 or $revs[$#revs]="HEAD"; - length($revs[0]) > 0 or $revs[0]="HEAD"; -} - -#exit ; - - -# cycle through all files - -@difffiles=(); -while ( $infile=$file2=shift @files ) { - print STDERR "Working on $infile \n"; - if ( scalar(@revs) == 1 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - push @tmpfiles,$file1; - # compare file with previous version ($revs[0]="") or specified version - ### system("$diffcmd$revs[0] $infile| $patchcmd -o$file1") ; - if (system("$diffcmd$revs[0] \"$infile\" | $patchcmd -o\"$file1\"")==0 and -z $file1 ) { - # no differences detected, i.e. file is equal to current version - copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; - } - } elsif ( scalar(@revs) == 2 ) { - ($file1=$infile) =~ s/\.(tex|bbl)/-oldtmp-$$.$1/ ; - $file2 =~ s/\.(tex|bbl)/-newtmp-$$.$1/ ; - push @tmpfiles,$file2; - if (system("$diffcmd$revs[1] $infile | $patchcmd -o$file2")==0 and -z $file2 ) { - copy($infile,$file2) || die "copy($infile,$file2) failed: $!"; - } - if (system("$diffcmd$revs[0] $infile | $patchcmd -o$file1")==0 and -z $file1 ) { - copy($infile,$file1) || die "copy($infile,$file1) failed: $!"; - }; - } - - if ( -z $file1 || -z $file2) { - print STDERR "One or both of the files to compare are empty. Possibly something went wrong in the retrieval of older versions. Aborting ...\n" ; - exit(10); - } - - # Get name of difference file - if ( defined($dir) ) { - $diff="$dir/$infile" ; - } else { - ($diff=$infile) =~ s/\.(tex|bbl)$/$append.$1/ ; - } - # make directories if needed - $dirname=dirname($diff) ; - system("mkdir -p $dirname") unless ( -e $dirname ); - - # Remaining options are passed to latexdiff - $options = join(" ",@ldoptions); - - if ( -e $diff && ! $force ) { - print STDERR "OK to overwrite existing file $diff (y/n)? "; - $answer = ; - unless ($answer =~ /^y/i ) { - unlink @tmpfiles; - die "Abort ... " ; - } - } - print "Running $latexdiff\n"; - unless ( system("$latexdiff $options \"$file1\" \"$file2\" > \"$diff\"") == 0 ) { - print STDERR "Something went wrong in $latexdiff. Deleting $diff and abort\n" ; unlink $diff ; exit(5) - }; - print "Generated difference file $diff\n"; - - if ( ( $postscript or $pdf ) and !( scalar(@revs) && greptex( qr/\\document(?:class|style)/ , $diff ) ) ) { - # save filename for later processing if postscript or pdf conversion is requested and either two-file mode was used (scalar(@revs)==0) or the diff file contains documentclass statement (ie. is a root document) - push @difffiles, $diff ; - } - - unlink @tmpfiles; -} - -foreach $diff ( @difffiles ) { - chomp($cwd=(`pwd`)); - if (defined($dir)) { - ( $diff =~ s/$dir\/?// ) ; - chdir $dir ; - } - @ptmpfiles=(); - ( $diffbase=$diff) =~ s/\.(tex)$// ; - - # adapt magically changebar styles to [pdftex] display driver if pdf output was selected - if ( $pdf ) { - system("sed \"s/Package\\[dvips\\]/Package[pdftex]/\" \"$diff\" > \"$diff.tmp$$\" ; \\mv \"$diff.tmp$$\" \"$diff\""); - $latexcmd = "pdflatex"; - } elsif ( $postscript ) { - $latexcmd = "latex"; - } - - if ( $pdf | $postscript ) { - print STDERR "PDF: $pdf Postscript: $postscript cwd $cwd\n"; - - if ( system("grep -q \'^[^%]*\\\\bibliography\' \"$diff\"") == 0 ) { - system("$latexcmd --interaction=batchmode \"$diff\"; bibtex \"$diffbase\";"); - push @ptmpfiles, "$diffbase.bbl","$diffbase.bbl" ; - } - - # if special needs, as CHANGEBAR - if ( $extracomp ) { - # print "Extracomp\n"; - system("$latexcmd --interaction=batchmode \"$diff\";"); - } - - # final compilation - system("$latexcmd --interaction=batchmode \"$diff\";"); # needed if cross-refs - system("$latexcmd \"$diff\";"); # final, with possible error messages - - if ( $postscript ) { - my $dvi="$diffbase.dvi"; - my $ps="$diffbase.ps"; - - system("dvips -o $ps $dvi"); - push @ptmpfiles, "$diffbase.aux","$diffbase.log",$dvi ; - print "Generated postscript file $ps\n"; - } - elsif ( $pdf ) { - push @ptmpfiles, "$diffbase.aux","$diffbase.log"; - } - } - unlink @ptmpfiles; - chdir $cwd; -} - -# greptex returns 1 if regex is not matched in filename -# 0 if there is a match -sub greptex { - my ($regex,$filename)=@_; - my ($i)=0; - open (FH, $filename) or die("Couldn't open $filename: $!"); - while () { - next if /^\s*%/; # skip comment lines - if ( m/$regex/ ) { - close(FH); - return(0); - } - # only scan 25 lines - $i++; - last if $i>25 ; - } - close(FH); - return(1); -} - - -=head1 NAME - -latexdiff-vc - wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) - -=head1 SYNOPSIS - -B [ F ] [ F ] B<-r> [F] [B<-r> F] F [ F ...] - - or - -B [ F ] [ F ][ B<--postscript> | B<--pdf> ] F F - -=head1 DESCRIPTION - -I is a wrapper script that applies I to a -file, or multiple files under version control (CVS, RCS or SVN), and optionally runs the -sequence of C and C or C commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. - -=head1 OPTIONS - -=over 4 - -=item B<--rcs>, B<--svn>, B<--cvs>, or B<--git> - -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. - -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. - -=item B<-r>, B<-r> F or B<--revision>, B<--revision=>F - -Choose revision (under RCS, CVS, SVN or GIT). One or two B<-r> options can be -specified, and they result in different behaviour: - -=over 4 - -=item B -r F ... - -compares F with the most recent version checked into RCS. - -=item B -r F F ... - -compares F with revision F. - -=item B -r F -r F F ... - -compares revisions F and F of F. - -Multiple files can be specified for all of the above options. All files must have the -extension C<.tex>, though. - -=item B F F - -compares two files. - -=back - -The name of the difference file is generated automatically and -reported to stdout. - -=item B<-d> or B<--dir> B<-d> F or B<--dir=>F - -Rather than appending the string C and optionally the version -numbers given to the output-file, this will prepend a directory name C -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname F can be specified, which is prepended instead of C. - -=item B<--fast> or B<--so> - -Use C or C, respectively (instead of C). - -=item B<--ps> or B<--postscript> - -Generate postscript output from difference file. This will run the -sequence C on the difference file (do not use -this option in the rare cases, where three C commands are -required if you care about correct referencing). If the difference -file contains a C<\bibliography> tag, run the sequence C. - -=item B<--pdf> - -Generate pdf output from difference file using C. This will -run the sequence C on the difference file, or -C for files requiring bibtex. - -=item B<--force> - -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. - -=item B<--help> or -B<-h> - -Show help text - -=item B<--version> - -Show version number - -=back - -All other options are passed on to C. - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I uses external commands and is therefore -limited to Unix-like systems. It also requires the RCS version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. - -=head1 BUG REPORTING - -Please submit bug reports using the issue tracker of the github repository page I, -or send them to I. Include the serial number of I -(option C<--version>) -. -=head1 AUTHOR - -Copyright (C) 2005,2012 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 -Contributors: S Utcke, H Bruyninckx - -=cut - diff --git a/latexdiff-1.0.4/latexdiff-vc.1 b/latexdiff-1.0.4/latexdiff-vc.1 deleted file mode 100644 index 87341f1..0000000 --- a/latexdiff-1.0.4/latexdiff-vc.1 +++ /dev/null @@ -1,252 +0,0 @@ -.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF-VC 1" -.TH LATEXDIFF-VC 1 "2014-07-20" "perl v5.18.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff\-vc \- wrapper script that calls latexdiff for different versions of a file under version management (CVS, RCS or SVN) -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ] \fB\-r\fR [\fIrev1\fR] [\fB\-r\fR \fIrev2\fR] \fIfile1.tex\fR [ \fIfile2.tex\fR ...] -.PP -.Vb 1 -\& or -.Ve -.PP -\&\fBlatexdiff-vc\fR [ \fIlatexdiff-options\fR ] [ \fIlatexdiff-vc-options\fR ][ \fB\-\-postscript\fR | \fB\-\-pdf\fR ] \fIold.tex\fR \fInew.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexdiff-vc\fR is a wrapper script that applies \fIlatexdiff\fR to a -file, or multiple files under version control (\s-1CVS, RCS\s0 or \s-1SVN\s0), and optionally runs the -sequence of \f(CW\*(C`latex\*(C'\fR and \f(CW\*(C`dvips\*(C'\fR or \f(CW\*(C`pdflatex\*(C'\fR commands necessary to -produce pdf or postscript output of the difference tex file(s). It can -also be applied to a pair of files to automatise the generation of difference -file in postscript or pdf format. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-\-rcs\fR, \fB\-\-svn\fR, \fB\-\-cvs\fR, or \fB\-\-git\fR" 4 -.IX Item "--rcs, --svn, --cvs, or --git" -Set the version system. -If no version system is specified, latexdiff-vc will venture a guess. -.Sp -latexdiff-cvs and latexdiff-rcs are variants of latexdiff-vc which default to -the respective versioning system. However, this default can still be overridden using the options above. -.IP "\fB\-r\fR, \fB\-r\fR \fIrev\fR or \fB\-\-revision\fR, \fB\-\-revision=\fR\fIrev\fR" 4 -.IX Item "-r, -r rev or --revision, --revision=rev" -Choose revision (under \s-1RCS, CVS, SVN\s0 or \s-1GIT\s0). One or two \fB\-r\fR options can be -specified, and they result in different behaviour: -.RS 4 -.IP "\fBlatexdiff-vc\fR \-r \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r file.tex ..." -compares \fIfile.tex\fR with the most recent version checked into \s-1RCS.\s0 -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 file.tex ..." -compares \fIfile.tex\fR with revision \fIrev1\fR. -.IP "\fBlatexdiff-vc\fR \-r \fIrev1\fR \-r \fIrev2\fR \fIfile.tex\fR ..." 4 -.IX Item "latexdiff-vc -r rev1 -r rev2 file.tex ..." -compares revisions \fIrev1\fR and \fIrev2\fR of \fIfile.tex\fR. -.Sp -Multiple files can be specified for all of the above options. All files must have the -extension \f(CW\*(C`.tex\*(C'\fR, though. -.IP "\fBlatexdiff-vc\fR \fIold.tex\fR \fInew.tex\fR" 4 -.IX Item "latexdiff-vc old.tex new.tex" -compares two files. -.RE -.RS 4 -.Sp -The name of the difference file is generated automatically and -reported to stdout. -.RE -.IP "\fB\-d\fR or \fB\-\-dir\fR \fB\-d\fR \fIpath\fR or \fB\-\-dir=\fR\fIpath\fR" 4 -.IX Item "-d or --dir -d path or --dir=path" -Rather than appending the string \f(CW\*(C`diff\*(C'\fR and optionally the version -numbers given to the output-file, this will prepend a directory name \f(CW\*(C`diff\*(C'\fR -to the -original filename, creating the directory and subdirectories should they not exist already. This is particularly useful in order to clone a -complete directory hierarchy. Optionally, a pathname \fIpath\fR can be specified, which is prepended instead of \f(CW\*(C`diff\*(C'\fR. -.IP "\fB\-\-fast\fR or \fB\-\-so\fR" 4 -.IX Item "--fast or --so" -Use \f(CW\*(C`latexdiff\-fast\*(C'\fR or \f(CW\*(C`latexdiff\-so\*(C'\fR, respectively (instead of \f(CW\*(C`latexdiff\*(C'\fR). -.IP "\fB\-\-ps\fR or \fB\-\-postscript\fR" 4 -.IX Item "--ps or --postscript" -Generate postscript output from difference file. This will run the -sequence \f(CW\*(C`latex; latex; dvips\*(C'\fR on the difference file (do not use -this option in the rare cases, where three \f(CW\*(C`latex\*(C'\fR commands are -required if you care about correct referencing). If the difference -file contains a \f(CW\*(C`\ebibliography\*(C'\fR tag, run the sequence \f(CW\*(C`latex; -bibtex; latex; latex; dvips\*(C'\fR. -.IP "\fB\-\-pdf\fR" 4 -.IX Item "--pdf" -Generate pdf output from difference file using \f(CW\*(C`pdflatex\*(C'\fR. This will -run the sequence \f(CW\*(C`pdflatex; pdflatex\*(C'\fR on the difference file, or -\&\f(CW\*(C`pdflatex; bibtex; pdflatex; pdflatex\*(C'\fR for files requiring bibtex. -.IP "\fB\-\-force\fR" 4 -.IX Item "--force" -Overwrite existing diff files without asking for confirmation. Default -behaviour is to ask for confirmation before overwriting an existing difference -file. -.IP "\fB\-\-help\fR or \fB\-h\fR" 4 -.IX Item "--help or -h" -Show help text -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Show version number -.PP -All other options are passed on to \f(CW\*(C`latexdiff\*(C'\fR. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff-vc\fR uses external commands and is therefore -limited to Unix-like systems. It also requires the \s-1RCS\s0 version control -system and latex to be installed on the system. Modules from Perl 5.8 -or higher are required. -.SH "BUG REPORTING" -.IX Header "BUG REPORTING" -Please submit bug reports using the issue tracker of the github repository page \fIhttps://github.com/ftilmann/latexdiff.git\fR, -or send them to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexdiff-vc\fR -(option \f(CW\*(C`\-\-version\*(C'\fR) -\&. -=head1 \s-1AUTHOR\s0 -.PP -Copyright (C) 2005,2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -Contributors: S Utcke, H Bruyninckx diff --git a/latexdiff-1.0.4/latexdiff.1 b/latexdiff-1.0.4/latexdiff.1 deleted file mode 100644 index cc7c69a..0000000 --- a/latexdiff-1.0.4/latexdiff.1 +++ /dev/null @@ -1,751 +0,0 @@ -.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXDIFF 1" -.TH LATEXDIFF 1 "2014-07-21" "perl v5.18.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexdiff \- determine and markup differences between two latex files -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexdiff\fR [ \fB\s-1OPTIONS\s0\fR ] \fIold.tex\fR \fInew.tex\fR > \fIdiff.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -Briefly, \fIlatexdiff\fR is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. -.PP -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "\f(CW\*(C`%DIF\ >\*(C'\fR" is appended to each added line, i.e. a -line present in \f(CW\*(C`new.tex\*(C'\fR but not in \f(CW\*(C`old.tex\*(C'\fR. Discarded lines - are deactivated by prepending "\f(CW\*(C`%DIF\ <\*(C'\fR". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file \f(CW\*(C`diff.tex\*(C'\fR will be similar to -\&\f(CW\*(C`new.tex\*(C'\fR. At the end of the preamble, the definitions for \fIlatexdiff\fR markup commands are inserted. -In differencing the main body of the text, \fIlatexdiff\fR attempts to -satisfy the following guidelines (in order of priority): -.IP "1." 3 -If both \f(CW\*(C`old.tex\*(C'\fR and \f(CW\*(C`new.tex\*(C'\fR are valid LaTeX, then the resulting -\&\f(CW\*(C`diff.tex\*(C'\fR should also be valid LateX. (\s-1NB\s0 If a few plain TeX commands -are used within \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR then \f(CW\*(C`diff.tex\*(C'\fR is not -guaranteed to work but usually will). -.IP "2." 3 -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -\&\f(CW\*(C`diff.tex\*(C'\fR. -.IP "3." 3 -If a changed passage contains text or text-producing commands, then -running \f(CW\*(C`diff.tex\*(C'\fR through LateX should produce output where added -and discarded passages are highlighted. -.IP "4." 3 -Where there are insignificant differences, e.g. in the positioning of -line breaks, \f(CW\*(C`diff.tex\*(C'\fR should follow the formatting of \f(CW\*(C`new.tex\*(C'\fR -.PP -For differencing the same algorithm as \fIdiff\fR is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, \f(CW\*(C`\ecaption\*(C'\fR and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write -.PP -.Vb 1 -\& \esection{\etextem{This is an emphasized section title}} -.Ve -.PP -and not -.PP -.Vb 1 -\& \esection {\etextem{This is an emphasized section title}} -.Ve -.PP -or -.PP -.Vb 1 -\& \esection\etextem{This is an emphasized section title} -.Ve -.PP -even though all varieties are the same to LaTeX (but see -\&\fB\-\-allow\-spaces\fR option which allows the second variety). -.PP -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the \s-1PICTUREENV\s0 configuration variable, set by -default to \f(CW\*(C`picture\*(C'\fR and \f(CW\*(C`DIFnomarkup\*(C'\fR environments; see \fB\-\-config\fR -option). The latter environment (\f(CW\*(C`DIFnomarkup\*(C'\fR) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by \f(CW\*(C`\ebegin{DIFnomarkup}\*(C'\fR and \f(CW\*(C`\eend{DIFnomarkup}\*(C'\fR. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, -.PP -\&\f(CW\*(C`\enewenvironment{DIFnomarkup}{}{}\*(C'\fR -.PP -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. -.PP -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. -.PP -All markup commands inserted by \fIlatexdiff\fR begin with "\f(CW\*(C`\eDIF\*(C'\fR". Added -blocks containing words, commands or comments which are in \f(CW\*(C`new.tex\*(C'\fR -but not in \f(CW\*(C`old.tex\*(C'\fR are marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR and \f(CW\*(C`\eDIFaddend\*(C'\fR. -Discarded blocks are marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR. -Within added blocks all text is highlighted with \f(CW\*(C`\eDIFadd\*(C'\fR like this: -\&\f(CW\*(C`\eDIFadd{Added text block}\*(C'\fR -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces \*(L"{\*(R" and \*(L"}\*(R" are never put within -the scope of \f(CW\*(C`\eDIFadd\*(C'\fR. Added comments are marked by prepending -"\f(CW\*(C`%DIF\ >\ \*(C'\fR". -.PP -Within deleted blocks text is highlighted with \f(CW\*(C`\eDIFdel\*(C'\fR. Deleted -comments are marked by prepending "\f(CW\*(C`%DIF\ <\ \*(C'\fR\*(L". Non-safe command -and curly braces within deleted blocks are commented out with -\&\*(R"\f(CW\*(C`%DIFDELCMD\ <\ \*(C'\fR". -.SH "OPTIONS" -.IX Header "OPTIONS" -.SS "Preamble" -.IX Subsection "Preamble" -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. -.IP "\fB\-\-type=markupstyle\fR or \fB\-t markupstyle\fR" 4 -.IX Item "--type=markupstyle or -t markupstyle" -Add code to preamble for selected markup style. This option defines -\&\f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands. -Available styles: -.Sp -\&\f(CW\*(C`UNDERLINE CTRADITIONAL TRADITIONAL CFONT FONTSTRIKE INVISIBLE -CHANGEBAR CCHANGEBAR CULINECHBAR CFONTCBHBAR\*(C'\fR -.Sp -[ Default: \f(CW\*(C`UNDERLINE\*(C'\fR ] -.IP "\fB\-\-subtype=markstyle\fR or \fB\-s markstyle\fR" 4 -.IX Item "--subtype=markstyle or -s markstyle" -Add code to preamble for selected style for bracketing -commands (e.g. to mark changes in margin). This option defines -\&\f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR commands. -Available styles: \f(CW\*(C`SAFE MARGINAL COLOR DVIPSCOL LABEL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`SAFE\*(C'\fR ] -.IP "\fB\-\-floattype=markstyle\fR or \fB\-f markstyle\fR" 4 -.IX Item "--floattype=markstyle or -f markstyle" -Add code to preamble for selected style which -replace standard marking and markup commands within floats -(e.g., marginal remarks cause an error within floats -so marginal marking can be disabled thus). This option defines all -\&\f(CW\*(C`\eDIF...FL\*(C'\fR commands. -Available styles: \f(CW\*(C`FLOATSAFE TRADITIONALSAFE IDENTICAL\*(C'\fR -.Sp -[ Default: \f(CW\*(C`FLOATSAFE\*(C'\fR ] -.IP "\fB\-\-encoding=enc\fR or \fB\-e enc\fR" 4 -.IX Item "--encoding=enc or -e enc" -Specify encoding of old.tex and new.tex. Typical encodings are -\&\f(CW\*(C`ascii\*(C'\fR, \f(CW\*(C`utf8\*(C'\fR, \f(CW\*(C`latin1\*(C'\fR, \f(CW\*(C`latin9\*(C'\fR. A list of available encodings can be -obtained by executing -.Sp -\&\f(CW\*(C`perl \-MEncode \-e \*(Aqprint join ("\en",Encode\-\*(C'\fRencodings( \*(L":all\*(R" )) ;' > -.Sp -[Default encoding is utf8 unless the first few lines of the preamble contain -an invocation \f(CW\*(C`\eusepackage[..]{inputenc}\*(C'\fR in which case the -encoding chosen by this command is asssumed. Note that \s-1ASCII \s0(standard -latex) is a subset of utf8] -.IP "\fB\-\-preamble=file\fR or \fB\-p file\fR" 4 -.IX Item "--preamble=file or -p file" -Insert file at end of preamble instead of generating -preamble. The preamble must define the following commands -\&\f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFadd{..}, -\&\eDIFdelbegin,\eDIFdelend,\eDIFdel{..},\*(C'\fR -and varieties for use within floats -\&\f(CW\*(C`\eDIFaddbeginFL, \eDIFaddendFL, \eDIFaddFL{..}, -\&\eDIFdelbeginFL, \eDIFdelendFL, \eDIFdelFL{..}\*(C'\fR -(If this option is set \fB\-t\fR, \fB\-s\fR, and \fB\-f\fR options -are ignored.) -.IP "\fB\-\-packages=pkg1,pkg2,..\fR" 4 -.IX Item "--packages=pkg1,pkg2,.." -Tell latexdiff that .tex file is processed with the packages in list -loaded. This is normally not necessary if the .tex file includes the -preamble, as the preamble is automatically scanned for \f(CW\*(C`\eusepackage\*(C'\fR commands. -Use of the \fB\-\-packages\fR option disables automatic scanning, so if for any -reason package specific parsing needs to be switched off, use \fB\-\-packages=none\fR. -The following packages trigger special behaviour: -.RS 4 -.ie n .IP """amsmath""" 8 -.el .IP "\f(CWamsmath\fR" 8 -.IX Item "amsmath" -Configuration variable amsmath is set to \f(CW\*(C`align*\*(C'\fR (Default: \f(CW\*(C`eqnarray*\*(C'\fR) -.ie n .IP """endfloat""" 8 -.el .IP "\f(CWendfloat\fR" 8 -.IX Item "endfloat" -Ensure that \f(CW\*(C`\ebegin{figure}\*(C'\fR and \f(CW\*(C`\eend{figure}\*(C'\fR always appear by themselves on a line. -.ie n .IP """hyperref""" 8 -.el .IP "\f(CWhyperref\fR" 8 -.IX Item "hyperref" -Change name of \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands to \f(CW\*(C`\eDIFaddtex\*(C'\fR and \f(CW\*(C`\eDIFdeltex\*(C'\fR and -define new \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands, which provide a wrapper for these commands, -using them for the text but not for the link defining command (where any markup would cause -errors). -.ie n .IP """apacite""" 8 -.el .IP "\f(CWapacite\fR" 8 -.IX Item "apacite" -Redefine the commands recognised as citation commands. -.RE -.RS 4 -.Sp -[ Default: scan the preamble for \f(CW\*(C`\e\eusepackage\*(C'\fR commands to determine - loaded packages.] -.RE -.IP "\fB\-\-show\-preamble\fR" 4 -.IX Item "--show-preamble" -Print generated or included preamble commands to stdout. -.SS "Configuration" -.IX Subsection "Configuration" -.ie n .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-safecmd=exclude\-file\fR or \fB\-A exclude-file\fR or \fB\-\-exclude\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-safecmd=exclude-file or -A exclude-file or --exclude-safecmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-safecmd=replace\-file\fR" 4 -.IX Item "--replace-safecmd=replace-file" -.ie n .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-safecmd=append\-file\fR or \fB\-a append-file\fR or \fB\-\-append\-safecmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-safecmd=append-file or -a append-file or --append-safecmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions (RegEx) -matching commands which are safe to use within the -scope of a \f(CW\*(C`\eDIFadd\*(C'\fR or \f(CW\*(C`\eDIFdel\*(C'\fR command. The file must contain -one Perl-RegEx per line (Comment lines beginning with # or % are -ignored). Note that the RegEx needs to match the whole of -the token, i.e., /^regex$/ is implied and that the initial -\&\*(L"\e\*(R" of the command is not included. -The \fB\-\-exclude\-safecmd\fR and \fB\-\-append\-safecmd\fR options can be combined with the \-\fB\-\-replace\-safecmd\fR -option and can be used repeatedly to add cumulatively to the lists. - \fB\-\-exclude\-safecmd\fR -and \fB\-\-append\-safecmd\fR can also take a comma separated list as input. If a -comma for one of the regex is required, escape it thus \*(L"\e,\*(R". In most cases it -will be necessary to protect the comma-separated list from the shell by putting -it in quotation marks. -.ie n .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-exclude\-textcmd=exclude\-file\fR or \fB\-X exclude-file\fR or \fB\-\-exclude\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--exclude-textcmd=exclude-file or -X exclude-file or --exclude-textcmd=cmd1,cmd2,..." -.PD 0 -.IP "\fB\-\-replace\-textcmd=replace\-file\fR" 4 -.IX Item "--replace-textcmd=replace-file" -.ie n .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-textcmd=append\-file\fR or \fB\-x append-file\fR or \fB\-\-append\-textcmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-textcmd=append-file or -x append-file or --append-textcmd=cmd1,cmd2,..." -.PD -Exclude from, replace or append to the list of regular expressions -matching commands whose last argument is text. See -entry for \fB\-\-exclude\-safecmd\fR directly above for further details. -.IP "\fB\-\-replace\-context1cmd=replace\-file\fR" 4 -.IX Item "--replace-context1cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=""cmd1,cmd2,...""\fR" 4 -.el .IP "\fB\-\-append\-context1cmd=append\-file\fR or =item \fB\-\-append\-context1cmd=``cmd1,cmd2,...''\fR" 4 -.IX Item "--append-context1cmd=append-file or =item --append-context1cmd=cmd1,cmd2,..." -.PD -Replace or append to the list of regex matching commands -whose last argument is text but which require a particular -context to work, e.g. \ecaption will only work within a figure -or table. These commands behave like text commands, except when -they occur in a deleted section, when they are disabled, but their -argument is shown as deleted text. -.IP "\fB\-\-replace\-context2cmd=replace\-file\fR" 4 -.IX Item "--replace-context2cmd=replace-file" -.PD 0 -.ie n .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=""cmd1,cmd2,...""\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.el .IP "\fB\-\-append\-context2cmd=append\-file\fR or =item \fB\-\-append\-context2cmd=``cmd1,cmd2,...''\fR As corresponding commands for context1. The only difference is that context2 commands are completely disabled in deleted sections, including their arguments." 4 -.IX Item "--append-context2cmd=append-file or =item --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." -.IP "\fB\-\-config var1=val1,var2=val2,...\fR or \fB\-c var1=val1,..\fR" 4 -.IX Item "--config var1=val1,var2=val2,... or -c var1=val1,.." -.IP "\fB\-c configfile\fR" 4 -.IX Item "-c configfile" -.PD -Set configuration variables. The option can be repeated to set different -variables (as an alternative to the comma-separated list). -Available variables (see below for further explanations): -.Sp -\&\f(CW\*(C`MINWORDSBLOCK\*(C'\fR (integer) -.Sp -\&\f(CW\*(C`FLOATENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`PICTUREENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`MATHARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`MATHARRREPL\*(C'\fR (String) -.Sp -\&\f(CW\*(C`ARRENV\*(C'\fR (RegEx) -.Sp -\&\f(CW\*(C`COUNTERCMD\*(C'\fR (RegEx) -.IP "\fB\-\-show\-safecmd\fR" 4 -.IX Item "--show-safecmd" -Print list of RegEx matching and excluding safe commands. -.IP "\fB\-\-show\-textcmd\fR" 4 -.IX Item "--show-textcmd" -Print list of RegEx matching and excluding commands with text argument. -.IP "\fB\-\-show\-config\fR" 4 -.IX Item "--show-config" -Show values of configuration variables. -.IP "\fB\-\-show\-all\fR" 4 -.IX Item "--show-all" -Combine all \-\-show commands. -.Sp -\&\s-1NB\s0 For all \-\-show commands, no \f(CW\*(C`old.tex\*(C'\fR or \f(CW\*(C`new.tex\*(C'\fR file needs to be specified, and no -differencing takes place. -.SS "Other configuration options:" -.IX Subsection "Other configuration options:" -.IP "\fB\-\-allow\-spaces\fR" 4 -.IX Item "--allow-spaces" -Allow spaces between bracketed or braced arguments to commands. Note -that this option might have undesirable side effects (unrelated scope -might get lumpeded with preceding commands) so should only be used if the -default produces erroneous results. (Default requires arguments to -directly follow each other without intervening spaces). -.IP "\fB\-\-math\-markup=level\fR" 4 -.IX Item "--math-markup=level" -Determine granularity of markup in displayed math environments: -Possible values for level are (both numerical and text labels are acceptable): -.Sp -\&\f(CW\*(C`off\*(C'\fR or \f(CW0\fR: suppress markup for math environments. Deleted equations will not -appear in diff file. This mode can be used if all the other modes -cause invalid latex code. -.Sp -\&\f(CW\*(C`whole\*(C'\fR or \f(CW1\fR: Differencing on the level of whole equations. Even trivial changes -to equations cause the whole equation to be marked changed. This -mode can be used if processing in coarse or fine mode results in -invalid latex code. -.Sp -\&\f(CW\*(C`coarse\*(C'\fR or \f(CW2\fR: Detect changes within equations marked up with a coarse -granularity; changes in equation type (e.g.displaymath to equation) -appear as a change to the complete equation. This mode is recommended -for situations where the content and order of some equations are still -being changed. [Default] -.Sp -\&\f(CW\*(C`fine\*(C'\fR or \f(CW3\fR: Detect small change in equations and mark up at fine granularity. -This mode is most suitable, if only minor changes to equations are -expected, e.g. correction of typos. -.IP "\fB\-\-disable\-citation\-markup\fR" 4 -.IX Item "--disable-citation-markup" -Suppress citation markup in styles using ulem (\s-1UNDERLINE, -FONTSTRIKE, CULINECHBAR\s0) -.IP "\fB\-\-enable\-citation\-markup\fR" 4 -.IX Item "--enable-citation-markup" -Protect citation commands in changed sections with \e\embox command [i.e. use default behaviour for ulem package for other packages] -.SS "Miscellaneous" -.IX Subsection "Miscellaneous" -.IP "\fB\-\-verbose\fR or \fB\-V\fR" 4 -.IX Item "--verbose or -V" -Output various status information to stderr during processing. -Default is to work silently. -.IP "\fB\-\-driver=type\fR" 4 -.IX Item "--driver=type" -Choose driver for changebar package (only relevant for styles using - changebar: \s-1CCHANGEBAR CFONTCHBAR CULINECHBAR CHANGEBAR\s0). Possible -drivers are listed in changebar manual, e.g. pdftex,dvips,dvitops - [Default: dvips] -.IP "\fB\-\-ignore\-warnings\fR" 4 -.IX Item "--ignore-warnings" -Suppress warnings about inconsistencies in length between input and -parsed strings and missing characters. These warning messages are -often related to non-standard latex or latex constructions with a -syntax unknown to \f(CW\*(C`latexdiff\*(C'\fR but the resulting difference argument -is often fully functional anyway, particularly if the non-standard -latex only occurs in parts of the text which have not changed. -.IP "\fB\-\-label=label\fR or \fB\-L label\fR" 4 -.IX Item "--label=label or -L label" -Sets the labels used to describe the old and new files. The first use -of this option sets the label describing the old file and the second -use of the option sets the label for the new file, i.e. set both -labels like this \f(CW\*(C`\-L labelold \-L labelnew\*(C'\fR. -[Default: use the filename and modification dates for the label] -.IP "\fB\-\-no\-label\fR" 4 -.IX Item "--no-label" -Suppress inclusion of old and new file names as comment in output file -.IP "\fB\-\-visble\-label\fR" 4 -.IX Item "--visble-label" -Include old and new filenames (or labels set with \-\-label option) as -visible output. -.IP "\fB\-\-flatten\fR" 4 -.IX Item "--flatten" -Replace \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within body by the content -of the files in their argument. If \f(CW\*(C`\eincludeonly\*(C'\fR is present in the -preamble, only those files are expanded into the document. However, -no recursion is done, i.e. \f(CW\*(C`\einput\*(C'\fR and \f(CW\*(C`\einclude\*(C'\fR commands within -included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, -respectively, making it possible to organise files into old and new directories. -\&\-\-flatten is applied recursively, so inputted files can contain further -\&\f(CW\*(C`\einput\*(C'\fR statements. -.Sp -Use of this option might result in prohibitive processing times for -larger documents, and the resulting difference document -no longer reflects the structure of the input documents. -.IP "\fB\-\-help\fR or \fB\-h\fR" 4 -.IX Item "--help or -h" -Show help text -.IP "\fB\-\-version\fR" 4 -.IX Item "--version" -Show version number -.SS "Predefined styles" -.IX Subsection "Predefined styles" -.SS "Major types" -.IX Subsection "Major types" -The major type determine the markup of plain text and some selected latex commands outside floats by defining the markup commands \f(CW\*(C`\eDIFadd{...}\*(C'\fR and \f(CW\*(C`\eDIFdel{...}\*(C'\fR . -.ie n .IP """UNDERLINE""" 10 -.el .IP "\f(CWUNDERLINE\fR" 10 -.IX Item "UNDERLINE" -Added text is wavy-underlined and blue, discarded text is struck out and red -(Requires color and ulem packages). Overstriking does not work in displayed math equations such that deleted parts of equation are underlined, not struck out (this is a shortcoming inherent to the ulem package). -.ie n .IP """CTRADITIONAL""" 10 -.el .IP "\f(CWCTRADITIONAL\fR" 10 -.IX Item "CTRADITIONAL" -Added text is blue and set in sans-serif, and a red footnote is created for each discarded -piece of text. (Requires color package) -.ie n .IP """TRADITIONAL""" 10 -.el .IP "\f(CWTRADITIONAL\fR" 10 -.IX Item "TRADITIONAL" -Like \f(CW\*(C`CTRADITIONAL\*(C'\fR but without the use of color. -.ie n .IP """CFONT""" 10 -.el .IP "\f(CWCFONT\fR" 10 -.IX Item "CFONT" -Added text is blue and set in sans-serif, and discarded text is red and very small size. -.ie n .IP """FONTSTRIKE""" 10 -.el .IP "\f(CWFONTSTRIKE\fR" 10 -.IX Item "FONTSTRIKE" -Added tex is set in sans-serif, discarded text small and struck out -.ie n .IP """CCHANGEBAR""" 10 -.el .IP "\f(CWCCHANGEBAR\fR" 10 -.IX Item "CCHANGEBAR" -Added text is blue, and discarded text is red. Additionally, the changed text is marked with a bar in the margin (Requires color and changebar packages). -.ie n .IP """CFONTCHBAR""" 10 -.el .IP "\f(CWCFONTCHBAR\fR" 10 -.IX Item "CFONTCHBAR" -Like \f(CW\*(C`CFONT\*(C'\fR but with additional changebars (Requires color and changebar packages). -.ie n .IP """CULINECHBAR""" 10 -.el .IP "\f(CWCULINECHBAR\fR" 10 -.IX Item "CULINECHBAR" -Like \f(CW\*(C`UNDERLINE\*(C'\fR but with additional changebars (Requires color, ulem and changebar packages). -.ie n .IP """CHANGEBAR""" 10 -.el .IP "\f(CWCHANGEBAR\fR" 10 -.IX Item "CHANGEBAR" -No mark up of text, but mark margins with changebars (Requires changebar package). -.ie n .IP """INVISIBLE""" 10 -.el .IP "\f(CWINVISIBLE\fR" 10 -.IX Item "INVISIBLE" -No visible markup (but generic markup commands will still be inserted. -.SS "Subtypes" -.IX Subsection "Subtypes" -The subtype defines the commands that are inserted at the begin and end of added or discarded blocks, irrespectively of whether these blocks contain text or commands (Defined commands: \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR) -.ie n .IP """SAFE""" 10 -.el .IP "\f(CWSAFE\fR" 10 -.IX Item "SAFE" -No additional markup (Recommended choice) -.ie n .IP """MARGIN""" 10 -.el .IP "\f(CWMARGIN\fR" 10 -.IX Item "MARGIN" -Mark beginning and end of changed blocks with symbols in the margin nearby (using -the standard \f(CW\*(C`\emarginpar\*(C'\fR command \- note that this sometimes moves somewhat -from the intended position. -.ie n .IP """COLOR""" 10 -.el .IP "\f(CWCOLOR\fR" 10 -.IX Item "COLOR" -An alternative way of marking added passages in blue, and deleted ones in red. -(It is recommeneded to use instead the main types to effect colored markup, -although in some cases coloring with dvipscol can be more complete, for example -with citation commands). -.ie n .IP """DVIPSCOL""" 10 -.el .IP "\f(CWDVIPSCOL\fR" 10 -.IX Item "DVIPSCOL" -An alternative way of marking added passages in blue, and deleted ones in red. Note -that \f(CW\*(C`DVIPSCOL\*(C'\fR 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). -.SS "Float Types" -.IX Subsection "Float Types" -Some of the markup used in the main text might cause problems when used within -floats (e.g. figures or tables). For this reason alternative versions of all -markup commands are used within floats. The float type defines these alternative commands. -.ie n .IP """FLOATSAFE""" 10 -.el .IP "\f(CWFLOATSAFE\fR" 10 -.IX Item "FLOATSAFE" -Use identical markup for text as in the main body, but set all commands marking the begin and end of changed blocks to null-commands. You have to choose this float type if your subtype is \f(CW\*(C`MARGIN\*(C'\fR as \f(CW\*(C`\emarginpar\*(C'\fR does not work properly within floats. -.ie n .IP """TRADITIONALSAFE""" 10 -.el .IP "\f(CWTRADITIONALSAFE\fR" 10 -.IX Item "TRADITIONALSAFE" -Mark additions the same way as in the main text. Deleted environments are marked by angular brackets \e[ and \e] and the deleted text is set in scriptscript size. This float type should always be used with the \f(CW\*(C`TRADITIONAL\*(C'\fR and \f(CW\*(C`CTRADITIONAL\*(C'\fR markup types as the \efootnote command does not work properly in floating environments. -.ie n .IP """IDENTICAL""" 10 -.el .IP "\f(CWIDENTICAL\fR" 10 -.IX Item "IDENTICAL" -Make no difference between the main text and floats. -.SS "Configuration Variables" -.IX Subsection "Configuration Variables" -.ie n .IP """MINWORDSBLOCK""" 10 -.el .IP "\f(CWMINWORDSBLOCK\fR" 10 -.IX Item "MINWORDSBLOCK" -Minimum number of tokens required to form an independent block. This value is -used in the algorithm to detect changes of complete blocks by merging identical text parts of less than \f(CW\*(C`MINWORDSBLOCK\*(C'\fR to the preceding added and discarded parts. -.Sp -[ Default: 3 ] -.ie n .IP """FLOATENV""" 10 -.el .IP "\f(CWFLOATENV\fR" 10 -.IX Item "FLOATENV" -Environments whose name matches the regular expression in \f(CW\*(C`FLOATENV\*(C'\fR are -considered floats. Within these environments, the \fIlatexdiff\fR markup commands -are replaced by their \s-1FL\s0 variaties. -.Sp -[ Default: \f(CW\*(C`(?:figure|table|plate)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """PICTUREENV""" 10 -.el .IP "\f(CWPICTUREENV\fR" 10 -.IX Item "PICTUREENV" -Within environments whose name matches the regular expression in \f(CW\*(C`PICTUREENV\*(C'\fR -all latexdiff markup is removed (in pathologic cases this might lead to - inconsistent markup but this situation should be rare). -.Sp -[ Default: \f(CW\*(C`(?:picture|DIFnomarkup)[\ew\ed*@]*\*(C'\fR\ ] -.ie n .IP """MATHENV"",""MATHREPL""" 10 -.el .IP "\f(CWMATHENV\fR,\f(CWMATHREPL\fR" 10 -.IX Item "MATHENV,MATHREPL" -If both \ebegin and \eend for a math environment (environment name matching \f(CW\*(C`MATHENV\*(C'\fR -or \e[ and \e]) -are within the same deleted block, they are replaced by a \ebegin and \eend commands for \f(CW\*(C`MATHREPL\*(C'\fR -rather than being commented out. -.Sp -[ Default: \f(CW\*(C`MATHENV\*(C'\fR=\f(CW\*(C`(?:displaymath|equation)\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`displaymath\*(C'\fR\ ] -.ie n .IP """MATHARRENV"",""MATHARRREPL""" 10 -.el .IP "\f(CWMATHARRENV\fR,\f(CWMATHARRREPL\fR" 10 -.IX Item "MATHARRENV,MATHARRREPL" -as \f(CW\*(C`MATHENV\*(C'\fR,\f(CW\*(C`MATHREPL\*(C'\fR but for equation arrays -.Sp -[ Default: \f(CW\*(C`MATHARRENV\*(C'\fR=\f(CW\*(C`eqnarray\e*?\*(C'\fR\ , \f(CW\*(C`MATHREPL\*(C'\fR=\f(CW\*(C`eqnarray\*(C'\fR\ ] -.ie n .IP """ARRENV""" 10 -.el .IP "\f(CWARRENV\fR" 10 -.IX Item "ARRENV" -If a match to \f(CW\*(C`ARRENV\*(C'\fR is found within an inline math environment within a deleted or added block, then the inlined math -is surrounded by \f(CW\*(C`\embox{\*(C'\fR...\f(CW\*(C`}\*(C'\fR. This is necessary as underlining does not work within inlined array environments. -.Sp -[ Default: \f(CW\*(C`ARRENV\*(C'\fR=\f(CW\*(C`(?:array|[pbvBV]matrix)\*(C'\fR\ -.ie n .IP """COUNTERCMD""" 10 -.el .IP "\f(CWCOUNTERCMD\fR" 10 -.IX Item "COUNTERCMD" -If a command in a deleted block which is also in the textcmd list matches \f(CW\*(C`COUNTERCMD\*(C'\fR then an -additional command \f(CW\*(C`\eaddtocounter{\*(C'\fR\fIcntcmd\fR\f(CW\*(C`}{\-1}\*(C'\fR, where \fIcntcmd\fR is the matching command, is appended in the diff file such that the numbering in the diff file remains synchronized with the -numbering in the new file. -.Sp -[ Default: \f(CW\*(C`COUNTERCMD\*(C'\fR=\f(CW\*(C`(?:footnote|part|section|subsection\*(C'\fR ... -.Sp -\&\f(CW\*(C`|subsubsection|paragraph|subparagraph)\*(C'\fR ] -.SH "COMMON PROBLEMS" -.IX Header "COMMON PROBLEMS" -.IP "Citations result in overfull boxes" 10 -.IX Item "Citations result in overfull boxes" -There is an incompatibility between the \f(CW\*(C`ulem\*(C'\fR package, which \f(CW\*(C`latexdiff\*(C'\fR uses for underlining and striking out in the \s-1UNDERLINE\s0 style, -the default style. In order to be able to mark up citations properly, they are placed with an \f(CW\*(C`\embox\*(C'\fR 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: -.Sp -1. Use \f(CW\*(C`COLOR\*(C'\fR or \f(CW\*(C`DVIPSCOL\*(C'\fR subtype markup (option \f(CW\*(C`\-s COLOR\*(C'\fR): 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. -.Sp -2. Choose option \f(CW\*(C`\-\-disable\-citation\-markup\*(C'\fR 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) -.IP "Changes in complicated mathematical equations result in latex processing errors" 10 -.IX Item "Changes in complicated mathematical equations result in latex processing errors" -Try options \f(CW\*(C`\-\-math\-markup=whole\*(C'\fR. If even that fails, you can turn off mark up for equations with \f(CW\*(C`\-\-math\-markup=off\*(C'\fR. -.SH "BUGS" -.IX Header "BUGS" -Option allow-spaces not implemented entirely consistently. It breaks -the rules that number and type of white space does not matter, as -different numbers of inter-argument spaces are treated as significant. -.PP -Please submit bug reports using the issue tracker of the github repository page \fIhttps://github.com/ftilmann/latexdiff.git\fR, -or send them to \fItilmann@gfz\-potsdam.de\fR. Include the serial number of \fIlatexdiff\fR -(from comments at the top of the source or use \fB\-\-version\fR). 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 -latex, please send me those files, ideally edited to only contain the -offending passage as long as that still reproduces the problem. If your -file relies on non-standard class files, you must include those. I will not -look at examples where I have trouble to latex the original files. -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexrevise, latexdiff-vc -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexdiff\fR does not make use of external commands and thus should run -on any platform supporting Perl 5.6 or higher. If files with encodings -other than \s-1ASCII\s0 or \s-1UTF\-8\s0 are processed, Perl 5.8 or higher is required. -.PP -The standard version of \fIlatexdiff\fR requires installation of the Perl package -\&\f(CW\*(C`Algorithm::Diff\*(C'\fR (available from \fIwww.cpan.org\fR \- -\&\fIhttp://search.cpan.org/~nedkonz/Algorithm\-Diff\-1.15\fR) but a stand-alone -version, \fIlatexdiff-so\fR, which has this package inlined, is available, too. -\&\fIlatexdiff-fast\fR requires the \fIdiff\fR command to be present. -.SH "AUTHOR" -.IX Header "AUTHOR" -Version 1.0.4 -Copyright (C) 2004\-2012 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 -.PP -Contributors of fixes and additions: V. Kuhlmann, J. Paisley, N. Becker, T. Doerges, K. Huebner, -T. Connors, Sebastian Gouezel and many others. -Thanks to the many people who sent in bug reports, feature suggestions, and other feedback. diff --git a/latexdiff-1.0.4/latexrevise b/latexdiff-1.0.4/latexrevise deleted file mode 100755 index 85955af..0000000 --- a/latexdiff-1.0.4/latexrevise +++ /dev/null @@ -1,538 +0,0 @@ -#!/usr/bin/env perl -# latexrevise - takes output file of latexdiff and removes either discarded -# or appended passages, then deletes all other latexdiff markup -# -# Copyright (C) 2004 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Detailed usage information at the end of the file -# Note: version number now keeping up with latexdiff -# Version 1.0.2 Option --version -# Version 1.0.1 no changes to latexrevise -# Version 0.3 Updated for compatibility with latexdiff 0.3 output (DIFAUXCMD removal) -# Version 0.1 First public release - -use Getopt::Long ; -use strict; -use warnings; - -my $versionstring=< \$accept, - 'decline|d'=> \$decline, - 'simplify|s' => \$simplify, - 'comment|c=s' => \$comment, - 'comment-environment|e=s' => \$comenv, - 'markup|m=s' => \$markup, - 'markup-environment|n=s' => \$markenv, - 'no-warnings|q' => \$verbose, - 'version' => \$version, - 'verbose|V' => \$verbose, - 'help|h|H' => \$help); - -if ( $help ) { - usage() ; -} - -if ( $version ) { - die $versionstring ; -} - - -if ( ($accept && $decline) || ($accept && $simplify) || ($decline && $simplify) ) { - die '-a,-d and -s options are mutually axclusive. Type latexrevise -h to get more help.'; -} - - - -print STDERR "ACCEPT mode\n" if $verbose && $accept; -print STDERR "DECLINE mode\n" if $verbose && $decline; -print STDERR "SIMPLIFY mode. WARNING: The output will not normally be valid latex,\n" if $verbose && $simplify; - -# Slurp old and new files -{ - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $input=<>; -} - -# split into parts -($preamble,$body,$post)=splitdoc($input,'\begin{document}','\end{document}'); - -if (length $preamble && ( $accept || $decline ) ) { - # - # WORK ON PREAMBLE - # - # (compare subroutine linediff in latexdiff to make sure correct strings are used) - - # remove extra commands added to preamble by latexdiff - $preamble =~ s/${PREAMBLEXTBEG}.*?${PREAMBLEXTEND}\n{0,1}//smg ; - - if ( $accept ) { - # delete mark up in appended lines - $preamble =~ s/^(.*) %DIF > $/$1/mg ; - } elsif ( $decline ) { - # delete appended lines - # $preamble =~ s/^(.*) %DIF > $//mg ; - $preamble =~ s/^(.*) %DIF > \n//mg ; - # delete markup in deleted lines - $preamble =~ s/^%DIF < //mg ; - } - # remove any remaining DIF markups - #$preamble =~ s/%DIF.*$//mg ; - $preamble =~ s/%DIF.*?\n//sg ; -} -#print $preamble ; - -# -# WORK ON BODY -# -if ($accept) { - # remove ADDMARKOPEN, ADDMARKCLOSE tokens - @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/$1/sg; - # remove text flanked by DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}//sg; - # remove markup of added comments - $body =~ s/%${ADDCOMMENT}(.*?)$/%$1/mg ; - # remove deleted comments (full line) - $body =~ s/^%${DELCOMMENT}.*?\n//mg ; - # remove deleted comments (part of line) - $body =~ s/%${DELCOMMENT}.*?$//mg ; -} -elsif ( $decline) { - # remove DELMARKOPEN, DELMARKCLOSE tokens - @matches= $body =~ m/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/sg; - checkpure(@matches); - $body =~ s/${DELMARKOPEN}(.*?)${DELMARKCLOSE}/$1/sg; - # remove text flanked by ADDMARKOPEN, ADDMARKCLOSE tokens - # as latexdiff algorithm keeps the formatting and white spaces - # of the new text, sometimes whitespace might be inserted or - # removed inappropriately. We try to guess whether this has - # happened - - # Mop up tokens. This must be done already now as otherwise - # detection of white-space problems does not work - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - # remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - $cnt += $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - while ( $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/s ) { - $prematch=$`; - $postmatch=$'; - checkpure($1); - if ( $prematch =~ /\w$/s && $postmatch =~ /^\w/ ) { - # apparently no white-space between word=>Insert white space - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/ /s ; - } - elsif ( $prematch =~ /\s$/s && $postmatch =~ /^[.,;:]/ ) { - # space immediately before one of ".,:;" => remove this space - $body =~ s/\s${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s ; - } - else { - # do not insert or remove any extras - $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//s; - } - } -# Alternative without special cases treatment -# @matches= $body =~ m/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}/sg; -# checkpure(@matches); -# $body =~ s/${ADDMARKOPEN}(.*?)${ADDMARKCLOSE}//sg; - # remove markup of deleted comments - $body =~ s/%${DELCOMMENT}(.*?)$/%$1/mg ; - # remove added comments (full line) - $body =~ s/^%${ADDCOMMENT}.*?\n//mg ; - # remove added comments (part of line) - $body =~ s/%${ADDCOMMENT}.*?$//mg ; -} - -# remove any remaining tokens -if ( $accept || $decline || $simplify ) { - # first substitution command deals with special case of added paragraph - $cnt = $body =~ s/${ADDOPEN}($pat4)\n${ADDCLOSE}\n/$1\n/sg; - $cnt += $body =~ s/${ADDOPEN}($pat4)${ADDCLOSE}/$1/sg; - $cnt==0 || warn 'Remaining $ADDOPEN tokens in DECLINE mode\n' unless ( $quiet || $accept || $simplify ); -} -if ($accept || $simplify ) { - # Note: in decline mode these commands have already been removed above - $cnt = $body =~ s/${DELOPEN}($pat4)${DELCLOSE}/$1/sg; - #### remove markup of deleted commands - $cnt += $body =~ s/${DELCMDOPEN}(.*?)${DELCMDCLOSE}/$1/sg ; - $cnt += $body =~ s/${DELCMDOPEN}//g ; - # remove aux commands - # $cnt += - $body =~ s/^.*${AUXCMD}$/${someword}/mg; $body =~ s/${someword}\n//g; - - #### remove deleted comments - ###$cnt += $body =~ s/${DIFDELCMD}.*?$//mg ; - $cnt==0 || warn 'Remaining $DELOPEN or $DIFDELCMD tokens in ACCEPT mode\n' unless ( $quiet || $simplify ); -} - -# Remove comment commands -if (defined($comment)) { - print STDERR "Removing \\$comment\{..\} sequences ..." if $verbose; - # protect $comments in comments by making them look different - $body =~ s/(%.*)${comment}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${comment}(?:\[${brat0}\])?\{${pat4}\}//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${comment}$2/mg ; -} -if (defined($comenv)) { - print STDERR "Removing $comenv environments ..." if $verbose; - $body =~ s/(%.*)${comenv}/$1${someword}/mg ; -## $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{\$comenv\}.*?\\end\{\$comenv\}//sg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${comenv}\}.*?\\end\{${comenv}\}\s*?\n//sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${comenv}/mg ; -} - -if (defined($markup)) { - print STDERR "Removing \\$markup\{..\} cpmmands ..." if $verbose; - # protect $markups in comments by making them look different - $body =~ s/(%.*)${markup}(.*)$/$1${someword}$2/mg ; - # carry out the substitution - $cnt = 0 + $body =~ s/\\${markup}(?:\[${brat0}\])?\{(${pat4})\}/$1/sg ; - print STDERR "$cnt matches found and removed.\n" if $verbose; - # and undo the protection substitution - $body =~ s/(%.*)${someword}(.*)$/$1${markup}$2/mg ; -} -if (defined($markenv)) { - print STDERR "Removing $markenv environments ..." if $verbose; - $body =~ s/(%.*)${markenv}/$1${someword}/mg ; - $cnt = 0 + $body =~ s/\\begin(?:\[${brat0}\])?\{${markenv}\}\n?//sg; - $cnt += 0 + $body =~ s/\\end\{${markenv}\}\n?//sg; - print STDERR $cnt/2, " matches found and removed.\n" if $verbose; - $body =~ s/(%.*)${someword}/$1${markenv}/mg ; -} - - -if ( length $preamble ) { - print "$preamble\\begin{document}${body}\\end{document}$post"; -} else { - print $body; -} - -# checkpure(@matches) -# checks whether any of the strings in matches contains -# $ADDMARKOPEN, $ADDMARKCLOSE,$DELMARKOPEN, or $DELMARKCLOSE -# If so, die reporting nesting problems, otherwise return to caller -sub checkpure { - while (defined($_=shift)) { - if ( /$ADDMARKOPEN/ || /$ADDMARKCLOSE/ - || /$DELMARKOPEN/ || /$DELMARKCLOSE/ ) { - die <=0 && $j>$i ) { - $part1 = substr($text,0,$i) ; - $part2 = substr($text,$i+$l1,$j-$i-$l1); - $part3 = substr($text,$j+$l2) unless $j+$l2 >= length $text; - } else { - die "$word1 or $word2 not in the correct order or not present as a pair." - } - return ($part1,$part2,$part3); -} - - - -sub usage { - die <<"EOF"; -Usage: $0 [OPTIONS] [diff.tex] > revised.tex - -Read a file diff.tex (output of latexdiff), and remove its markup. -If no filename is given read from standard input. The command can be used -in ACCEPT, DECLINE, or SIMPLIFY mode, and be used to remove user-defined -latex commands from the input (see options -c, -e, -m, -n below). -In ACCEPT mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In DECLINE mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that latexrevise only pays attention to the \\DIFaddbegin, -\\DIFaddend, \\DIFdelbegin, and \\DIFdelend tokens and corresponding FL -varieties. All \\DIFadd and \\DIFdel commands (but not their content) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In SIMPLIFY mode all latexdiff markup is removed from the body of the text (after -\\begin{document}) except for \\DIFaddbegin, \\DIFaddend, \\DIFdelbegin, \\DIFdelend -tokens and the corresponding FL varieties of those commands. The result -will not in general be valid latex-code but might be easier to read and edit in -preparation for a subsequent run in ACCEPT or DECLINE mode. -In SIMPLIFY mode the preamble is left unmodified. - --a ---accept Run in ACCEPT mode (delete all blocks marked by \\DIFdelbegin - and \\DIFdelend). - --d ---decline Run in DECLINE mode (delete all blocks marked by \\DIFaddbegin - and \\DIFaddend). - --s ---simplify Run in SIMPLIFY mode (Keep all \\DIFaddbegin, \\DIFaddend, - \\DIFdelbegin, \\DIFdelend tokens, but remove all other latexdiff - markup from body. - -Note that the three mode options are mutually exclusive. If no mode option is given, -latexrevise simply removes user annotations and markup according to the following four -options. - - --c cmd ---comment=cmd Remove \\cmd{...}. cmd is supposed to mark some explicit - anotations which should be removed from the file before - release. - --e envir ---comment-environment=envir - Remove explicit annotation environments from the text, i.e. remove - \\begin{envir} - ... - \\end{envir} - blocks. - --m cmd ---markup=cmd Remove the markup command cmd but leave its argument, i.e. - turn \\cmd{abc} into abc. - --n envir ---markup-environment=envir - Similarly, remove \\begin{envir} and \\end{envir} commands, - but leave content of the environment in the text. - --q ---no-warnings Do not warn users about \\DIDadd{..} or \\DIFdel statements - which should not be there anymore - --V ---verbose Verbose output - -EOF -} - -=head1 NAME - -latexrevise - selectively remove markup and text from latexdiff output - -=head1 SYNOPSIS - -B [ B ] [ F ] > F - -=head1 DESCRIPTION - -I reads a file C (output of I), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in I, I, or I mode, or can be used to remove user-defined -latex commands from the input (see B<-c>, B<-e>, B<-m>, and B<-n> below). -In I mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In I mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that I only pays attention to the C<\DIFaddbegin>, -C<\DIFaddend>, C<\DIFdelbegin>, and C<\DIFdelend> tokens and corresponding FL -varieties. All C<\DIFadd> and C<\DIFdel> commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In I mode, C<\DIFaddbegin, \DIFaddend, \DIFdelbegin, \DIFdelend> -tokens and their corresponding C varieties are kept but all other markup (e.g. C and <\DIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in I or I mode. -In I mode the preamble is left unmodified. - -=head1 OPTIONS - -=over 4 - -=item B<-a> or B<--accept> - -Run in I mode (delete all blocks marked by C<\DIFdelbegin> and C<\DIFdelend>). - -=item B<-d> or B<--decline> - -Run in I mode (delete all blocks marked by C<\DIFaddbegin> -and C<\DIFaddend>). - -=item B<-s> or B<--simplify> - -Run in I mode (Keep all C<\DIFaddbegin>, C<\DIFaddend>, -C<\DIFdelbegin>, C<\DIFdelend> tokens, but remove all other latexdiff -markup from body). - -=back - -Note that the three mode options are mutually exclusive. If no mode option is given, -I simply removes user annotations and markup according to the following four -options. - -=over 4 - -=item B<-c cmd> or B<--comment=cmd> - -Remove C<\cmd{...}> sequences. C is supposed to mark some explicit -anotations which should be removed from the file before -release. - -=item B<-e envir> or B<--comment-environment=envir> - -Remove explicit annotation environments from the text, i.e. remove - - \begin{envir} - ... - \end{envir} - -blocks. - -=item B<-m cmd> or B<--markup=cmd> - -Remove the markup command C<\cmd> but leave its argument, i.e. -turn C<\cmd{abc}> into C. - -=item B<-n envir> or B<--markup-environment=envir> - -Similarly, remove C<\begin{envir}> and C<\end{envir}> commands but -leave content of the environment in the text. - - -=item B<-V> or B<--verbose> - -Verbose output - -=item B<-q> or B<--no-warnings> - -Do not warn users about C<\DIDadd{..}> or C<\DIFdel{..}> statements -which should have been removed already. - -=back - -=head1 BUGS - -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports using the issue tracker of the github repository page I, -or send them to I.. Include the serial number of I -(Option --version). If you come across latexdiff -output which is not processed correctly by I please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. - -Note that I gets confused by commented C<\begin{document}> or -C<\end{document}> statements - -=head1 SEE ALSO - -L - -=head1 PORTABILITY - -I does not make use of external commands and thus should run -on any platform supporting PERL v5 or higher. - -=head1 AUTHOR - -Copyright (C) 2004 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 - -=cut diff --git a/latexdiff-1.0.4/latexrevise.1 b/latexdiff-1.0.4/latexrevise.1 deleted file mode 100644 index b39017e..0000000 --- a/latexdiff-1.0.4/latexrevise.1 +++ /dev/null @@ -1,243 +0,0 @@ -.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -. ds C` -. ds C' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.\" -.\" Avoid warning from groff about undefined register 'F'. -.de IX -.. -.nr rF 0 -.if \n(.g .if rF .nr rF 1 -.if (\n(rF:(\n(.g==0)) \{ -. if \nF \{ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. if !\nF==2 \{ -. nr % 0 -. nr F 2 -. \} -. \} -.\} -.rr rF -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "LATEXREVISE 1" -.TH LATEXREVISE 1 "2014-07-20" "perl v5.18.2" " " -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.if n .ad l -.nh -.SH "NAME" -latexrevise \- selectively remove markup and text from latexdiff output -.SH "SYNOPSIS" -.IX Header "SYNOPSIS" -\&\fBlatexrevise\fR [ \fB\s-1OPTIONS\s0\fR ] [ \fIdiff.tex\fR ] > \fIrevised.tex\fR -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -\&\fIlatexrevise\fR reads a file \f(CW\*(C`diff.tex\*(C'\fR (output of \fIlatexdiff\fR), and remove the markup commands. -If no filename is given the input is read from standard input. The command can be used -in \fI\s-1ACCEPT\s0\fR, \fI\s-1DECLINE\s0\fR, or \fI\s-1SIMPLIFY\s0\fR mode, or can be used to remove user-defined -latex commands from the input (see \fB\-c\fR, \fB\-e\fR, \fB\-m\fR, and \fB\-n\fR below). -In \fI\s-1ACCEPT\s0\fR mode, all appended text fragments (or preamble lines) -are kept, and all discarded text fragments (or preamble lines) are -deleted. -In \fI\s-1DECLINE\s0\fR mode, all discarded text fragments are kept, and all appended -text fragments are deleted. -If you wish to keep some changes, edit the diff.tex file in -advance, and manually remove those tokens which would otherwise be -deleted. Note that \fIlatexrevise\fR only pays attention to the \f(CW\*(C`\eDIFaddbegin\*(C'\fR, -\&\f(CW\*(C`\eDIFaddend\*(C'\fR, \f(CW\*(C`\eDIFdelbegin\*(C'\fR, and \f(CW\*(C`\eDIFdelend\*(C'\fR tokens and corresponding \s-1FL\s0 -varieties. All \f(CW\*(C`\eDIFadd\*(C'\fR and \f(CW\*(C`\eDIFdel\*(C'\fR commands (but not their contents) are -simply deleted. The commands added by latexdiff to the preamble are also -removed. -In \fI\s-1SIMPLIFY\s0\fR mode, \f(CW\*(C`\eDIFaddbegin, \eDIFaddend, \eDIFdelbegin, \eDIFdelend\*(C'\fR -tokens and their corresponding \f(CW\*(C`FL\*(C'\fR varieties are kept but all other markup (e.g. \f(CW\*(C`DIFadd\*(C'\fR and <\eDIFdel>) is removed. The result -will not in general be valid latex-code but it will be easier to read and edit in -preparation for a subsequent run in \fI\s-1ACCEPT\s0\fR or \fI\s-1DECLINE\s0\fR mode. -In \fI\s-1SIMPLIFY\s0\fR mode the preamble is left unmodified. -.SH "OPTIONS" -.IX Header "OPTIONS" -.IP "\fB\-a\fR or \fB\-\-accept\fR" 4 -.IX Item "-a or --accept" -Run in \fI\s-1ACCEPT\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFdelbegin\*(C'\fR and \f(CW\*(C`\eDIFdelend\*(C'\fR). -.IP "\fB\-d\fR or \fB\-\-decline\fR" 4 -.IX Item "-d or --decline" -Run in \fI\s-1DECLINE\s0\fR mode (delete all blocks marked by \f(CW\*(C`\eDIFaddbegin\*(C'\fR -and \f(CW\*(C`\eDIFaddend\*(C'\fR). -.IP "\fB\-s\fR or \fB\-\-simplify\fR" 4 -.IX Item "-s or --simplify" -Run in \fI\s-1SIMPLIFY\s0\fR mode (Keep all \f(CW\*(C`\eDIFaddbegin\*(C'\fR, \f(CW\*(C`\eDIFaddend\*(C'\fR, -\&\f(CW\*(C`\eDIFdelbegin\*(C'\fR, \f(CW\*(C`\eDIFdelend\*(C'\fR tokens, but remove all other latexdiff -markup from body). -.PP -Note that the three mode options are mutually exclusive. If no mode option is given, -\&\fIlatexrevise\fR simply removes user annotations and markup according to the following four -options. -.IP "\fB\-c cmd\fR or \fB\-\-comment=cmd\fR" 4 -.IX Item "-c cmd or --comment=cmd" -Remove \f(CW\*(C`\ecmd{...}\*(C'\fR sequences. \f(CW\*(C`cmd\*(C'\fR is supposed to mark some explicit -anotations which should be removed from the file before -release. -.IP "\fB\-e envir\fR or \fB\-\-comment\-environment=envir\fR" 4 -.IX Item "-e envir or --comment-environment=envir" -Remove explicit annotation environments from the text, i.e. remove -.Sp -.Vb 3 -\& \ebegin{envir} -\& ... -\& \eend{envir} -.Ve -.Sp -blocks. -.IP "\fB\-m cmd\fR or \fB\-\-markup=cmd\fR" 4 -.IX Item "-m cmd or --markup=cmd" -Remove the markup command \f(CW\*(C`\ecmd\*(C'\fR but leave its argument, i.e. -turn \f(CW\*(C`\ecmd{abc}\*(C'\fR into \f(CW\*(C`abc\*(C'\fR. -.IP "\fB\-n envir\fR or \fB\-\-markup\-environment=envir\fR" 4 -.IX Item "-n envir or --markup-environment=envir" -Similarly, remove \f(CW\*(C`\ebegin{envir}\*(C'\fR and \f(CW\*(C`\eend{envir}\*(C'\fR commands but -leave content of the environment in the text. -.IP "\fB\-V\fR or \fB\-\-verbose\fR" 4 -.IX Item "-V or --verbose" -Verbose output -.IP "\fB\-q\fR or \fB\-\-no\-warnings\fR" 4 -.IX Item "-q or --no-warnings" -Do not warn users about \f(CW\*(C`\eDIDadd{..}\*(C'\fR or \f(CW\*(C`\eDIFdel{..}\*(C'\fR statements -which should have been removed already. -.SH "BUGS" -.IX Header "BUGS" -The current version is a beta version which has not yet been -extensively tested, but worked fine locally. Please submit bug reports using the issue tracker of the github repository page \fIhttps://github.com/ftilmann/latexdiff.git\fR, -or send them to \fItilmann@gfz\-potsdam.de\fR.. Include the serial number of \fIlatexrevise\fR -(Option \-\-version). If you come across latexdiff -output which is not processed correctly by \fIlatexrevise\fR please include the -problem file as well as the old and new files on which it is based, -ideally edited to only contain the offending passage as long as that still -reproduces the problem. -.PP -Note that \fIlatexrevise\fR gets confused by commented \f(CW\*(C`\ebegin{document}\*(C'\fR or -\&\f(CW\*(C`\eend{document}\*(C'\fR statements -.SH "SEE ALSO" -.IX Header "SEE ALSO" -latexdiff -.SH "PORTABILITY" -.IX Header "PORTABILITY" -\&\fIlatexrevise\fR does not make use of external commands and thus should run -on any platform supporting \s-1PERL\s0 v5 or higher. -.SH "AUTHOR" -.IX Header "AUTHOR" -Copyright (C) 2004 Frederik Tilmann -.PP -This program is free software; you can redistribute it and/or modify -it under the terms of the \s-1GNU\s0 General Public License Version 3 diff --git a/latexdiff-1.1.0/COPYING b/latexdiff-1.1.0/COPYING deleted file mode 100644 index d6fa915..0000000 --- a/latexdiff-1.1.0/COPYING +++ /dev/null @@ -1,623 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - diff --git a/latexdiff-1.1.0/Makefile b/latexdiff-1.1.0/Makefile deleted file mode 100644 index 148ead2..0000000 --- a/latexdiff-1.1.0/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# Modify these paths to the requirements of your own system -# For the current setting you will need root permission but -# it is perfectly acceptable to choose user directories -# -INSTALLPATH = /usr/local -INSTALLMANPATH = $(INSTALLPATH)/man -INSTALLEXECPATH = $(INSTALLPATH)/bin - -default: - @echo "To install stand-alone version type: make install" - @echo " (Note the standard version requires prior installation" - @echo " of the PERL package Algorithm::Diff available from " - @echo " the PERL archive www.cpan.org)" - @echo " " - @echo "To install fast version (using UNIX diff) type: make install fast " - @echo " " - @echo "To install the version which uses the system Algorithm::Diff package type: make install-ext" - @echo " " - -install: install-so - -install-ext: install-latexdiff install-latexrevise install-latexdiff-vc install-man - -install-so: install-latexdiff-so install-latexrevise install-latexdiff-vc install-man - -install-fast: install-latexdiff-fast install-latexrevise install-latexdiff-vc install-man - -install-man: - install latexrevise.1 latexdiff.1 latexdiff-vc.1 $(INSTALLMANPATH)/man1 - -install-latexdiff: - install latexdiff $(INSTALLEXECPATH) - -install-latexdiff-so: - if [ -e $(INSTALLEXECPATH)/latexdiff ]; then rm $(INSTALLEXECPATH)/latexdiff; fi - install latexdiff-so $(INSTALLEXECPATH) - cd $(INSTALLEXECPATH); ln -s latexdiff-so latexdiff - -install-latexdiff-fast: - if [ -e $(INSTALLEXECPATH)/latexdiff ]; then rm $(INSTALLEXECPATH)/latexdiff; fi - install latexdiff-fast $(INSTALLEXECPATH) - cd $(INSTALLEXECPATH); ln -s latexdiff-fast latexdiff - -install-latexrevise: - install latexrevise $(INSTALLEXECPATH) - -install-latexdiff-vc: - install latexdiff-vc $(INSTALLEXECPATH) - 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)" - ./latexdiff -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" - -test-so: - @echo "latexdiff example/example-draft.tex example/example-rev.tex (stand-alone version)" - ./latexdiff-so -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" - -test-fast: - @echo "latexdiff example/example-draft.tex example/example-rev.tex (stand-alone version)" - ./latexdiff-fast -V example/example-draft.tex example/example-rev.tex > example/example-diff.tex - @echo "Difference file created: example/example-diff.tex" diff --git a/latexdiff-1.1.0/README b/latexdiff-1.1.0/README deleted file mode 100644 index 911b585..0000000 --- a/latexdiff-1.1.0/README +++ /dev/null @@ -1,108 +0,0 @@ -INTRODUCTION - -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -A rudimentary revision facilility is provided by another Perl script, -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. - -Project webpage: https://github.com/ftilmann/latexdiff/ -CTAN page: http://www.ctan.org/pkg/latexdiff - - -REQUIREMENTS - -Perl 5.8 or higher must be installed. - The latexdiff script makes use of the Perl package Algorithm::Diff (available -from www.cpan.org, current version 1.19). You can either install this package, or -use the standalone version of latexdiff, latexdiff-so, which has version 1.15 of -this package inlined and does not require external installation of -the package. Because latexdiff uses internal functions of Algorithm:Diff whose -calling format or availability can change without notice, the preferred method is -now to use the standalone version. - -As an alternative, latexdiff-fast has a modified version of Algorithm::Diff inlined, -which internally uses the UNIX diff command. This version is much faster but is dependent -on an external "diff" command. Subtle differences in the algorithm of Algorithm::Diff and -UNIX-diff mean that the resulting set of differences will generally not be the same as -for the standard latexdiff. In most practical cases, these differences are minor, though. - -INSTALLATION UNIX/LINUX - -The basic installation procedure is almost trivial: - -1. Copy latexdiff, latexrevise and latexdiff-vc into a directory which - is in the search path and make them executable. If the Algorithm::Diff - package is not installed, use latexdiff-so instead of latexdiff. - -2. Copy latexdiff.1 and latexrevise.1 into the correct man directory - -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 - - make install (for the stand alone version) -or - make install-ext (for the version using the external Algorithm::Diff) -or - make install-fast (for the version using the UNIX 'diff' function for fast differencing) - -to get it rolling. You can type - - make test -or - make test-ext -or - make test-fast - -to test the respective versions on a brief example before installation. It will often be -as easy to carry out these steps manually instead of using the Makefile. - - -DOCUMENTATION: - -Usage instructions are in the manual latexdiff-man.pdf as well as the -man pages. - -CHANGELOGS: - -Check out the comment lines at the beginning of the perl scripts (latexdiff, latexdiff-vc, latexrevise) - -CONTRIBUTIONS - -The directory contrib contains code written by others relating to latexdiff. -Currently this directory contains: - -latexdiff-wrap (Author: V. Kuhlmann) An alternative wrapper script which can be used - instead of latexdiff-vc. Its main use is as a template for customised wrapper scripts. - -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) - -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) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License Version 3 as published by -the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details (file LICENSE in the -distribution). - diff --git a/latexdiff-1.1.0/contrib/README.latexchanges b/latexdiff-1.1.0/contrib/README.latexchanges deleted file mode 100644 index 4a02765..0000000 --- a/latexdiff-1.1.0/contrib/README.latexchanges +++ /dev/null @@ -1,13 +0,0 @@ -latexchanges.py (Jan-Ake Larsson): -Here's a wrapper I wrote for latexdiff, intended as a drop-in -replacement for latex, when you have several numbered (or dated) -versions of a manuscript. My coauthors don't as a rule know what CVS or -SVN is, they simply use a number or date for the different versions. - -latexchanges replaces the current DVI with one that includes a -latexdiff to the last version. The last version is selected as the -TEX file in the same directory with the same prefix (up to a number -or a dot), that has an mtime immediately preceding the given TEX -file. - - diff --git a/latexdiff-1.1.0/contrib/latexchanges.py b/latexdiff-1.1.0/contrib/latexchanges.py deleted file mode 100644 index de7acbe..0000000 --- a/latexdiff-1.1.0/contrib/latexchanges.py +++ /dev/null @@ -1,67 +0,0 @@ -#! /bin/env python -# latexchanges -# -# Wrapper for latexdiff, intended as a drop-in replacement for latex, -# when you have several numbered (or dated) versions of a manuscript. -# My coauthors don't as a rule know what CVS or SVN is, they simply -# use a number or date for the different versions. -# -# latexchanges replaces the current DVI with one that includes a -# latexdiff to the last version. The last version is selected as the -# TEX file in the same directory with the same prefix (up to a number -# or a dot), that has an mtime immediately preceding the given TEX -# file. -# -# (I should probably add CVS version numbering too, at some point.) -# -# Copyright (C) 2009 by Jan-\AA{}ke Larsson -# Released under the terms of the GNU General Public License (GPL) -# Version 2. See http://www.gnu.org/ for details. -# -# Please do provide patches and bug reports, but remember: if it -# breaks, you get to keep the pieces. -# -# Jan-\AA{}ke Larsson -# Sept 16 2009 - -from os import listdir,system,stat -from sys import argv -from re import split - -name="" -newarg=[] - -# Find filename argument -for i in range(1,len(argv)): - if argv[i][-4:]==".tex": - basename=split('[0-9.]',argv[i])[0] - name=argv[i][:-4] - newarg.append(name+".changes.tex") - else: - newarg.append(argv[i]) - -if name: - print "Filename",name+".tex" - print "Prefix is",basename - # Find last archived version - mtime=stat(name+".tex").st_mtime - old_mtime=0 - ls=listdir(".") - for j in ls: - if j.startswith(basename) and j.endswith(".tex")\ - and not j.endswith(".changes.tex"): - tmptime=stat(j).st_mtime - if mtime>tmptime and old_mtime0: - print "Comparing with",oldname - system ("/bin/cp "+name+".aux "+name+".changes.aux") - system ("/bin/cp "+name+".bbl "+name+".changes.bbl") - system ("latexdiff "+oldname+" "+name+".tex > "+name+".changes.tex") - system ("latex "+" ".join(newarg)) - system ("cp "+name+".changes.dvi "+name+".dvi") - else: - system ("latex "+" ".join(argv[1:])) diff --git a/latexdiff-1.1.0/contrib/latexdiff-wrap b/latexdiff-1.1.0/contrib/latexdiff-wrap deleted file mode 100755 index 894b424..0000000 --- a/latexdiff-1.1.0/contrib/latexdiff-wrap +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/bash -# -# latexdiff-wrap -# -# Wrapper for latexdiff, to -# * provide support for documents consiting of more than 1 latex file -# * provide my common arguments -# -# Copyright (C) by Volker Kuhlmann -# Released under the terms of the GNU General Public License (GPL) Version 2. -# See http://www.gnu.org/ for details. -# -# Volker Kuhlmann -# 5, 6, 7, 12, 16, 17 Oct 2005 -# 31 Jan; 5, 7, 13, 15 Feb 2006 -# - -VERSION="0.6, 15 Feb 2006" -AUTHOR="Volker Kuhlmann " -COPYRIGHT="Copyright (C) 2005-2006" - - -#### -#### Constants and initialised variables -# -diffcmd="latexdiff" -diffrc="$HOME/texmf/latexdiff" -#diffargs="-e latin1 --ignore-warnings -p latexdiff-preamble.sty" -diffargs="-e latin1 --ignore-warnings" -diffargs="$diffargs --append-safecmd $diffrc/safe-cmds" -diffargs="$diffargs --append-textcmd $diffrc/text-cmds" -# Note: Can't use multiple --append-safecmd -# show current command lists: -#diffcmd="$diffcmd --show-safecmd --show-textcmd --show-config" - - -#### -#### Version, Usage, Help -# -show_version() { - echo "${0##*/} version $VERSION -$COPYRIGHT by $AUTHOR" -} - -show_usage() { - echo " -Usage: ${0##*/} OLDDIR NEWDIR DIFFDIR [DIFFARGS --] FILE.tex [...] - ${0##*/} --show [DIFFARGS] -Version $VERSION -$COPYRIGHT by $AUTHOR -" -} - -show_help() { - show_usage - echo "\ -For each FILE.tex, build a new file DIFFDIR/FILE.tex with markup of the changes -which were made from OLDDIR/FILE.tex to NEWDIR/FILE.tex. -Any path given with FILE.tex is stripped off. -Any DIFFARGS are added to the latexdiff call, if present (remember to follow -them with a double-hyphen on its own before the FILE arguments). - -With --show, shows the settings latexdiff would be running with, including the -changes applied by the user. -" -} - -# For scripts not using function library only: -Version() { show_version; exitwith ErrVersion; } -Usage() { show_help; exitwith ErrUsage; } -Help() { test "$1" && exitwith ErrHelp show_help; show_help; exitwith ErrOK; } - - -#### -#### Error/Exit codes -# -exitwith() { - exec 1>&2 # write stdout on stderr instead - case "$1" in - ErrOK) - exit 0;; - ErrVersion|ErrUsage|ErrHelp) - # Output generated by function (program) $2, if given - test -n "$2" && "$2" - exit 1;; - # more codes in here - # more codes in here - ErrBadoption) - echo "Bad option '$2'." - echo "Call with -h for help." - exit 9;; - ErrMissingParameter) - echo "A required parameter for option $2 is missing." - echo "Call with -h for help." - exit 9;; - *) - echo "Internal error: exitwith() called with illegal error code '$1'." - exit 19;; - esac -} - - -#### -#### Parse command line parameters -# - -# If the next arg starts with a "-", collect additional argument for latexdiff -# until "--". -scanextraargs() { - addargs=() - case "$1" in -*) - while [ $# -gt 0 -a "$1" != "--" ]; do - addargs=( "${addargs[@]}" "$1" ) - shift - done - test "$1" == "--" && shift - ;; esac - fileargs=( "$@" ) -} - -case "$1" in - --version) Version;; - --usage) Usage;; - --help|-h|-help) Help;; - --show) - shift - scanextraargs "$@" - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - --show-safecmd --show-textcmd --show-config - ) | fmt - exit $? ;; -esac - -olddir="${1%/}" -newdir="${2%/}" -diffdir="${3%/}" - -if ! [ -d "$olddir" -a -d "$newdir" -a -d "$diffdir" ]; then - Help 1>&2 err -fi - -shift 3 - -scanextraargs "$@" -set -- "${fileargs[@]}" - - - -#### -#### Functions -# -#set -x -Log() { echo 1>&2 "+ $@"; "$@"; } - - -#### -#### Main -# - -# Create output directory, just in case. -(set -x -mkdir -p "$diffdir" -) -while [ $# -gt 0 ]; do - file="${1##*/}" - echo Examining: "$file" - # No point running latexdiff if both files are identical, - # but run latexdiff on top-level LaTeX file in any case. - if cmp --quiet "$olddir/$file" "$newdir/$file" \ - && ! grep -lq '\\begin.*{document}' "$newdir/$file"; then - (set -x - cp -p "$olddir/$file" "$diffdir" - ) - else - # Delete file, to make sure it's not clobbered by redirecting stdout - # in case it's a symlink to te original. - test -f "$diffdir/$file" && (set -x - rm "$diffdir/$file" - ) - # Run latexdiff if both input files are present. - run=1 - test -f "$olddir/$file" || { echo 1>&2 "No file: $olddir/$file"; run=; } - test -f "$newdir/$file" || { echo 1>&2 "No file: $newdir/$file"; run=; } - test -n "$run" && \ - (set -x - $diffcmd $diffargs "${addargs[@]}" \ - "$olddir/$file" "$newdir/$file" > "$diffdir/$file" - ) - fi - shift -done diff --git a/latexdiff-1.1.0/contrib/latexdiff.spec b/latexdiff-1.1.0/contrib/latexdiff.spec deleted file mode 100644 index 9255a69..0000000 --- a/latexdiff-1.1.0/contrib/latexdiff.spec +++ /dev/null @@ -1,58 +0,0 @@ -Summary: Diff for LaTeX files -Name: latexdiff -Version: 0.5 -Release: 1 -License: GPL -Group: Productivity/Publishing/TeX/Utilities -URL: http://www.tug.org/tex-archive/help/Catalogue/entries/latexdiff.html -Source0: %{name}.zip -BuildArch: noarch -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -# only required for 'make install-ext' -# Requires: perl-Algorithm-Diff - - -%description -latexdiff is a Perl script, which compares two latex files and marks -up significant differences between them (i.e. a diff for latex files). - Various options are available for visual markup using standard latex -packages such as "color.sty". Changes not directly affecting visible -text, for example in formatting commands, are still marked in -the latex source. - -(C) 2004 Frederik Tilmann - - -%prep -%setup -n %{name} - - -%build -# quick had to adapt the Makefile -%{__mv} Makefile Makefile.old -%{__sed} \ - -e "s;INSTALLPATH = /usr/local;INSTALLPATH = \${DESTDIR}%{_prefix};" \ - -e "s;INSTALLMANPATH = \$(INSTALLPATH)/man;INSTALLMANPATH = \${DESTDIR}%{_mandir};" \ - Makefile.old > Makefile - - -%install -%{__mkdir_p} $RPM_BUILD_ROOT%{_bindir} -%{__mkdir_p} $RPM_BUILD_ROOT%{_mandir}/man1 - -%makeinstall - - -%clean -[ "${RPM_BUILD_ROOT}" != "/" ] && [ -d "${RPM_BUILD_ROOT}" ] && %{__rm} -rf "${RPM_BUILD_ROOT}" - - -%files -%defattr(-,root,root) -%doc example CHANGES LICENSE README -%{_bindir}/* -%{_mandir}/man*/* - -%changelog -* Thu Jan 4 2007 Till Dörges - 0.5-1 -- Initial build. diff --git a/latexdiff-1.1.0/doc/latexdiff-man.pdf b/latexdiff-1.1.0/doc/latexdiff-man.pdf deleted file mode 100644 index cb909a5..0000000 Binary files a/latexdiff-1.1.0/doc/latexdiff-man.pdf and /dev/null differ diff --git a/latexdiff-1.1.0/doc/latexdiff-man.tex b/latexdiff-1.1.0/doc/latexdiff-man.tex deleted file mode 100644 index 2adffcc..0000000 --- a/latexdiff-1.1.0/doc/latexdiff-man.tex +++ /dev/null @@ -1,355 +0,0 @@ -\documentclass[a4]{article} -\usepackage{graphicx} -%\def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -%\def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -\setlength{\parindent}{0pt} -%\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}} -\date{\today} - -\begin{document} -\maketitle - -\section*{Preamble} - -{\em latexdiff} is a Perl script, which compares two -latex files and marks up significant differences between them. Various options are available for visual markup using standard -latex packages such as {\em color.sty}. Changes not directly affecting visible -text, for example in formatting commands, are still marked in the -latex source. - -A rudimentary revision facilility is provided by another Perl script, -{\em 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. - -There is no explicit support for annotations as these are trivial to implement. -For example, I include the following command definition in the preamble -\begin{verbatim} -\newcommand{\remark}[1]{{ \bf [ \footnotesize #1 ]}} -\end{verbatim} -and mark up annotations as follows -\begin{verbatim} -... The roadrunner is the fastest running bird \remark{Check this -again with a zoologist!}. The most famous roadrunner ... -\end{verbatim} -Alternatively, instead of a command like \verb#\remark# in the example just given, an -equivalent annotation environment could be defined. -{\em latexrevise} can remove such comments or -environments from the text body. - -%It is planned that the revision capabilities of this system will be -%further expanded, dependent on the amount of feedback received. - -On the following pages you find the {\em man} pages for {\em - latexdiff} and {\em latexrevise} and a simple example. - -\include{latexdiff} -\setcounter{section}{0} - -\include{latexrevise} -\setcounter{section}{0} - -\include{latexdiff-vc} -\setcounter{section}{0} - -\section*{A simple example} - -We start with a draft text, \verb|example-draft.tex|, listed here in -full but also included in the distribution (except that the ``verbatim'' environment had -to be renamed to ``Verbatim'' for the listing). - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. Of course, instead of \verb|xpdf| you can use -\verb|okular, evince, acroread| or any other pdf or postscript viewer. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things -could be said were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} -\end{verbatim} -} - -We can now edit -this text as we would do with any other latex file to create -a new revision of the text, \verb|example-rev.tex|. We should run -\begin{verbatim} -latex example-rev.tex -\end{verbatim} -and look at the resulting \verb|.dvi| file to make sure that all -changes are valid. An example revision is listed here: - -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. -More things could be said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} -\end{verbatim} -} - -To compare both revisions, type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -This results in the following difference file (a few newlines have been -added in this listing for legibility reasosn): -{\scriptsize -\begin{verbatim} -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -%DIF 7c7 -%DIF < \setlength{\textwidth}{6.5in} -%DIF ------- -\setlength{\textwidth}{6in} %DIF > -%DIF ------- - -%DIF 9c9 -%DIF < \title{latexdiff Example - Draft version} -%DIF ------- -\title{latexdiff Example - Revised version} %DIF > -%DIF ------- -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even %DIF > -% if some preamble might eventually end up as visible text.) %DIF > -%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF -%DIF UNDERLINE PREAMBLE %DIF PREAMBLE -\RequirePackage[normalem]{ulem} %DIF PREAMBLE -\RequirePackage{color} %DIF PREAMBLE -\providecommand{\DIFadd}[1]{{\color{blue}\uline{#1}}} %DIF PREAMBLE -\providecommand{\DIFdel}[1]{{\color{red}\sout{#1}}} %DIF PREAMBLE -%DIF SAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddbegin}{} %DIF PREAMBLE -\providecommand{\DIFaddend}{} %DIF PREAMBLE -\providecommand{\DIFdelbegin}{} %DIF PREAMBLE -\providecommand{\DIFdelend}{} %DIF PREAMBLE -%DIF FLOATSAFE PREAMBLE %DIF PREAMBLE -\providecommand{\DIFaddFL}[1]{\DIFadd{#1}} %DIF PREAMBLE -\providecommand{\DIFdelFL}[1]{\DIFdel{#1}} %DIF PREAMBLE -\providecommand{\DIFaddbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFaddendFL}{} %DIF PREAMBLE -\providecommand{\DIFdelbeginFL}{} %DIF PREAMBLE -\providecommand{\DIFdelendFL}{} %DIF PREAMBLE -%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{Verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{Verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{Verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{Verbatim} -or -\begin{Verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{Verbatim} -to display the markup. - -\section*{\DIFaddbegin \DIFadd{Yet another }\DIFaddend \DIFdelbegin -\DIFdel{Another }\DIFdelend section title} - - \DIFdelbegin \DIFdel{A paragraph with a line only in the draft - document. }\DIFdelend More things could - be said were it not for the constraints of time and space. - -\DIFaddbegin \DIFadd{A paragraph with a line only in the revised - document. }\DIFaddend More things could be said -were it not for the constraints of time and space. - -And here is a \DIFaddbegin \DIFadd{typo}\DIFaddend \DIFdelbegin -\DIFdel{tipo}\DIFdelend . - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & \DIFaddbegin \DIFadd{White }\DIFaddend \DIFdelbegin -\DIFdel{Grey }\DIFdelend \\ -Saruman & \DIFaddbegin \DIFadd{Evil -}\DIFaddend \DIFdelbegin \DIFdel{White -}\DIFdelend \end{tabular} - -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -No change, -no markup! -\end{document} -\end{verbatim} -} -Type -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -to make the markup visible. This is what it looks like: - -\vspace{1cm} -\framebox[\textwidth]{\includegraphics[width=\textwidth]{example-diff}} -\vspace{1cm} - -If you approve of all the changes in the revision, just continue with -\verb|example-rev.tex| for the next revision. If you like to adopt -most but not all changes you can use \verb|latexrevise| in the -following manner. Simply remove the \verb|\DIFdelbegin| and -\verb|\DIFdelend| tags around the text you would like to keep and -simply remove the text between \verb|\DIFaddbegin| and -\verb|\DIFaddend| tags, if you do not wish to keep them. Say you are happy with all proposed changes for the -example above except in -the last paragraph where you prefer the original draft. You have -to change - -{\scriptsize -\begin{verbatim} -... -And \DIFaddbegin \DIFadd{now for something completely different, with not - a paragraph in sight}\DIFaddend \DIFdelbegin \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}\DIFdelend . -... -\end{verbatim} -} -into -{\scriptsize -\begin{verbatim} -... -And \DIFdel{sometimes a whole - paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical}. -... -\end{verbatim} -} -and run -\begin{verbatim} -latexrevise -a example-rev.tex > example-final.tex -\end{verbatim} -\verb|example-final.tex| is then almost identical to -\verb|example-rev.tex| except for the last paragraph. -\end{document} diff --git a/latexdiff-1.1.0/example/example-draft.tex b/latexdiff-1.1.0/example/example-draft.tex deleted file mode 100644 index 593a170..0000000 --- a/latexdiff-1.1.0/example/example-draft.tex +++ /dev/null @@ -1,59 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6.5in} - -\title{latexdiff Example - Draft version} -\author{F Tilmann} - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Another section title} - -A paragraph with a line only in the draft document. More things could be said -were it not for the constraints of time and space. - -More things could be said were it not for the constraints of time and space. - -And here is a tipo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & Grey \\ -Saruman & White -\end{tabular} - -And sometimes a whole paragraph gets completely rewritten. In this -case latexdiff marks up the whole paragraph even if some words in it -are identical. -No change, no markup! -\end{document} - - diff --git a/latexdiff-1.1.0/example/example-rev.tex b/latexdiff-1.1.0/example/example-rev.tex deleted file mode 100644 index 4bcaf15..0000000 --- a/latexdiff-1.1.0/example/example-rev.tex +++ /dev/null @@ -1,60 +0,0 @@ -\documentclass[12pt,a4paper]{article} - -\setlength{\topmargin}{-0.2in} -\setlength{\textheight}{9.5in} -\setlength{\oddsidemargin}{0.0in} - -\setlength{\textwidth}{6in} - -\title{latexdiff Example - Revised version} -\author{F Tilmann} -% Note how in the preamble visual markup is never used (even -% if some preamble might eventually end up as visible text.) - -\begin{document} -\maketitle - -\section*{Introduction} - -This is an extremely simple document that showcases some of the latexdiff features. -Type -\begin{verbatim} -latexdiff -t UNDERLINE example-draft.tex example-rev.tex > example-diff.tex -\end{verbatim} -to create the difference file. You can inspect this file directly. Then run either -\begin{verbatim} -pdflatex example-diff.tex -xpdf example-diff.pdf -\end{verbatim} -or -\begin{verbatim} -latex example-diff.tex -dvips -o example-diff.ps example-diff.dvi -gv example-diff.ps -\end{verbatim} -to display the markup. - -\section*{Yet another section title} - - More things could be said were it not for the constraints of time and space. - -A paragraph with a line only in the revised document. More things could be -said were it not for the constraints of time and space. - -And here is a typo. - -Here is a table: - -\begin{tabular}{ll} -Name & Description \\ -\hline -Gandalf & White \\ -Saruman & Evil -\end{tabular} - -And now for something completely different, with not a paragraph in sight. -No change, -no markup! -\end{document} - - diff --git a/latexdiff-1.1.0/latexdiff b/latexdiff-1.1.0/latexdiff deleted file mode 100755 index bb75ce4..0000000 --- a/latexdiff-1.1.0/latexdiff +++ /dev/null @@ -1,3824 +0,0 @@ -#!/usr/bin/env perl -##!/usr/bin/perl -w -# latexdiff - differences two latex files on the word level -# and produces a latex file with the differences marked up. -# -# Copyright (C) 2004-12 F J Tilmann (tilmann@gfz-potsdam.de) -# -# Repository/issue tracker: https://github.com/ftilmann/latexdiff -# CTAN page: http://www.ctan.org/tex-archive/support/latexdiff -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# 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) -# - new subtype LABEL which gives each change a label. This can later be used to only display pages where changes -# have been made (instructions for that are put as comments into the diff'ed file) inspired by answer on http://tex.stackexchange.com/questions/166049/invisible-markers-in-pdfs-using-pdflatex -# - Configuration variables take into accout some commands from additional packages: -# tikzpicture environment now treated as PICTUREENV, and \smallmatrix in ARRENV (amsmath) -# - --flatten: support for \subfile command (subfiles package) (in response to http://tex.stackexchange.com/questions/167620/latexdiff-with-subfiles ) -# - --flatten: \bibliography commands expand if corresponding bbl file present -# - angled bracket optional commands now parsed correctly (patch #3570) submitted by Dave Kleinschmidt (thanks) -# - \RequirePackage now treated as synonym of \usepackage with respect to setting packages -# - special rules for apacite package (redefine citation commands) -# - recognise /dev/null as 'file-like' arguments for --preamble and --config options -# - fix units package incompatibility with ulem for text maths statements $ ..$ (thanks to Stuart Prescott for reporting this) -# - amsmath environment cases treated correctly (Bug fix #19029) (thanks to Jalar) -# - {,} in comments no longer confuse latexdiff (Bug fix #19146) -# - \% in one-letter sub/Superscripts was not converted correctly -# -# Version 1.0.3 -# - fix bug in add_safe_commands that made latexdiff hang on DeclareMathOperator -# command in preamble -# - \(..\) inline math expressions were not parsed correctly, if they contained a linebreak -# - applied patch contributed by tomflannaghan via Berlios: [ Patch #3431 ] Adds correct handling of \left< and \right> -# - \$ is treated correctly as a literal dollar sign (thanks to Reed Cartwright and Joshua Miller for reporting this bug -# and sketching out the solution) -# - \^ and \_ are correctly interpreted as accent and underlined space, respectively, not as superscript of subscript -# (thanks to Wail Yahyaoui for pointing out this bug) -# -# Version 1.0.1 - treat \big,\bigg etc. equivalently to \left and -# \right - include starred version in MATHENV - apply -# - flatten recursively and --flatten expansion is now -# aware of comments (thanks to Tim Connors for patch) -# - Change to post-processing for more reliability for -# deleted math environments -# - On linux systems, recognise and remove DOS style newlines -# - Provide markup for some special preamble commands (\title, -# \author,\date, -# - configurable by setting context2cmd -# - for styles using ulem package, remove \emph and \text.. from list of -# safe commands in order to allow linebreaks within the -# highlighted sections. -# - for ulem style, now show citations by enclosing them in \mbox commands. -# This unfortunately implies linebreaks within citations no longer function, -# so this functionality can be turned off (Option --disable-citation-markup). -# With --enable-citation-markup, the mbox markup is forced for other styles) -# - new substyle COLOR. This is particularly useful for marking up citations -# and some special post-processing is implemented to retain cite -# commands in deleted blocks. -# - four different levels of math-markup -# - Option --driver for choosing driver for modes employing changebar package -# - accept \\* as valid command (and other commands of form \.*). Also accept -# \ (backslashed newline) -# - some typo fixes, include commands defined in preamble as safe commands -# (Sebastian Gouezel) -# - include compared filenames as comments as line 2 and 3 of -# the preamble (can be modified with option --label, and suppressed with -# --no-label), option --visible-label to show files in generated pdf or dvi -# at the beginning of main document -# -# Version 0.5 A number of minor improvements based on feedback -# Deleted blocks are now shown before added blocks -# Package specific processing -# -# Version 0.43 unreleased typo in list of styles at the end -# Add protect to all \cbstart, \cbend commands -# More robust substitution of deleted math commands -# -# Version 0.42 November 06 Bug fixes only -# -# Version 0.4 March 06 option for fast differencing using UNIX diff command, several minor bug fixes (\par bug, improved highlighting of textcmds) -# -# Version 0.3 August 05 improved parsing of displayed math, --allow-spaces -# option, several minor bug fixes -# -# Version 0.25 October 04 Fix bug with deleted equations, add math mode commands to safecmd, add | to allowed interpunctuation signs -# Version 0.2 September 04 extension to utf-8 and variable encodings -# Version 0.1 August 04 First public release - -use Algorithm::Diff qw(traverse_sequences); - -use Getopt::Long ; -use strict ; -use warnings; -use utf8 ; - -my ($algodiffversion)=split(/ /,$Algorithm::Diff::VERSION); - - -my ($versionstring)=< 0, - WHOLE => 1, - COARSE => 2, - FINE => 3 -}; - -my ($mboxcmd); - -my (@configlist,@labels, - @appendsafelist,@excludesafelist, - @appendmboxsafelist,@excludemboxsafelist, - @appendtextlist,@excludetextlist, - @appendcontext1list,@appendcontext2list, - @packagelist); -my ($assign,@config); -# Hash where keys corresponds to the names of all included packages (including the documentclass as another package -# the optional arguments to the package are the values of the hash elements -my ($pkg,%packages); -# Defaults -$mathmarkup=COARSE; - -$verbose=0; -# output debug and intermediate files, set to 0 in final distribution -$debug=0; -# insert preamble directly after documentclass - experimental feature, set to 0 in final distribution -# Note that this failed with mini example (or other files, where packages used in latexdiff preamble -# are called again with incompatible options in preamble of resulting file) -$earlylatexdiffpreamble=0; - -# define character properties -sub IsNonAsciiPunct { return <<'END' # Unicode punctuation but excluding ASCII punctuation -+utf8::IsPunct --utf8::IsASCII -END -} -sub IsNonAsciiS { return <<'END' # Unicode symbol but excluding ASCII -+utf8::IsS --utf8::IsASCII -END -} - - -my %verbhash; - -Getopt::Long::Configure('bundling'); -GetOptions('type|t=s' => \$type, - 'subtype|s=s' => \$subtype, - 'floattype|f=s' => \$floattype, - 'config|c=s' => \@configlist, - 'preamble|p=s' => \$preamblefile, - 'encoding|e=s' => \$encoding, - 'label|L=s' => \@labels, - 'no-label' => \$nolabel, - 'visible-label' => \$visiblelabel, - 'exclude-safecmd|A=s' => \@excludesafelist, - 'replace-safecmd=s' => \$replacesafe, - 'append-safecmd|a=s' => \@appendsafelist, - 'exclude-textcmd|X=s' => \@excludetextlist, - 'replace-textcmd=s' => \$replacetext, - 'append-textcmd|x=s' => \@appendtextlist, - 'replace-context1cmd=s' => \$replacecontext1, - '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, - 'show-config' => \$showconfig, - 'show-all' => \$showall, - 'packages=s' => \@packagelist, - 'allow-spaces' => \$allowspaces, - 'math-markup=s' => \$mathmarkup, - '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, - 'debug!' => \$debug ); - -if ( $help ) { - usage() ; -} - - -if ( $version ) { - die $versionstring ; -} - -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/; - if ( $mathmarkup eq 'OFF' ){ - $mathmarkup=OFF; - } elsif ( $mathmarkup eq 'WHOLE' ){ - $mathmarkup=WHOLE; - } elsif ( $mathmarkup eq 'COARSE' ){ - $mathmarkup=COARSE; - } elsif ( $mathmarkup eq 'FINE' ){ - $mathmarkup=FINE; - } elsif ( $mathmarkup !~ m/^[0123]$/ ) { - die "Illegal value: ($mathmarkup) for option--math-markup. Possible values: OFF,WHOLE,COARSE,FINE,0- "; - } - # else use numerical value -} - -# setting extra preamble commands -if (defined($preamblefile)) { - $latexdiffpreamble=join "\n",(extrapream($preamblefile),""); -} else { - $latexdiffpreamble=join "\n",(extrapream($type,$subtype,$floattype),""); -} - -if ( defined($driver) ) { - # for changebar only - $latexdiffpreamble=~s/\[dvips\]/[$driver]/sg; -} -# setting up @SAFECMDLIST and @SAFECMDEXCL -if (defined($replacesafe)) { - init_regex_arr_ext(\@SAFECMDLIST,$replacesafe); -} else { - init_regex_arr_data(\@SAFECMDLIST, "SAFE COMMANDS"); -} -foreach $appendsafe ( @appendsafelist ) { - init_regex_arr_ext(\@SAFECMDLIST, $appendsafe); -} -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)) { - init_regex_arr_ext(\@TEXTCMDLIST,$replacetext); -} else { - init_regex_arr_data(\@TEXTCMDLIST, "TEXT COMMANDS"); -} -foreach $appendtext ( @appendtextlist ) { - init_regex_arr_ext(\@TEXTCMDLIST, $appendtext); -} -foreach $excludetext ( @excludetextlist ) { - init_regex_arr_ext(\@TEXTCMDEXCL, $excludetext); -} - - -# setting up @CONTEXT1CMDLIST ( @CONTEXT1CMDEXCL exist but is always empty ) -if (defined($replacecontext1)) { - init_regex_arr_ext(\@CONTEXT1CMDLIST,$replacecontext1); -} else { - init_regex_arr_data(\@CONTEXT1CMDLIST, "CONTEXT1 COMMANDS"); -} -foreach $appendcontext1 ( @appendcontext1list ) { - init_regex_arr_ext(\@CONTEXT1CMDLIST, $appendcontext1); -} - - -# setting up @CONTEXT2CMDLIST ( @CONTEXT2CMDEXCL exist but is always empty ) -if (defined($replacecontext2)) { - init_regex_arr_ext(\@CONTEXT2CMDLIST,$replacecontext2); -} else { - init_regex_arr_data(\@CONTEXT2CMDLIST, "CONTEXT2 COMMANDS"); -} -foreach $appendcontext2 ( @appendcontext2list ) { - init_regex_arr_ext(\@CONTEXT2CMDLIST, $appendcontext2); -} - -# setting configuration variables -@config=(); -foreach $config ( @configlist ) { - if (-f $config || lc $config eq '/dev/null' ) { - open(FILE,$config) or die ("Couldn't open configuration file $config: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@config,$_); - } - close(FILE); - } - else { -# foreach ( split(",",$config) ) { -# push @config,$_; -# } - push @config,split(",",$config) - } -} -foreach $assign ( @config ) { - $assign=~ m/\s*(\w*)\s*=\s*(\S*)\s*$/ or die "Illegal assignment $assign in configuration list (must be variable=value)"; - if ( $1 eq "MINWORDSBLOCK" ) { $MINWORDSBLOCK = $2; } - elsif ( $1 eq "FLOATENV" ) { $FLOATENV = $2 ; } - elsif ( $1 eq "PICTUREENV" ) { $PICTUREENV = $2 ; } - elsif ( $1 eq "MATHENV" ) { $MATHENV = $2 ; } - elsif ( $1 eq "MATHREPL" ) { $MATHREPL = $2 ; } - elsif ( $1 eq "MATHARRENV" ) { $MATHARRENV = $2 ; } - elsif ( $1 eq "MATHARRREPL" ) { $MATHARRREPL = $2 ; } - elsif ( $1 eq "ARRENV" ) { $ARRENV = $2 ; } - elsif ( $1 eq "COUNTERCMD" ) { $COUNTERCMD = $2 ; } - else { die "Unknown variable $1 in assignment.";} -} - -if ( $mathmarkup == COARSE || $mathmarkup == WHOLE ) { - push(@MATHTEXTCMDLIST,qr/^MATHBLOCK(?:$MATHENV|$MATHARRENV|SQUAREBRACKET)$/); -} - - - -foreach $pkg ( @packagelist ) { - map { $packages{$_}="" } split(/,/,$pkg) ; -} - -if ($showpreamble) { - print "\nPreamble commands:\n"; - print $latexdiffpreamble ; -} - -if ($showsafe) { - print "\nCommands safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE (unless excluded):\n"; - print_regex_arr(@SAFECMDLIST); - print "\nCommands not safe within scope of $ADDOPEN $ADDCLOSE and $DELOPEN $DELCLOSE :\n"; - print_regex_arr(@SAFECMDEXCL); -} - -if ($showtext) { - print "\nCommands with last argument textual (unless excluded) and safe in every context:\n"; - print_regex_arr(@TEXTCMDLIST); - print "\nContext1 commands (last argument textual, command will be disabled in deleted passages, last argument will be shown as plain text):\n"; - print_regex_arr(@CONTEXT1CMDLIST); - print "\nContext2 commands (last argument textual, command and its argument will be disabled in deleted passages):\n"; - print_regex_arr(@CONTEXT2CMDLIST); - print "\nExclude list of Commands with last argument not textual (overrides patterns above):\n"; - print_regex_arr(@TEXTCMDEXCL); -} - - -if ($showconfig) { - print "Configuration variables:\n"; - print "MINWORDSBLOCK=$MINWORDSBLOCK\n"; - print "FLOATENV=$FLOATENV\n"; - print "PICTUREENV=$PICTUREENV\n"; - print "MATHENV=$MATHENV\n"; - print "MATHREPL=$MATHREPL\n"; - print "MATHARRENV=$MATHARRENV\n"; - print "MATHARRREPL=$MATHARRREPL\n"; - print "ARRENV=$ARRENV\n"; - print "COUNTERCMD=$COUNTERCMD\n"; -} -if ($showconfig || $showtext || $showsafe || $showpreamble) { - exit 0; } -if ( @ARGV != 2 ) { - print STDERR "2 and only 2 non-option arguments required. Write latexdiff -h to get help\n"; - exit(2); -} - -# Are extra spaces between command arguments permissible? -my $extraspace; -if ($allowspaces) { - $extraspace='\s*'; -} else { - $extraspace=''; -} - -# append context lists to text lists (as text property is implied) -push @TEXTCMDLIST, @CONTEXT1CMDLIST; -push @TEXTCMDLIST, @CONTEXT2CMDLIST; - -push @TEXTCMDLIST, @MATHTEXTCMDLIST if $mathmarkup==COARSE; - -# internal additions to SAFECMDLIST -push(@SAFECMDLIST, qr/^QLEFTBRACE$/, qr/^QRIGHTBRACE$/); - - -# Patterns. These are used by some of the subroutines, too -# I can only define them down here because value of extraspace depends on an option - my $pat0 = '(?:[^{}])*'; - my $pat1 = '(?:[^{}]|\{'.$pat0.'\})*'; - my $pat2 = '(?:[^{}]|\{'.$pat1.'\})*'; - my $pat3 = '(?:[^{}]|\{'.$pat2.'\})*'; - my $pat4 = '(?:[^{}]|\{'.$pat3.'\})*'; - my $pat5 = '(?:[^{}]|\{'.$pat4.'\})*'; - my $pat6 = '(?:[^{}]|\{'.$pat5.'\})*'; - my $brat0 = '(?:[^\[\]]|\\\[|\\\])*'; - my $abrat0 = '(?:[^<>])*'; - - my $quotemarks = '(?:\'\')|(?:\`\`)'; - my $punct='[0.,\/\'\`:;\"\?\(\)\[\]!~\p{IsNonAsciiPunct}\p{IsNonAsciiS}]'; - my $number='-?\d*\.\d*'; - 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}|$quotedunderscore|$cmdleftright|${cmdoptseq}|${math}|${backslashnl}|${oneletcmd}|${comment}|${punct}|${mathpunct}|\{|\})\s*/ ; - -# now we are done setting up and can start working -my ($oldfile, $newfile) = @ARGV; -# check for existence of input files -if ( ! -e $oldfile ) { - die "Input file $oldfile does not exist."; -} -if ( ! -e $newfile ) { - die "Input file $newfile does not exist."; -} - - -# set the labels to be included into the file -my ($oldtime,$newtime,$oldlabel,$newlabel); -if (defined($labels[0])) { - $oldlabel=$labels[0] ; -} else { - $oldtime=localtime((stat($oldfile))[9]); - $oldlabel="$oldfile " . " "x(length($newfile)-length($oldfile)) . $oldtime; -} -if (defined($labels[1])) { - $newlabel=$labels[1] ; -} else { - $newtime=localtime((stat($newfile))[9]); - $newlabel="$newfile " . " "x(length($oldfile)-length($newfile)) . $newtime; -} - -$encoding=guess_encoding($newfile) unless defined($encoding); - -$encoding = "utf8" if $encoding =~ m/^utf8/i ; -if (lc($encoding) eq "utf8" ) { - binmode(STDOUT, ":utf8"); - binmode(STDERR, ":utf8"); -} - -$old=read_file_with_encoding($oldfile,$encoding); -$new=read_file_with_encoding($newfile,$encoding); - - - - -# reset time -exetime(1); -($oldpreamble,$oldbody,$oldpost)=splitdoc($old,'\\\\begin\{document\}','\\\\end\{document\}'); - - -($newpreamble,$newbody,$newpost)=splitdoc($new,'\\\\begin\{document\}','\\\\end\{document\}'); - - -if ($flatten) { - $oldbody=flatten($oldbody,$oldpreamble,$oldfile,$encoding); - $newbody=flatten($newbody,$newpreamble,$newfile,$encoding); -} - - - - -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 - @auxlines=preprocess_preamble($oldpreamble,$newpreamble); - - @oldpreamble = split /\n/, $oldpreamble; - @newpreamble = split /\n/, $newpreamble; - - # If a command is defined in the preamble of the new file, and only uses safe commands, then it can be considered to be safe) (contribution S. Gouezel) - # Base this assessment on the new preamble - add_safe_commands($newpreamble); - - # get a list of packages from preamble if not predefine - %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"),""); - ### $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; - - # insert dummy first line such that line count begins with line 1 (rather than perl's line 0) - just so that line numbers inserted by linediff are correct - unshift @newpreamble,''; - unshift @oldpreamble,''; - @diffpreamble = linediff(\@oldpreamble, \@newpreamble); - # remove dummy line again - shift @diffpreamble; - # add filenames, modification time and latexdiff mark - defined($nolabel) or splice @diffpreamble,1,0, - "%DIF LATEXDIFF DIFFERENCE FILE", - ,"%DIF DEL $oldlabel", - "%DIF ADD $newlabel"; - if ( @auxlines ) { - push @diffpreamble,"%DIF DELETED TITLE COMMANDS FOR MARKUP"; - push @diffpreamble,join("\n",@auxlines); - } - if ( $earlylatexdiffpreamble) { - # insert latexdiff command directly after documentclass at beginning of preamble - # note that grep is only run for its side effect - ( grep { s/^([^%]*\\documentclass.*)$/$1$latexdiffpreamble/ } @diffpreamble )==1 or die "Could not find documentclass statement in preamble"; - } else { - # insert latexdiff commands at the end of preamble (default behaviour) - push @diffpreamble,$latexdiffpreamble; - } - push @diffpreamble,'\begin{document}'; -} -elsif ( !length $oldpreamble && !length $newpreamble ) { - @diffpreamble=(); -} else { - print STDERR "Either both texts must have preamble or neither text must have the preamble.\n"; - exit(2); -} - -# Special: treat all cite commands as safe except in UNDERLINE and FONTSTRIKE mode -# (there is a conflict between citation and ulem package, see -# package documentation) -# Use post-processing -# and $packages{"apacite"}!~/natbibpapa/ - -$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 "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 - $citpat='(?:cite\w*|nocite)'; -}; - -if ( ! $ulem ) { - # modes not using ulem: citation is safe - push (@SAFECMDLIST, $citpat); -} else { - ### Experimental: disable text and emph commands - 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 @MBOXCMDLIST; - # deleted cite commands - } -} -push(@MBOXCMDLIST,$citpat) if $enablecitmark ; - - -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; -preprocess($oldbody,$newbody); - - -# run difference algorithm -@diffbody=bodydiff($oldbody, $newbody); -$diffbo=join("",@diffbody); -if ( $debug ) { - open(RAWDIFF,">","latexdiff.debug.bodydiff"); - print RAWDIFF $diffbo; - close(RAWDIFF); -} -print STDERR "(",exetime()," s)\n","Postprocessing body. \n " if $verbose; -postprocess($diffbo); -$diffall =join("\n",@diffpreamble) ; -# add visible labels -if (defined($visiblelabel)) { - # Give information right after \begin{document} (or at the beginning of the text for files without preamble - ### if \date command is used, add information to \date argument, otherwise give right after \begin{document} - ### $diffall=~s/(\\date$extraspace(?:\[$brat0\])?$extraspace)\{($pat6)\}/$1\{$2 \\ LATEXDIFF comparison \\ Old: $oldlabel \\ New: $newlabel \}/ or - $diffbo = "\\begin{verbatim}LATEXDIFF comparison\nOld: $oldlabel\nNew: $newlabel\\end{verbatim}\n$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; - $diffall=Encode::encode($encoding,$diffall); - binmode STDOUT; -} -print $diffall; - - -print STDERR "(",exetime()," s)\n","Done.\n" if $verbose; - - - -## guess_encoding(filename) -## reads the first 20 lines of filename and looks for call of inputenc package -## if found, return the option of this package (encoding), otherwise return ascii -sub guess_encoding { - my ($filename)=@_; - my ($i,$enc); - open (FH, $filename) or die("Couldn't open $filename: $!"); - $i=0; - while () { - next if /^\s*%/; # skip comment lines - if (m/\\usepackage\[(\w*?)\]\{inputenc\}/) { - close(FH); - return($1); - } - last if (++$i > 20 ); # scan at most 20 non-comment lines - } - close(FH); - return("ascii"); -} - - -sub read_file_with_encoding { - my ($output); - my ($filename, $encoding) = @_; - - if (lc($encoding) eq "utf8" ) { - open (FILE, "<:utf8",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } elsif ( lc($encoding) eq "ascii") { - open (FILE, $filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - } else { - require Encode; - open (FILE, "<",$filename) or die("Couldn't open $filename: $!"); - local $/ ; # locally set record operator to undefined, ie. enable whole-file mode - $output=; - print STDERR "Converting $filename from $encoding to utf8\n" if $verbose; - $output=Encode::decode($encoding,$output); - } - close FILE; - if ($^O eq "linux" ) { - $output =~ s/\r\n/\n/g ; - } - return $output; -} - -## %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/(?catfile($dirname,$fname), "\n" if $debug; - # content of file becomes replacement value (use recursion), add \newpage if the command was include - ###$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 - $newpage=(defined($3)? " \\newpage " : "") ; - "$begline$newpage$replacement$newpage"; - }/exgm; - # replace bibliography with bbl file if it exists - $text=~s/(^(?:[^%\n]|\\%)*)\\bibliography{(.*?)}/{ - if ( -f $bblfile ){ - $replacement=read_file_with_encoding(File::Spec->catfile($bblfile), $encoding); - } else { - warn "Bibliography file $bblfile cannot be found. No flattening of \\bibliography done. Run bibtex on old and new files first"; - $replacement="\\bibliography{$2}"; - } - $begline=(defined($1)? $1 : "") ; - "$begline$replacement"; - }/exgm; - # replace subfile with contents (subfile package) - $text=~s/(^(?:[^%\n]|\\%)*)\\subfile{(.*?)}/{ - $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 "Include file as subfile $fname\n" if $verbose; - # 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$replacement"; - }/exgm; - - return($text); -} - - -# print_regex_arr(@arr) -# prints regex array without x-ism expansion put in by pearl to stdout -sub print_regex_arr { - my $dumstring; - $dumstring = join(" ",@_); # PERL generates string (?-xism:^ref$) for quoted refex ^ref$ - $dumstring =~ s/\(\?-xism:\^(.*?)\$\)/$1/g; # remove string and ^,$ marks before output - print $dumstring,"\n"; -} - - -# @lines=extrapream($type) -# reads line from appendix (end of file after __END__ token) -sub extrapream { - my $type; - my @retval=("%DIF PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - my ($copy); - - while (@_) { - $copy=0; - $type=shift ; - if ( -f $type || lc $type eq '/dev/null' ) { - open (FILE,$type) or die "Cannot open preamble file $type: $!"; - print STDERR "Reading preamble file $type\n" if $verbose ; - while () { - chomp ; - if ( $_ =~ m/%DIF PREAMBLE/ ) { - push (@retval,"$_"); - } else { - push (@retval,"$_ %DIF PREAMBLE"); - } - } - } - else { # not (-f $type) - $type=uc($type); # upcase argument - print STDERR "Preamble Internal Type $type\n" if $verbose; - while () { - if ( m/^%DIF $type/ ) { - $copy=1; } - elsif ( m/^%DIF END $type/ ) { - last; } - chomp; - push (@retval,"$_ %DIF PREAMBLE") if $copy; - } - if ( $copy == 0 ) { - print STDERR "\nPreamble style $type not implemented.\n"; - print STDERR "Write latexdiff -h to get help with available styles\n"; - exit(2); - } - seek DATA,0,0; # rewind DATA handle to file begin - } - } - push (@retval,"%DIF END PREAMBLE EXTENSION ADDED BY LATEXDIFF") ; - return @retval; -} - - -# ($part1,$part2,$part3)=splitdoc($text,$word1,$word2) -# splits $text into 3 parts at $word1 and $word2. -# if neither $word1 nor $word2 exist, $part1 and $part3 are empty, $part2 is $text -# If only $word1 or $word2 exist but not the other, output an error message. - -# NB this version avoids $` and $' for performance reason although it only makes a tiny difference -# (in one test gain a tenth of a second for a 30s run) -sub splitdoc { - my ($text,$word1,$word2)=@_; - my ($part1,$part2,$part3)=("","",""); - my ($rest,$pos); - - if ( $text =~ m/(^[^%]*)($word1)/mg ) { - $pos=pos $text; - $part1=substr($text,0,$pos-length($2)); - $rest=substr($text,$pos); - if ( $rest =~ m/(^[^%]*)($word2)/mg ) { - $pos=pos $rest; - $part2=substr($rest,0,$pos-length($2)); - $part3=substr($rest,$pos); - } - else { - die "$word1 and $word2 not in the correct order or not present as a pair." ; - } - } else { - $part2=$text; - die "$word2 present but not $word1." if ( $text =~ m/(^[^%]*)$word2/ms ); - } - return ($part1,$part2,$part3); -} - - - - - -# bodydiff($old,$new) -sub bodydiff { - my ($oldwords, $newwords) = @_; - my @retwords; - - print STDERR "(",exetime()," s)\n","Splitting into latex tokens \n" if $verbose; - print STDERR "Parsing $oldfile \n" if $verbose; - my @oldwords = splitlatex($oldwords); - print STDERR "Parsing $newfile \n" if $verbose; - my @newwords = splitlatex($newwords); - - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - print STDERR "(",exetime()," s)\n","Pass 1: Expanding text commands and merging isolated identities with changed blocks " if $verbose; - pass1(\@oldwords, \@newwords); - - - print STDERR "(",exetime()," s)\n","Pass 2: inserting DIF tokens and mark up. " if $verbose; - if ( $debug ) { - open(TOKENOLD,">","latexdiff.debug.tokenold2"); - print TOKENOLD join("***\n",@oldwords); - close(TOKENOLD); - open(TOKENNEW,">","latexdiff.debug.tokennew2"); - print TOKENNEW join("***\n",@newwords); - close(TOKENNEW); - } - - @retwords=pass2(\@oldwords, \@newwords); - - return(@retwords); -} - - - - -# @words=splitlatex($string) -# split string according to latex rules -# 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 ($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); - - if (length($string) != length(join("",@retval))) { - print STDERR "\nWARNING: Inconsistency in length of input string and parsed string:\n This often indicates faulty or non-standard latex code.\n In many cases you can ignore this and the following warning messages.\n Note that character numbers in the following are counted beginning after \\begin{document} and are only approximate." unless $ignorewarnings; - print STDERR "DEBUG Original length ",length($string)," Parsed length ",length(join("",@retval)),"\n" if $debug; - print STDERR "DEBUG Input string: |$string|\n" if (length($string)<500) && $debug; - print STDERR "DEBUG Token parsing: |",join("+",@retval),"|\n" if (length($string)<500) && $debug ; - @retval=(); - # slow way only do this if other m//sg method fails - my $last = 0; - while ( $string =~ m/$pat/osg ) { - my $match=$&; - if ($last + length $& != pos $string ) { - my $pos=pos($string); - my $offset=30<$last ? 30 : $last; - my $dum=substr($string,$last-$offset,$pos-$last+2*$offset); - my $dum1=$dum; - my $cnt=$#retval; - my $i; - $dum1 =~ s/\n/ /g; - unless ($ignorewarnings) { - print STDERR "\n$dum1\n"; - print STDERR " " x 30,"^" x ($pos-$last)," " x 30,"\n"; - print STDERR "Missing characters near word " . (scalar @retval) . " character index: " . $last . "-" . pos($string) . " Length: " . length($match) . " Match: |$match| (expected match marked above).\n"; - } - # put in missing characters `by hand' - push (@retval, substr($dum,$offset,$pos-$last-length($match))); -# Note: there seems to be a bug in substr with utf8 that made the following line output substr which were too long, -# using dum instead appears to work -# push (@retval, substr($string,$last, pos($string)-$last-length($match))); - } - push (@retval, $match); - $last=pos $string; - } - - } - unshift(@retval,$leadin) if (length($leadin)>0); - return @retval; -} - - -# pass1( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Where an common-subsequence block is flanked by deleted or appended blocks, -# and is shorter than $MINWORDSBLOCK words it is appended -# to the last deleted or appended word. If the block contains tokens other than words -# or punctuation it is not merged. -# Deleted or appended block consisting of words and safe commands only are -# also merged, to prevent break-up in pass2 (after previous isolated words have been removed) -# If there are commands with textual arguments (e.g. \caption) both in corresponding -# appended and deleted blocks split them such that the command and opening bracket -# are one token, then the rest is split up following standard rules, and the closing -# bracket is a separate token, ie. turn -# "\caption{This is a textual argument}" into -# ("\caption{","This ","is ","a ","textual ","argument","}") -# No return value. Destructively changes sequences -sub pass1 { - my $seq1 = shift ; - my $seq2 = shift ; - - my $len1 = scalar @$seq1; - my $len2 = scalar @$seq2; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - - my ($last1,$last2)=(-1,-1) ; - my $cnt=0; - my $block=[]; - my $addblock=[]; - my $delblock=[]; - my $todo=[]; - my $instruction=[]; - my $i; - my (@delmid,@addmid,@dummy); - - my ($addcmds,$delcmds,$matchindex); - my ($addtextblocks,$deltextblocks); - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $adddiscard = sub { - if ($cnt > 0 ) { - $matblkcnt++; - # just after an unchanged block -# print STDERR "Unchanged block $cnt, $last1,$last2 \n"; - if ($cnt < $MINWORDSBLOCK - && $cnt==scalar ( - grep { /^$wpat/ || ( /^\\((?:[`'^"~=.]|[\w\d@*]+))((?:\[$brat0\]|\{$pat6\})*)/o - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && scalar(@dummy=split(" ",$2))<3 ) } - @$block) ) { - # merge identical blocks shorter than $MINWORDSBLOCK - # and only containing ordinary words - # with preceding different word - # We cannot carry out this merging immediately as this - # would change the index numbers of seq1 and seq2 and confuse - # the algorithm, instead we store in @$todo where we have to merge - push(@$todo, [ $last1,$last2,$cnt,@$block ]); - } - $block = []; - $cnt=0; $last1=-1; $last2=-1; - } - }; - my $discard=sub { $deltokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$delblock,[ $seq1->[$_[0]],$_[0] ]); - $last1=$_[0] }; - - my $add = sub { $addtokcnt++; - &$adddiscard; #($_[0],$_[1]); - push(@$addblock,[ $seq2->[$_[1]],$_[1] ]); - $last2=$_[1] }; - - my $match = sub { $mattokcnt++; - if ($cnt==0) { # first word of matching sequence after changed sequence or at beginning of word sequence - $deltextblocks = extracttextblocks($delblock); - $delblkcnt++ if scalar @$delblock; - $addtextblocks = extracttextblocks($addblock); - $addblkcnt++ if scalar @$addblock; - - $delcmds = extractcommands($delblock); - $addcmds = extractcommands($addblock); - # keygen(third argument of _longestCommonSubsequence) implies to sort on command (0th elements of $addcmd elements) - # the calling format for longestCommonSubsequence has changed between versions of - # Algorithm::Diff so we need to check which one we are using - if ( $algodiffversion > 1.15 ) { - ### Algorithm::Diff 1.19 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, 0, sub { $_[0]->[0] } ); - } else { - ### Algorithm::Diff 1.15 - $matchindex=Algorithm::Diff::_longestCommonSubsequence($delcmds,$addcmds, sub { $_[0]->[0] } ); - } - - for ($i=0 ; $i<=$#$matchindex ; $i++) { - if (defined($matchindex->[$i])){ - $j=$matchindex->[$i]; - @delmid=splitlatex($delcmds->[$i][3]); - @addmid=splitlatex($addcmds->[$j][3]); - while (scalar(@$deltextblocks) && $deltextblocks->[0][0]<$delcmds->[$i][1]) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) }; - push(@$todo, [$index,-1,$cnt,@$block]); - } - push(@$todo, [ $delcmds->[$i][1],-1,-1,$delcmds->[$i][2],@delmid,$delcmds->[$i][4]]); - - while (scalar(@$addtextblocks) && $addtextblocks->[0][0]<$addcmds->[$j][1]) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - push(@$todo, [ -1,$addcmds->[$j][1],-1,$addcmds->[$j][2],@addmid,$addcmds->[$j][4]]); - } - } - # mop up remaining textblocks - while (scalar(@$deltextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$deltextblocks) } ; - push(@$todo, [$index,-1,$cnt,@$block]); - } - while (scalar(@$addtextblocks)) { - my ($index,$block,$cnt)=@{ shift(@$addtextblocks) }; - push(@$todo, [-1,$index,$cnt,@$block]); - } - - $addblock=[]; - $delblock=[]; - } - push(@$block,$seq2->[$_[1]]); - $cnt++ }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - - - # now carry out the merging/splitting. Refer to elements relative from - # the end (with negative indices) as these offsets don't change before the instruction is executed - # cnt>0: merged small unchanged groups with previous changed blocks - # cnt==-1: split textual commands into components - foreach $instruction ( @$todo) { - ($last1,$last2,$cnt,@$block)=@$instruction ; - if ($cnt>=0) { - splice(@$seq1,$last1-$len1,1+$cnt,join("",$seq1->[$last1-$len1],@$block)) if $last1>=0; - splice(@$seq2,$last2-$len2,1+$cnt,join("",$seq2->[$last2-$len2],@$block)) if $last2>=0; - } else { - splice(@$seq1,$last1-$len1,1,@$block) if $last1>=0; - splice(@$seq2,$last2-$len2,1,@$block) if $last2>=0; - } - } - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens in $matblkcnt blocks.\n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } -} - - -# extracttextblocks(\@blockindex) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [[ $index, $textblock, $cnt ], .. -# where $index index of block to be merged -# $textblock contains all the words to be merged with the word at $index (but does not contain this word) -# $cnt is length of block -# -# requires: iscmd -# -sub extracttextblocks { - my $block=shift; - my ($i,$token,$index); - my $textblock=[]; - my $last=-1; - my $wpat=qr/^(?:[a-zA-Z.,'`:;?()!]*)[\s~]*$/; #' - my $retval=[]; - - 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 - && iscmd($1,\@SAFECMDLIST,\@SAFECMDEXCL) - && !iscmd($1,\@TEXTCMDLIST,\@TEXTCMDEXCL))) { - # we have text or a command which can be treated as text - if ($last<0) { - # new pure-text block - $last=$index; - } else { - # add to pure-text block - push(@$textblock, $token); - } - } else { - # it is not text - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - $textblock=[]; - $last=-1; - } - } - # finish processing a possibly unfinished block before returning - if (scalar(@$textblock)) { - push(@$retval,[ $last, $textblock, scalar(@$textblock) ]); - } - return($retval) -} - - - -# extractcommands( \@blockindex ) -# $blockindex has the following format -# [ [ token1, index1 ], [token2, index2],.. ] -# where index refers to the index in the original old or new word sequence -# Returns: reference to an array of the form -# [ [ "\cmd1", index, "\cmd1[optarg]{arg1}{", "arg2" ,"} " ],.. -# where index is just taken from input array -# command must have a textual argument as last argument -# -# requires: iscmd -# -sub extractcommands { - my $block=shift; - my ($i,$token,$index,$cmd,$open,$mid,$closing); - my $retval=[]; - - for ($i=0;$i< scalar @$block;$i++) { - ($token,$index)=@{ $block->[$i] }; - # check if token is an alphanumeric command sequence with at least one non-optional argument - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: \cmd - # $3: last argument - # $4: } + trailing spaces - if ( ( $token =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL) ) { - # push(@$retval,[ $2,$index,$1,$3,$4 ]); - ($cmd,$open,$mid,$closing) = ($2,$1,$3,$4) ; - $closing =~ s/\}/\\RIGHTBRACE/ ; - push(@$retval,[ $cmd,$index,$open,$mid,$closing ]); - } - } - return $retval; -} - -# iscmd($cmd,\@regexarray,\@regexexcl) checks -# return 1 if $cmd matches any of the patterns in the -# array $@regexarray, and none of the patterns in \@regexexcl, otherwise return 0 -sub iscmd { - my ($cmd,$regexar,$regexexcl)=@_; - my ($ret)=0; - foreach $pat ( @$regexar ) { - if ( $cmd =~ m/^${pat}$/ ) { - $ret=1 ; - last; - } - } - return 0 unless $ret; - foreach $pat ( @$regexexcl ) { - return 0 if ( $cmd =~ m/^${pat}$/ ); - } - return 1; -} - - -# pass2( \@seq1,\@seq2) -# Look for differences between seq1 and seq2. -# Mark begin and end of deleted and appended sequences with tags $DELOPEN and $DELCLOSE -# and $ADDOPEN and $ADDCLOSE, respectively, however exclude { } & and all comands, unless -# they match an element of the whitelist (SAFECMD) -# For words in TEXTCMD but not in SAFECMD, enclose interior with $ADDOPEN and $ADDCLOSE brackets -# Deleted comment lines are marked with %DIF < -# Added comment lines are marked with %DIF > -sub pass2 { - my $seq1 = shift ; - my $seq2 = shift ; - - my ($addtokcnt,$deltokcnt,$mattokcnt)=(0,0,0); - my ($addblkcnt,$delblkcnt,$matblkcnt)=(0,0,0); - - my $retval = []; - my $delhunk = []; - my $addhunk = []; - - my $discard = sub { $deltokcnt++; - push ( @$delhunk, $seq1->[$_[0]]) }; - - my $add = sub { $addtokcnt++; - push ( @$addhunk, $seq2->[$_[1]]) }; - - my $match = sub { $mattokcnt++; - if ( scalar @$delhunk ) { - $delblkcnt++; - # mark up changes, but comment out commands - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk); - $delhunk = []; - } - if ( scalar @$addhunk ) { - $addblkcnt++; - # we mark up changes, but simply quote commands - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk); - $addhunk = []; - } - push(@$retval,$seq2->[$_[1]]) }; - - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - # clear up unprocessed hunks - push @$retval,marktags($DELMARKOPEN,$DELMARKCLOSE,$DELOPEN,$DELCLOSE,$DELCMDOPEN,$DELCMDCLOSE,$DELCOMMENT,$delhunk) if scalar @$delhunk; - push @$retval,marktags($ADDMARKOPEN,$ADDMARKCLOSE,$ADDOPEN,$ADDCLOSE,"","",$ADDCOMMENT,$addhunk) if scalar @$addhunk; - - - if ($verbose) { - print STDERR "\n"; - print STDERR " $mattokcnt matching tokens. \n"; - print STDERR " $deltokcnt discarded tokens in $delblkcnt blocks.\n"; - print STDERR " $addtokcnt appended tokens in $addblkcnt blocks.\n"; - } - - return(@$retval); -} - -# marktags($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,\@block) -# 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 -# ($openmark, $open,...,$close, $opencmd,command, command,$closecmd, $open, ..., $close, $closemark) -# If $opencmd begins with "%" marktags assumes it is operating on a deleted block, otherwise on an added block -sub marktags { - my ($openmark,$closemark,$open,$close,$opencmd,$closecmd,$comment,$block)=@_; - my $word; - my (@argtext); - my $retval=[]; - my $noncomment=0; - my $cmd=-1; # -1 at beginning 0: last token written is a ordinary word - # 1: last token written is a command - # for keeping track whether we are just in a command sequence or in a word sequence - my $cmdcomment= ($opencmd =~ m/^%/); # Flag to indicate whether opencmd is a comment (i.e. if we intend to simply comment out changed commands) - my ($command,$commandword,$closingbracket) ; # temporary variables needed below to remember sub-pattern matches - -# 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) { - push (@$retval,$closecmd) ; - $cmd=-1; - } - 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 matching \( .. \) patterns - # also note that second pattern will match \\ - ### 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 - # \cmd[...]{...}{last argument} - # Capturing in the following results in these associations - # $1: \cmd[...]{...}{ - # $2: cmd - # $3: last argument - # $4: } + trailing spaces - ### pre-0.3 if ( ( $token =~ m/^(\\([\w\d\*]+)(?:\[$brat0\]|\{$pat6\})*\{)($pat6)(\}\s*)$/so ) - if ( ( $word =~ m/^(\\([\w\d\*]+)(?:${extraspace}\[$brat0\]|${extraspace}\{$pat6\})*${extraspace}\{)($pat6)(\}\s*)$/so ) - && (iscmd($2,\@TEXTCMDLIST,\@TEXTCMDEXCL)|| iscmd($2,\@MATHTEXTCMDLIST,\@MATHTEXTCMDEXCL)) - && ( !$cmdcomment || !iscmd($2,\@CONTEXT2CMDLIST, \@CONTEXT2CMDEXCL) ) ) { - # Condition 1: word is a command? - if yes, $1,$2,.. will be set as above - # Condition 2: word is a text command - we mark up the interior of the word. There is a separate check for MATHTEXTCMDLIST - # because for $mathmarkup=WHOLE, the commands should not be split in pass1 (ie. math mode commands are not in - # TEXTCMDLIST, but the interior of MATHTEXT commands should be highlighted in both deleted and added blocks - # Condition 3: But if we are in a deleted block ($cmdcomment=1) and - # $2 (the command) is in context2, just treat it as an ordinary command (i.e. comment it open with $opencmd) - # Because we do not want to disable this command - # here we do not use $opencmd and $closecmd($opencmd is empty) - if ($cmd==1) { - push (@$retval,$closecmd) ; - } elsif ($cmd==0) { - push (@$retval,$close) ; - } - $command=$1; $commandword=$2; $closingbracket=$4; - @argtext=splitlatex($3); # split textual argument into tokens - # and mark it up (but we do not need openmark and closemark) - # insert command with initial arguments, marked-up final argument, and closing bracket - if ( $cmdcomment && iscmd($commandword,\@CONTEXT1CMDLIST, \@CONTEXT1CMDEXCL) ) { - # context1cmd in a deleted environment; delete command itself but keep last argument, marked up - push (@$retval,$opencmd); - $command =~ s/\n/\n${opencmd}/sg ; # repeat opencmd at the beginning of each line - # argument, note that the additional comment character is included - # to suppress linebreak after opening parentheses, which is important - # for latexrevise - push (@$retval,$command,"%\n{$AUXCMD\n",marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } elsif ( iscmd($commandword,,\@MATHTEXTCMDLIST, \@MATHTEXTCMDEXCL) ) { - # MATHBLOCK pseudo command: consider all commands safe, except & and \\ - # Keep these commands even in deleted blocks, hence set $opencmd and $closecmd (5th and 6th argument of marktags) to - # "" - 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 { - # normal textcmd or context1cmd in an added block - push (@$retval,$command,marktags("","",$open,$close,$opencmd,$closecmd,$comment,\@argtext),$closingbracket); - } - push (@$retval,$AUXCMD,"\n") if $cmdcomment ; - $cmd=-1 ; - } else { - # ordinary command - push (@$retval,$opencmd) if $cmd==-1 ; - push (@$retval,$close,$opencmd) if $cmd==0 ; - $word =~ s/\n/\n${opencmd}/sg if $cmdcomment ; # if opencmd is a comment, repeat this at the beginning of every line - push (@$retval,$word); - $cmd=1; - } - } else { - ###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 ; - ###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; - } - } - push (@$retval,$close) if $cmd==0; - push (@$retval,$closecmd) if $cmd==1; - - push (@$retval,$closemark) if ($noncomment); - return @$retval; -} - -# preprocess($string, ..) -# carry out the following pre-processing steps for all arguments: -# 1. Remove leading white-space -# 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 -# 4. Convert all \verb|some verbatim text| commands (where | can be an arbitrary character) -# into \verb{hash} -# 5. Convert \begin{verbatim} some verbatim text \end{verbatim} into \verbatim{hash} -# 6. Convert _n into \SUBSCRIPTNB{n} and _{nnn} into \SUBSCRIPT{nn} -# 7. Convert ^n into \SUPERSCRIPTNB{n} and ^{nnn} into \SUPERSCRIPT{nn} -# 8. a. Convert $$ $$ into \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} -# b. Convert \[ \] into \begin{SQUAREBRACKET} \end{SQUAREBRACKET} -# 9. Convert all picture environmentent (\begin{PICTUREENV} .. \end{PICTUREENV} \PICTUREBLOCKenv -# For --block-math-markup option -convert all \begin{MATH} .. \end{MATH} -# into \MATHBLOCKmath{...} commands, where MATH/math is any valid math environment - -# 10. Add final token STOP to the very end. This is put in because the algorithm works better if the last token is identical. This is removed again in postprocessing. -# -# NB: step 6 and 7 is likely to convert some "_" inappropriately, e.g. in file -# 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 { - for (@_) { - # Change \{ to \QLEFTBRACE and \} to \QRIGHTBRACE - s/(?{$hstr}) && $string ne $hash->{$hstr}) { - warn "Repeated hash value for verbatim mode in spite of different content."; - $hstr="-$hstr"; - } - $hash->{$hstr}=$string; - return($hstr); -} - -#string=fromhash(\%hash,$fromstring) -# restores string value stored in hash -#string=fromhash(\%hash,$fromstring,$prependstring) -# additionally begins each line with prependstring -sub fromhash { - my ($hash,$hstr)=($_[0],$_[1]); - my $retstr=$hash->{$hstr}; - if ( $#_ >= 2) { - $retstr =~ s/^/$_[2]/mg; - } - return $retstr; -} - - -# postprocess($string, ..) -# carry out the following post-processing steps for all arguments: -# * Remove STOP token from the end -# * Replace \RIGHTBRACE by } -# * change citation commands within comments to protect from processing (using marker CITEDIF) -# 1. Check all deleted blocks: -# a.where a deleted block contains a matching \begin and -# \end environment (these will be disabled by a %DIFDELCMD statements), for selected environments enable -# these commands again (such that for example displayed math in a deleted equation -# is properly within math mode. For math mode environments replace numbered equation -# environments with their display only variety (so that equation numbers in new file and -# diff file are identical). Where the correct type of math environment cannot be determined -# use a place holder MATHMODE -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file -# Replace all MATHMODE environment commands by the correct environment to achieve matching -# pairs -# c. Convert MATHBLOCKmath commands to their uncounted numbers (e.g. convert equation -> displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL -# d. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# For added blocks: -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es -# d. place \cite commands in mbox'es (for UNDERLINE style) -# -# 2. If --block-math-markup option set: Convert \MATHBLOCKmath{..} commands back to environments -# -# Convert all PICTUREblock{..} commands back to the appropriate environments -# 3. Convert DIFadd, DIFdel, DIFFaddbegin , ... into FL varieties -# within floats (currently recognised float environments: plate,table,figure -# plus starred varieties). -# 4. Remove empty %DIFDELCMD < lines -# 4. Convert \begin{SQUAREBRACKET} \end{SQUAREBRACKET} into \[ \] -# Convert \begin{DOLLARDOLLAR} \end{DOLLARDOLLAR} into $$ $$ -# 5. Convert \SUPERSCRIPTNB{n} into ^n and \SUPERSCRIPT{nn} into ^{nnn} -# 6. Convert \SUBSCRIPTNB{n} into _n and \SUBCRIPT{nn} into _{nnn} -# 7. Expand hashes of verb and verbatim environments -# 8. Convert '\PERCENTAGE ' back into '\%' and '\DOLLAR ' into '\$' -# 9.. remove all \PAR tokens -# 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,\AMPERSAND to \{,\},\& -# -# Note have to manually synchronize substitution commands below and -# DIF.. command names in the header -sub postprocess { - my ($begin,$len,$cnt,$float,$delblock,$addblock); - # second level blocks - my ($begin2,$cnt2,$len2,$eqarrayblock,$mathblock); - - for (@_) { - - # change $'s in comments to something harmless - 1 while s/(%.*)\$/$1DOLLARDIF/mg ; - - # Remove final STOP token - s/ STOP$//; - # Replace \RIGHTBRACE by } - s/\\RIGHTBRACE/}/g; - - # 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 - # is properly within math mode. For math mode environments replace numbered equation - # environments with their display only variety (so that equation numbers in new file and - # diff file are identical - while ( m/\\DIFdelbegin.*?\\DIFdelend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $delblock=$&; - - - ### (.*?[^\n]?)\n? construct is necessary to avoid empty lines in math mode, which result in - ### an error - # displayed math environments - if ($mathmarkup == FINE ) { - $delblock=~ s/(\%DIFDELCMD < \s*\\begin\{((?:$MATHENV)|SQUAREBRACKET)\}.*?(?:$DELCMDCLOSE|\n))(.*?[^\n]?)\n?(\%DIFDELCMD < \s*\\end\{\2\})/\\begin{$MATHREPL}$AUXCMD\n$1$3\n\\end{$MATHREPL}$AUXCMD\n$4/sg; - # also transform the opposite pair \end{displaymath} .. \begin{displaymath} but we have to be careful not to interfere with the results of the transformation in the line directly above - ### pre-0.42 obsolete version which did not work on eqnarray test $delblock=~ s/(? displaymath -# (environments defined in $MATHENV will be replaced by $MATHREPL, and environments in $MATHARRENV -# will be replaced by $MATHARRREPL - $delblock=~ s/\\MATHBLOCK($MATHENV)\{($pat6)\}/\\MATHBLOCK$MATHREPL\{$2\}/sg; - $delblock=~ s/\\MATHBLOCK($MATHARRENV)\{($pat6)\}/\\MATHBLOCK$MATHARRREPL\{$2\}/sg; - } - - -# b.where one of the commands matching $COUNTERCMD is used as a DIFAUXCMD, add a statement -# subtracting one from the respective counter to keep numbering consistent with new file - $delblock=~ s/\\($COUNTERCMD)((?:${extraspace}\[$brat0\]${extraspace}|${extraspace}\{$pat6\})*\s*${AUXCMD}\n)/\\$1$2\\addtocounter{$1}{-1}${AUXCMD}\n/sg ; - - -# c. If in-line math mode contains array environment, enclose the whole environment in \mbox'es - while ( $delblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($delblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($delblock,$begin2,$len2)=$mathblock; - pos($delblock) = $begin2 + length($mathblock); - } - # 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) - $delblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } - -# splice in modified delblock - substr($_,$begin,$len)=$delblock; - pos = $begin + length($delblock); - } - # make the array modification in added blocks - while ( m/\\DIFaddbegin.*?\\DIFaddend/sg ) { - $cnt=0; - $len=length($&); - $begin=pos($_) - $len; - $addblock=$&; - while ( $addblock =~ m/($math)(\s*)/sg ) { - $cnt2=0; - $len2=length($&); - $begin2=pos($addblock) - $len2; - $mathblock="%\n\\mbox{$AUXCMD\n$1\n}$AUXCMD\n"; - next unless $mathblock =~ m/\{$ARRENV\}/ ; - substr($addblock,$begin2,$len2)=$mathblock; - pos($addblock) = $begin2 + length($mathblock); - } - # 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; - $addblock=~s/($math)(?:[\s\n]*)?/\\mbox{$AUXCMD\n$1\n}$AUXCMD\n/sg; - } -# splice in modified addblock - substr($_,$begin,$len)=$addblock; - pos = $begin + length($addblock); - } - - - - # Replace MATHMODE environments from step 1a above by the correct Math environment - - # The next line is complicated. The negative look-ahead insertion makes sure that no \end{$MATHENV} (or other mathematical - # environments) are between the \begin{$MATHENV} and \end{MATHMODE} commands. This is necessary as the minimal matching - # is not globally minimal but only 'locally' (matching is beginning from the left side of the string) - if ( $mathmarkup == FINE ) { - 1 while s/\\begin{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}((?:.(?!(?:\\end{(?:(?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}|\\begin{MATHMODE})))*?)\\end{MATHMODE}/\\begin{$1}$2\\end{$1}/s; - 1 while s/\\begin{MATHMODE}((?:.(?!\\end{MATHMODE}))*?)\\end{((?:$MATHENV)|(?:$MATHARRENV)|SQUAREBRACKET)}/\\begin{$2}$1\\end{$2}/s; - # convert remaining \begin{MATHMODE} \end{MATHMODE} (and not containing & or \\ )into MATHREPL environments - s/\\begin{MATHMODE}((?:(.(?!(?[1])) { - $optargnew=$newhash{$cmd}->[1]; - } else { - $optargnew=""; - } - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - } else { - $optargold=""; - } - - if ( defined($oldhash{$cmd}) ) { - $argold=$oldhash{$cmd}->[2]; - } else { - $argold=""; - } - $argnew=$newhash{$cmd}->[2]; - $argdiff="{" . join("",bodydiff($argold,$argnew)) ."}"; - if ( length $optargnew ) { - $optargdiff="[".join("",bodydiff($optargold,$optargnew))."]" ; - $optargdiff =~ s/\\DIFaddbegin /\\DIFaddbeginFL /g; - $optargdiff =~ s/\\DIFaddend /\\DIFaddendFL /g; - $optargdiff =~ s/\\DIFadd\{/\\DIFaddFL{/g; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - ### print STDERR "DEBUG s/\\Q$newhash{$cmd}->[0]\\E/\\$cmd$optargdiff$argdiff/s\n"; - # Note: \Q and \E force literal interpretation of what it between them but allow - # variable interpolation, such that e.g. \title matches just that and not TAB-itle - $$newpreambleref=~s/\Q$newhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s; - # replace this in old preamble if necessary - if ( defined($oldhash{$cmd}->[0])) { - $$oldpreambleref=~s/\Q$oldhash{$cmd}->[0]\E/\\$cmd$optargdiff$argdiff/s ; - } - ### print STDERR "DEBUG NEW PRE ".$$newpreambleref."\n"; - } - - foreach $cmd ( keys %oldhash ) { - # if this has already been dealt with above can just skip - next if defined($newhash{$cmd}) ; - if ( defined($oldhash{$cmd}->[1])) { - $optargold=$oldhash{$cmd}->[1]; - $optargdiff="[".join("",bodydiff($optargold,""))."]" ; - $optargdiff =~ s/\\DIFdelbegin /\\DIFdelbeginFL /g; - $optargdiff =~ s/\\DIFdelend /\\DIFdelendFL /g; - $optargdiff =~ s/\\DIFdel\{/\\DIFdelFL{/g; - } else { - $optargdiff=""; - } - $argdiff="{" . join("",bodydiff($argold,"")) ."}"; - $auxline = "\\$cmd$optargdiff$argdiff"; - $auxline =~s/$/$AUXCMD/sg; - push @auxlines,$auxline; - } - # add auxcmd comment to highlight added lines - return(@auxlines); -} - - - -# @diffs=linediff(\@seq1, \@seq2) -# mark up lines like this -#%DIF mm-mmdnn -#%< old deleted line(s) -#%DIF ------- -#%DIF mmann-nn -#new appended line %< -#%DIF ------- -# Future extension: mark change explicitly -# Assumes: traverse_sequence traverses deletions before insertions in changed sequences -# all line numbers relative to line 0 (first line of real file) -sub linediff { - my $seq1 = shift ; - my $seq2 = shift ; - - my $block = []; - my $retseq = []; - my @begin=('','',''); # dummy initialisation - my $instring ; - - my $discard = sub { @begin=('d',$_[0],$_[1]) unless scalar @$block ; - push(@$block, "%DIF < " . $seq1->[$_[0]]) }; - my $add = sub { if (! scalar @$block) { - @begin=('a',$_[0],$_[1]) ;} - elsif ( $begin[0] eq 'd' ) { - $begin[0]='c'; $begin[2]=$_[1]; - push(@$block, "%DIF -------") } - push(@$block, $seq2->[$_[1]] . " %DIF > " ) }; - my $match = sub { if ( scalar @$block ) { - if ( $begin[0] eq 'd' && $begin[1]!=$_[0]-1) { - $instring = sprintf "%%DIF %d-%dd%d",$begin[1],$_[0]-1,$begin[2]; } - elsif ( $begin[0] eq 'a' && $begin[2]!=$_[1]-1) { - $instring = sprintf "%%DIF %da%d-%d",$begin[1],$begin[2],$_[1]-1; } - elsif ( $begin[0] eq 'c' ) { - $instring = sprintf "%%DIF %sc%s", - ($begin[1]==$_[0]-1) ? "$begin[1]" : $begin[1]."-".($_[0]-1) , - ($begin[2]==$_[1]-1) ? "$begin[2]" : $begin[2]."-".($_[1]-1) ; } - else { - $instring = sprintf "%%DIF %d%s%d",$begin[1],$begin[0],$begin[2]; } - push @$retseq, $instring,@$block, "%DIF -------" ; - $block = []; - } - push @$retseq, $seq2->[$_[1]] - }; - # key function: remove multiple spaces (such that insertion or deletion of redundant white space is not reported) - my $keyfunc = sub { join(" ",split(" ",shift())) }; - - traverse_sequences($seq1,$seq2, { MATCH=>$match, DISCARD_A=>$discard, DISCARD_B=>$add }, $keyfunc ); - push @$retseq, @$block if scalar @$block; - - return wantarray ? @$retseq : $retseq ; -} - - - -# init_regex_arr_data(\@array,"TOKEN INIT") -# scans DATA file handel for line "%% TOKEN INIT" line -# then appends each line not beginning with % into array (as a quoted regex) -sub init_regex_arr_data { - my ($arr,$token)=@_; - my ($copy); - while () { - if ( m/^%%BEGIN $token\s*$/ ) { - $copy=1; } - elsif ( m/^%%END $token\s*/ ) { - last; } - chomp; - push (@$arr,qr/^$_$/) if ( $copy && !/^%/ ) ; - } - seek DATA,0,0; # rewind DATA handle to file begin -} - - -# init_regex_arr_ext(\@array,$arg) -# fills array with regular expressions. -# if arg is a file name, then read in list of regular expressions from that file -# (one expression per line) -# Otherwise treat arg as a comma separated list of regular expressions -sub init_regex_arr_ext { - my ($arr,$arg)=@_; - my $regex; - if ( -f $ arg ) { - open(FILE,"$arg") or die ("Couldn't open $arg: $!"); - while () { - chomp; - next if /^\s*#/ || /^\s*%/ || /^\s*$/ ; - push (@$arr,qr/^$_$/); - } - close(FILE); - } - else { - # assume it is a comma-separated list of reg-ex - foreach $regex (split(qr/(?=1) { - $reset=shift; - } - if ($reset) { - $lasttime=times(); - } - else { - $retval=times()-$lasttime; - $lasttime=$lasttime+$retval; - return($retval); - } -} - - -sub usage { - die <<"EOF"; -Usage: $0 [options] old.tex new.tex > diff.tex - -Compares two latex files and writes tex code to stdout, which has the same -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 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 ZLABEL ONLYCHANGEDPAGE (LABEL)* - [ Default: SAFE ] - * LABEL subtype is deprecated - ---floattype=markstyle --f markstyle Add code to preamble for selected style which - replace standard marking and markup commands within floats - (e.g., marginal remarks cause an error within floats - so marginal marking can be disabled thus) - Available styles: FLOATSAFE IDENTICAL - [ Default: FLOATSAFE ] - ---encoding=enc --e enc Specify encoding of old.tex and new.tex. Typical encodings are - ascii, utf8, latin1, latin9. A list of available encodings can be - obtained by executing - perl -MEncode -e 'print join ("\\n",Encode->encodings( ":all" )) ;' - [Default encoding is utf8 unless the first few lines of the preamble contain - an invocation "\\usepackage[..]{inputenc} in which case the - encoding chosen by this command is asssumed. Note that ASCII (standard - latex) is a subset of utf8] - ---preamble=file --p file Insert file at end of preamble instead of auto-generating - preamble. The preamble must define the following commands - \\DIFaddbegin,\\DIFaddend,\\DIFadd{..}, - \\DIFdelbegin,\\DIFdelend,\\DIFdel{..}, - and varieties for use within floats - \\DIFaddbeginFL,\\DIFaddendFL,\\DIFaddFL{..}, - \\DIFdelbeginFL,\\DIFdelendFL,\\DIFdelFL{..} - (If this option is set -t, -s, and -f options - are ignored.) - ---exclude-safecmd=exclude-file ---exclude-safecmd="cmd1,cmd2,..." --A exclude-file ---replace-safecmd=replace-file ---append-safecmd=append-file ---append-safecmd="cmd1,cmd2,..." --a append-file Exclude from, replace or append to the list of regex - matching commands which are safe to use within the - scope of a \\DIFadd or \\DIFdel command. The file must contain - one Perl-RegEx per line (Comment lines beginning with # or % are - ignored). A literal comma within the comma-separated list must be - escaped thus "\\,", Note that the RegEx needs to match the whole of - the token, i.e., /^regex\$/ is implied and that the initial - "\\" of the command is not included. The --exclude-safecmd - and --append-safecmd options can be combined with the --replace-safecmd - option and can be used repeatedly to add cumulatively to the lists. - ---exclude-textcmd=exclude-file ---exclude-textcmd="cmd1,cmd2,..." --X exclude-file ---replace-textcmd=replace-file ---append-textcmd=append-file ---append-textcmd="cmd1,cmd2,..." --x append-file Exclude from, replace or append to the list of regex - matching commands whose last argument is text. See - entry for --exclude-safecmd directly above for further details. - ---replace-context1cmd=replace-file ---append-context1cmd=append-file ---append-context1cmd="cmd1,cmd2,..." - Replace or append to the list of regex matching commands - whose last argument is text but which require a particular - context to work, e.g. \\caption will only work within a figure - or table. These commands behave like text commands, except when - they occur in a deleted section, when they are disabled, but their - argument is shown as deleted text. - ---replace-context2cmd=replace-file ---append-context2cmd=append-file ---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. - ---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. --c configfile Available variables: - MINWORDSBLOCK (integer) - FLOATENV (RegEx) - PICTUREENV (RegEx) - MATHENV (RegEx) - MATHREPL (String) - MATHARRENV (RegEx) - MATHARRREPL (String) - ARRENV (RegEx) - COUNTERCMD (RegEx) - This option can be repeated. - - ---packages=pkg1,pkg2,.. - Tell latexdiff that .tex file is processed with the packages in list - loaded. This is normally not necessary if the .tex file includes the - preamble, as the preamble is automatically scanned for \\usepackage commands. - Use of the --packages option disables automatic scanning, so if for any - reason package specific parsing needs to be switched off, use --packages=none. - The following packages trigger special behaviour: - endfloat hyperref amsmath apacite siunitx cleveref glossaries mhchem chemformula - [ Default: scan the preamble for \\usepackage commands to determine - loaded packages.] - ---show-preamble Print generated or included preamble commands to stdout. - ---show-safecmd Print list of regex matching and excluding safe commands. - ---show-textcmd Print list of regex matching and excluding commands with text argument. - ---show-config Show values of configuration variables - ---show-all Show all of the above - - NB For all --show commands, no old.tex or new.tex file needs to be given, and no - differencing takes place. - -Other configuration options: - ---allow-spaces Allow spaces between bracketed or braced arguments to commands - [Default requires arguments to directly follow each other without - intervening spaces] - ---math-markup=level Determine granularity of markup in displayed math environments: - Possible values for level are (both numerical and text labels are acceptable): - off or 0: suppress markup for math environments. Deleted equations will not - appear in diff file. This mode can be used if all the other modes - cause invalid latex code. - whole or 1: Differencing on the level of whole equations. Even trivial changes - to equations cause the whole equation to be marked changed. This - mode can be used if processing in coarse or fine mode results in - invalid latex code. - coarse or 2: Detect changes within equations marked up with a coarse - granularity; changes in equation type (e.g.displaymath to equation) - appear as a change to the complete equation. This mode is recommended - for situations where the content and order of some equations are still - being changed. [Default] - fine or 3: Detect small change in equations and mark up and fine granularity. - This mode is most suitable, if only minor changes to equations are - expected, e.g. correction of typos. - ---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 - ---label=label --L label Sets the labels used to describe the old and new files. The first use - of this option sets the label describing the old file and the second - use of the option sets the label for the new file. - [Default: use the filename and modification dates for the label] - ---no-label Suppress inclusion of old and new file names as comment in output file - ---visible-label Include old and new filenames (or labels set with --label option) as - visible output - ---flatten Replace \\input and \\include commands within body by the content - of the files in their argument. If \\includeonly is present in the - preamble, only those files are expanded into the document. However, - no recursion is done, i.e. \\input and \\include commands within - included sections are not expanded. The included files are assumed to - be located in the same directories as the old and new master files, - respectively, making it possible to organise files into old and new directories. - --flatten is applied recursively, so inputted files can contain further - \\input statements. - ---help --h Show this help text. - ---ignore-warnings Suppress warnings about inconsistencies in length between input - and parsed strings and missing characters. - ---verbose --V Output various status information to stderr during processing. - Default is to work silently. - ---version Show version number. - -EOF -} - -=head1 NAME - -latexdiff - determine and markup differences between two latex files - -=head1 SYNOPSIS - -B [ B ] F F > F - -=head1 DESCRIPTION - -Briefly, I is a utility program to aid in the management of -revisions of latex documents. It compares two valid latex files, here -called C and C, finds significant differences -between them (i.e., ignoring the number of white spaces and position -of line breaks), and adds special commands to highlight the -differences. Where visual highlighting is not possible, e.g. for changes -in the formatting, the differences are -nevertheless marked up in the source. - -The program treats the preamble differently from the main document. -Differences between the preambles are found using line-based -differencing (similarly to the Unix diff command, but ignoring white -spaces). A comment, "S>>" is appended to each added line, i.e. a -line present in C but not in C. Discarded lines - are deactivated by prepending "S>>". Changed blocks are preceded by -comment lines giving information about line numbers in the original files. Where there are insignificant -differences, the resulting file C will be similar to -C. At the end of the preamble, the definitions for I markup commands are inserted. -In differencing the main body of the text, I attempts to -satisfy the following guidelines (in order of priority): - -=over 3 - -=item 1 - -If both C and C are valid LaTeX, then the resulting -C should also be valid LateX. (NB If a few plain TeX commands -are used within C or C then C is not -guaranteed to work but usually will). - -=item 2 - -Significant differences are determined on the level of -individual words. All significant differences, including differences -between comments should be clearly marked in the resulting source code -C. - -=item 3 - -If a changed passage contains text or text-producing commands, then -running C through LateX should produce output where added -and discarded passages are highlighted. - -=item 4 - -Where there are insignificant differences, e.g. in the positioning of -line breaks, C should follow the formatting of C - -=back - -For differencing the same algorithm as I is used but words -instead of lines are compared. An attempt is made to recognize -blocks which are completely changed such that they can be marked up as a unit. -Comments are differenced line by line -but the number of spaces within comments is ignored. Commands including -all their arguments are generally compared as one unit, i.e., no mark-up -is inserted into the arguments of commands. However, for a selected -number of commands (for example, C<\caption> and all sectioning -commands) the last argument is known to be text. This text is -split into words and differenced just as ordinary text (use options to -show and change the list of text commands, see below). As the -algorithm has no detailed knowledge of LaTeX, it assumes all pairs of -curly braces immediately following a command (i.e. a sequence of -letters beginning with a backslash) are arguments for that command. -As a restriction to condition 1 above it is thus necessary to surround -all arguments with curly braces, and to not insert -extraneous spaces. For example, write - - \section{\textem{This is an emphasized section title}} - -and not - - \section {\textem{This is an emphasized section title}} - -or - - \section\textem{This is an emphasized section title} - -even though all varieties are the same to LaTeX (but see -B<--allow-spaces> option which allows the second variety). - -For environments whose content does not conform to standard LaTeX or -where graphical markup does not make sense all markup commands can be -removed by setting the PICTUREENV configuration variable, set by -default to C and C environments; see B<--config> -option). The latter environment (C) can be used to -protect parts of the latex file where the markup results in illegal -markup. You have to surround the offending passage in both the old and -new file by C<\begin{DIFnomarkup}> and C<\end{DIFnomarkup}>. You must -define the environment in the preambles of both old and new -documents. I prefer to define it as a null-environment, - -C<\newenvironment{DIFnomarkup}{}{}> - -but the choice is yours. Any markup within the environment will be -removed, and generally everything within the environment will just be -taken from the new file. - -It is also possible to difference files which do not have a preamble. - In this case, the file is processed in the main document -mode, but the definitions of the markup commands are not inserted. - -All markup commands inserted by I begin with "C<\DIF>". Added -blocks containing words, commands or comments which are in C -but not in C are marked by C<\DIFaddbegin> and C<\DIFaddend>. -Discarded blocks are marked by C<\DIFdelbegin> and C<\DIFdelend>. -Within added blocks all text is highlighted with C<\DIFadd> like this: -C<\DIFadd{Added text block}> -Selected `safe' commands can be contained in these text blocks as well -(use options to show and change the list of safe commands, see below). -All other commands as well as braces "{" and "}" are never put within -the scope of C<\DIFadd>. Added comments are marked by prepending -"S >>". - -Within deleted blocks text is highlighted with C<\DIFdel>. Deleted -comments are marked by prepending "S >>". Non-safe command -and curly braces within deleted blocks are commented out with -"S >>". - - - -=head1 OPTIONS - -=head2 Preamble - -The following options determine the visual markup style by adding the appropriate -command definitions to the preamble. See the end of this section for a description of -available styles. - -=over 4 - -=item B<--type=markupstyle> or -B<-t markupstyle> - -Add code to preamble for selected markup style. This option defines -C<\DIFadd> and C<\DIFdel> commands. -Available styles: - -C - -[ Default: C ] - -=item B<--subtype=markstyle> or -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 - -[ Default: C ] -* Subtype C