Estou usando latexdiff
para mostrar as alterações que faço em um texto grande (mais de 200 páginas). A maioria das minhas alterações afetam apenas algumas páginas, por isso não quero que meus leitores vasculhem 200 páginas procurando as raras páginas onde foram feitas correções isoladas de erros de digitação: apenas cerca de 30 pp das 200 conterão alterações.
Eu gostaria de:
- Insira marcadores PDF ocultos nas páginas onde ocorrem alterações
- Compilar com pdflatex
Execute um script que filtre as páginas que não contêm os marcadores PDF ocultos
book.tex -latexdiff-> book_diff.tex -pdftex-> 200pp.pdf -script-> 30pp.pdf
Alguém poderia recomendar:
- um pacote tex para inserir algum tipo de "marcadores" em um arquivo PDF
- um pacote python para ler PDFs (e procurar por esses marcadores)
Responder1
Meu primeiro pensamento foi usar as operações de arquivo de E/S, por exemplo, \write
or \immediate\write
, mas enfrentei um problema conhecido com objetos flutuantes e seu comportamento. Também tive problemas com objetos flutuantes com contador próprio quando não havia \global
prefixo.
Prefiro usar referências cruzadas diretamente onde uma gravação protegida é garantida. Posso lhe oferecer esta solução com a ajuda do LuaTeX. As etapas processadas são:
- Compomos um documento normal e marcamos uma posição. Para o propósito deste post é uma marca visível e é um número de página. A definição usa
\label
comando regular com um determinado prefixo, por exemplomalipivo
. Nomeei o arquivofilter.tex
e o comando\writeme
. O comando utiliza contador próprio e isso garante a exclusividade do marcador no\label
comando. - O
filter.tex
arquivo é processado diversas vezes dependendo do material tipográfico real, neste exemplo são duas vezes. Após a primeira execução, obtemos um documento com dois pontos de interrogação vermelhos (linha 1 na visualização), após a segunda execução, obtemos referências cruzadas formatadas corretamente (linha 2 na visualização).
Este é o código:
%! *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}
O conteúdo do filter.aux
arquivo é assim:
\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}}
Na verdade, você pode ver que há algum objeto flutuante à medida que os números são trocados por seus equivalentes de número de página ( malipivo10
<-> malipivo9
; 7
<-> 8
). Precisamos processar esse arquivo auxiliar de alguma forma e extrair as páginas do arquivo filter.pdf
. Usei LuaTeX e o pdfpages
pacote.
A princípio pensei que precisava ordenar as linhas, mas parece que não é necessário, já está ordenado pelos números das páginas, não pelos marcadores.
Porém, precisei extrair linhas com
malipivo
prefixo incluído e pular as demais. Useistring.find
do LuaTeX. Há uma nota no terminal desta etapa dizendoTesting note on page 1...
.Então precisei extrair os números das páginas para obter
1 1 2 2 2 2 4 4 7 8
, usei astring.gsub
função.Tive que garantir que cada página seria incluída apenas uma vez, portanto deveríamos obter essa sequência de números
1 2 4 7 8
após remover as duplicatas.Meu próximo passo foi adicionar vírgulas, fiz isso enquanto concatenava a string temporária. Estamos chegando
1,2,4,7,8
.O resto foi relativamente fácil. Eu criei um comando LaTeX para obtê-lo
\includepdf[pages={1,2,4,7,8},fitpaper]{filter.pdf}
e enviá-lo para o corpo do documento.
Eu criei uma função simples no LuaTeX chamada testme
com dois parâmetros, o primeiro parâmetro está pedindo o arquivo testado ( filter
), o código usa seus arquivos aux
e pdf
, e o segundo parâmetro está pedindo um prefixo que estávamos usando (em teoria, poderia haver mais prefixos), usei malipivo
. A composição tipográfica real é feita por \directlua{testme("filter","malipivo")}
.
Incluo o código ( filtered.tex
) a ser executado lualatex
uma vez e por fim uma prévia das páginas selecionadas ( filtered.pdf
) que foram marcadas no código original ( 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}
Responder2
Ok, então escrevi um primeiro rascunho de um pipeline funcional.
- Conforme sugestão de @ChristianH, useipdfcomentar
- Para o script, usei:
- minerador de pdfpara ler as anotações do PDF
- pdfrwpara escrever as páginas selecionadas
O código está aqui: https://gist.github.com/ivanistheone/219dad11a30efef82b7e