Ich verwende es, latexdiff
um Änderungen anzuzeigen, die ich in einem großen Text (200+ Seiten) vornehme. Die meisten meiner Änderungen betreffen jedoch nur wenige Seiten, daher möchte ich nicht, dass meine Leser 200 Seiten durchforsten müssen, um die wenigen Seiten zu finden, auf denen vereinzelte Tippfehlerkorrekturen vorgenommen wurden: Nur etwa 30 der 200 Seiten enthalten Änderungen.
Ich möchte:
- Einfügen versteckter PDF-Marker auf Seiten, auf denen Änderungen auftreten
- Kompilieren mit pdflatex
Führen Sie ein Skript aus, das Seiten herausfiltert, die die versteckten PDF-Marker nicht enthalten
book.tex -latexdiff-> book_diff.tex -pdftex-> 200pp.pdf -script-> 30pp.pdf
Kann jemand Folgendes empfehlen:
- ein Tex-Paket zum Einfügen von „Markierungen“ jeglicher Art in eine PDF-Datei
- ein Python-Paket zum Lesen von PDFs (und Suchen nach den genannten Markierungen)
Antwort1
Mein erster Gedanke war, die E/A-Dateioperationen zu verwenden, z. B. \write
oder \immediate\write
, aber dabei trat ein bekanntes Problem mit schwebenden Objekten und ihrem Verhalten auf. Ich hatte auch Probleme mit schwebenden Objekten mit eigenem Zähler, wenn kein \global
Präfix vorhanden war.
Ich habe lieber direkt Querverweise verwendet, bei denen ein geschütztes Schreiben gewährleistet ist. Diese Lösung kann ich Ihnen mit Hilfe von LuaTeX anbieten. Die verarbeiteten Schritte sind:
- Wir setzen ein normales Dokument und markieren eine Position. Für die Zwecke dieses Beitrags ist es eine sichtbare Markierung und eine Seitenzahl. Die Definition verwendet einen regulären
\label
Befehl mit einem bestimmten Präfix, z. B.malipivo
. Ich habe die Dateifilter.tex
und den Befehl genannt\writeme
. Der Befehl verwendet einen eigenen Zähler und das stellt die Eindeutigkeit der Markierung im\label
Befehl sicher. - Die
filter.tex
Datei wird je nach tatsächlichem Satzmaterial mehrmals verarbeitet, in diesem Beispiel zweimal. Nach dem ersten Durchlauf erhalten wir ein Dokument mit zwei roten Fragezeichen (Zeile 1 in der Vorschau), nach dem zweiten Durchlauf erhalten wir korrekt gesetzte Querverweise (Zeile 2 in der Vorschau).
Dies ist der Code:
%! *latex filter.tex
%! Run me twice or even more times to get references right.
\def\myprefixis{malipivo}
\documentclass[a4paper]{article}
\usepackage{tikz}
\usepackage[numbers]{kantlipsum}
\newcount\mycounter
\mycounter=0
% Our own marker...
% Save the reference and mark it...
\def\writeme{%
\global\advance\mycounter by 1%
\label{\myprefixis\the\mycounter}%
\begin{tikzpicture}%
\begin{pgfinterruptboundingbox}%
\node[red,font=\bfseries\Huge,scale=4]{\pageref{\myprefixis\the\mycounter}};%
\end{pgfinterruptboundingbox}%
\end{tikzpicture}%
}% End of \writeme...
\begin{document}
\section{My experiment}
\kant[1-2]\writeme
\kant[14]\writeme
\kant[15-16]\writeme
\kant[25]\writeme\ There is a typo and\writeme\ one more\writeme
\kant[26-32]\writeme
\kant[46]\writeme
\begin{figure}[p]
\kant[51] I am floating.\writeme
\end{figure}
\kant[52-61]\writeme
\end{document}
Der Inhalt der filter.aux
Datei sieht wie folgt aus:
\relax
\@writefile{toc}{\contentsline {section}{\numberline {1}My experiment}{1}}
\newlabel{malipivo1}{{1}{1}}
\newlabel{malipivo2}{{1}{1}}
\newlabel{malipivo3}{{1}{2}}
\newlabel{malipivo4}{{1}{2}}
\newlabel{malipivo5}{{1}{2}}
\newlabel{malipivo6}{{1}{2}}
\newlabel{malipivo7}{{1}{4}}
\newlabel{malipivo8}{{1}{4}}
\newlabel{malipivo10}{{1}{7}}
\newlabel{malipivo9}{{1}{8}}
Sie können tatsächlich sehen, dass es ein schwebendes Objekt gibt, da Zahlen durch ihre Seitenzahlen-Gegenstücke ersetzt werden ( malipivo10
<-> malipivo9
; 7
<-> 8
). Wir müssen diese Hilfsdatei irgendwie verarbeiten und die Seiten daraus extrahieren filter.pdf
. Ich habe LuaTeX und das pdfpages
Paket verwendet.
Zuerst dachte ich, dass ich die Zeilen sortieren müsste, aber das scheint nicht nötig zu sein, die Sortierung erfolgt bereits nach den Seitenzahlen und nicht nach den Markierungen.
Ich musste jedoch Zeilen mit enthaltenem Präfix extrahieren
malipivo
und die anderen überspringen. Ich habestring.find
LuaTeX verwendet. Im Terminal erscheint zu diesem Schritt eine Notiz mit dem InhaltTesting note on page 1...
.Dann musste ich Seitenzahlen extrahieren
1 1 2 2 2 2 4 4 7 8
, um sie zu erhalten. Ich habe diestring.gsub
Funktion verwendet.Ich musste sicherstellen, dass jede Seite nur einmal eingefügt wird, daher sollten wir nach dem Entfernen der Duplikate diese Zahlenfolge erhalten
1 2 4 7 8
.Mein nächster Schritt war das Hinzufügen von Kommas. Das habe ich beim Verketten der temporären Zeichenfolge gemacht. Wir kommen zum Punkt
1,2,4,7,8
.Der Rest war relativ einfach. Ich habe daraus einen LaTeX-Befehl gemacht, um
\includepdf[pages={1,2,4,7,8},fitpaper]{filter.pdf}
es abzurufen und an den Dokumenttext zu übertragen.
Ich habe eine einfache Funktion in LuaTeX testme
mit zwei Parametern erstellt. Der erste Parameter fragt nach der getesteten Datei ( filter
), der Code verwendet seine aux
und pdf
Dateien, und der zweite Parameter fragt nach einem von uns verwendeten Präfix (theoretisch könnte es mehrere Präfixe geben), ich habe verwendet malipivo
. Der eigentliche Schriftsatz wird von durchgeführt \directlua{testme("filter","malipivo")}
.
Anbei der Code ( filtered.tex
), der einmalig ausgeführt werden soll lualatex
und abschließend eine Vorschau ausgewählter Seiten ( filtered.pdf
), die im Originalcode markiert wurden ( filter.tex
).
%! lualatex filtered.tex
%! run me only once
\documentclass{article}
\usepackage{pdfpages}
\usepackage{luacode}
\begin{document}
\begin{luacode*}
function testme (filtering, thekey)
-- Initializing variables...
local myinput=filtering..".aux" -- Where are the reference?
local myinputpdf=filtering..".pdf" -- Where are the real PDF pages?
local mylines="" -- List of pages to get is?
local mycount=0 -- How many tested reference do we have?
local lastcount="" -- What is the previous reference?
-- The core of the function...
for mylinetemp in io.lines(myinput) do -- Read input file line by line
test=string.find(mylinetemp,thekey) -- Is a unique key involved?
if test~=nil then -- Yes, the key is present there...
myline=string.gsub(mylinetemp,"\\newlabel{"..thekey..".-}{{.-}{(.-)}}", "%1", 1) -- Find a group with page reference.
print("Testing note on page "..myline.."...") -- Print information to the terminal
mycount=mycount+1 -- Increase a number of tested references
if mycount==1 then -- Save the first value as the starting value
mylines=myline -- Start the resulting string
lastcount=myline -- Remember the last occurance
else -- Add value to the list if not already stored in the list
if lastcount~=myline then -- But only if last two values differ (aka uniq)
mylines=mylines..","..myline -- Add comma and value to the string (aka join)
lastcount=myline -- Remember this occurance as the last one for next testing
end -- of if not lastcount
end -- of if mycount
end -- of if thekey is involved
end -- of myline
-- Print the results and generate PDF via regular typesetting...
local keyresult="\\includepdf[pages={"..mylines.."},fitpaper]{"..myinputpdf.."}"
print(keyresult)
tex.print(keyresult)
end -- of function testme
\end{luacode*}
% The tested file, e.g. filter.{aux,pdf}, and its reference label prefix.
\directlua{testme("filter","malipivo")}
\end{document}
Antwort2
Okay, ich habe also einen ersten Entwurf einer funktionierenden Pipeline geschrieben.
- Gemäß dem Vorschlag von @ChristianH habe ichpdfkommentar
- Für das Skript habe ich Folgendes verwendet:
Der Code ist hier: https://gist.github.com/ivanistheone/219dad11a30efef82b7e