我用它latexdiff
来显示我在大型文本(超过 200 页)中所做的更改。不过,我的大部分更改只影响几页,因此我不希望读者仔细阅读 200 页以寻找少数几个进行了单独拼写更正的页面:200 页中只有大约 30 页包含更改。
我想:
- 在发生更改的页面上插入隐藏的 PDF 标记
- 使用 pdflatex 编译
运行脚本,过滤掉不包含隐藏 PDF 标记的页面
book.tex -latexdiff-> book_diff.tex -pdftex-> 200pp.pdf -script-> 30pp.pdf
有人可以推荐:
- 用于在 PDF 文件中插入某种“标记”的 tex 包
- 一个用于读取 PDF(并查找所述标记)的 Python 包
答案1
我的第一个想法是使用 I/O 文件操作,例如\write
或\immediate\write
,但它面临着浮动对象及其行为的已知问题。当没有\global
前缀时,我也遇到了带有自己计数器的浮动对象的问题。
我宁愿直接使用交叉引用来确保受保护的写入。我可以借助 LuaTeX 为您提供此解决方案。处理步骤如下:
- 我们排版一份常规文档并标记一个位置。就本文而言,这是一个可见的标记,也是一个页码。定义使用带有
\label
特定前缀的常规命令,例如malipivo
。我将文件filter.tex
和命令命名为\writeme
。该命令使用自己的计数器,这确保了命令中标记的唯一性\label
。 - 根据实际排版材料,文件
filter.tex
会被处理多次,本例中是两次。第一次运行后,我们得到一个带有两个红色问号的文档(预览中的第 1 行),第二次运行后,我们得到正确排版的交叉引用(预览中的第 2 行)。
这是代码:
%! *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}
该文件的内容filter.aux
如下:
\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}}
实际上,您可以看到,当数字与其页码对应项交换时,存在一些浮动对象(malipivo10
<-> malipivo9
;7
<-> 8
)。我们需要以某种方式处理此辅助文件并从中提取页面filter.pdf
。我使用了 LuaTeX 和pdfpages
包。
起初我以为我需要对行进行排序,但似乎没有必要,它已经按页码排序,而不是按标记排序。
但是,我需要提取
malipivo
包含前缀的行并跳过其他行。我使用的string.find
是 LuaTeX。此步骤的终端中有一个注释,上面写着Testing note on page 1...
。然后我需要提取页码来获得
1 1 2 2 2 2 4 4 7 8
,我使用了该string.gsub
函数。我必须保证每个页面只被包含一次,所以我们应该
1 2 4 7 8
在删除重复项后得到这个数字序列。我的下一步是添加逗号,我在连接临时字符串时这样做了。我们开始吧
1,2,4,7,8
。剩下的就比较简单了。我制作了一个 LaTeX 命令来获取
\includepdf[pages={1,2,4,7,8},fitpaper]{filter.pdf}
它并将其发送到文档主体。
我在 LuaTeX 中创建了一个简单的函数,它testme
有两个参数,第一个参数要求输入测试文件(filter
),代码使用它的aux
和pdf
文件,第二个参数要求输入我们使用的前缀(理论上可以有更多前缀),我使用了malipivo
。实际的排版由完成\directlua{testme("filter","malipivo")}
。
filtered.tex
我附上了一次运行的代码( )以及最后在原始代码()中标记的lualatex
选定页面的预览( ) 。filtered.pdf
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}
答案2
好的,我写了一个工作管道的初稿。
代码在这里: https://gist.github.com/ivanistheone/219dad11a30efef82b7e