Я использую latexdiff
для отображения изменений, которые я вношу в большой текст (более 200 страниц). Большинство моих изменений затрагивают лишь несколько страниц, поэтому я не хочу, чтобы мои читатели просматривали 200 страниц в поисках редких страниц, где были сделаны отдельные исправления опечаток: только около 30 страниц из 200 будут содержать изменения.
Я хотел бы:
- Вставьте скрытые маркеры PDF на страницы, где происходят изменения.
- Компилировать с помощью pdflatex
Запустите скрипт, который отфильтрует страницы, не содержащие скрытых маркеров PDF.
book.tex -latexdiff-> book_diff.tex -pdftex-> 200pp.pdf -script-> 30pp.pdf
Может ли кто-нибудь порекомендовать:
- пакет tex для вставки «маркеров» определенного рода в PDF-файл
- пакет Python для чтения PDF-файлов (и поиска указанных маркеров)
решение1
Первой моей мыслью было использовать операции ввода-вывода файлов, например, \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
Итак, я написал первый черновик рабочего конвейера.
- По предложению @ChristianH я использовалpdfкомментарий
- Для сценария я использовал:
Код здесь: https://gist.github.com/ivanistheone/219dad11a30efef82b7e