latexmk
是我用来编译文档的工具,该-pvc
选项是通常启用的。在此设置下,当我保存产生编译错误的文件时,会latexmk
通知出现错误并且文档未在查看器中更新(skim
就我而言)。一旦我更正了文件中的问题.tex
,latexmk
它就会再次启动并恢复其活动。特别是,打开的文档会正确刷新。
当我使用上述设置尝试编译beamer
类文档时(如果有任何不同,beamerposter
则使用包),出现了问题。在这种情况下,当编译一个有错误的文件时,latexmk
将报告问题,文档不会像以前一样更新。但是,一旦我纠正了源代码中的问题,latexmk
重新编译并生成正确的.pdf
文件,但打开文档的链接就会断开,我必须手动重新打开它……换句话说,打开的文档已经失效,无法“看到”纠正错误后创建的更新版本。
您知道如何处理这个问题吗?在哪里可以找到解决方案?
编辑:
我刚刚意识到,在编译不使用的源时也会发生同样的问题beamer
。这次的原因可能是tikz
图形。有什么想法吗?
编辑 2-可能的解决方法:
Skim
提供了revert
选项,似乎可以修复skim
与损坏/处理不当的 pdf 之间的断开链接。你能想出一种方法来将这个线索变成完整的解决方案吗?
答案1
该问题并不是特定于的latexmk
,而是与 Skim 有关,它的工作方式pdflatex
以及文件通知在 OSX(以及其底层的 Mach 内核)中的实现方式。
问题在于它
pdflatex
不会以原子方式更改 PDF 文件,而是在编译过程中或多或少地不断更新其中的位和字节。文件系统会注意到对文件的写入,并向监控 Skim 进程发送更新通知。它使用一些启发式方法,不为每个更改的字节发送更新事件(这将非常低效)。此处的常见方法是延迟更新通知,直到一段时间内没有出现新的更改(通常是几毫秒)。
如果此启发式方法与 的写入模式交互不良
pdflatex
,Skim 会在 PDF 准备就绪之前收到通知,并尝试读取尚未完成的 PDF 文件。但是,Skim 对此准备不足,这会导致各种问题:从奇怪的错误消息到崩溃,再到通知句柄丢失。最后是您观察到的行为。问题不应该本身绑定到特定文档类,例如
beamer
。但是,我还观察到它尤其与结合使用beamer
。我的假设是,在编译beamer
文档时,pdflatex
通常必须生成一大堆额外的文件(所有.toc
文件.vrb
) ,.nav
并且.snm
在这之间还花费了相对多的计算时间。因此,编译期间对 PDF 文件的更新频率较低,这增加了与文件系统启发式发送更改通知发生不良交互的可能性。
我个人解决这个问题的方法是添加另一个间接层:每当构建最终 PDF 的命令(我pdflatex
直接使用 或rubber
)成功终止时,我都会将结果复制document.pdf
到document-view.pdf
,这是我在 Skim 中打开的文件。复制几乎是即时发生的,更新机制运行良好。
我个人使用Makefile
来完成此任务,并结合一个小型 Ruby 脚本,该脚本会观察源文件,make
并在源文件发生更改时调用。要将此类行为集成到latexmk
一个脚本中,可能需要对 中的工具设置进行一些修改latexmkrc
(例如,设置$pdf_previewer='cp %S %S-view.pdf'
)。但是,我的经验latexmk
有限,我还没有测试过这个。
答案2
首先,检查一下Daniel 对这个问题的背景的精彩回答。
如果这对任何人来说仍然有意义,这里有一个latexmkrc
与 Skim 结合解决问题的例子。
笔记:一旦 LaTeX 编译完成,它就会依赖于自定义更新命令来 Skim,因此您需要在 Skim 本身中禁用文件的自动重新加载(检查https://sourceforge.net/p/skim-app/wiki/TeX_and_PDF_Synchronization/#reload-updated-pdf-files了解更多信息)
$pdf_mode = 1;
$pdf_previewer = 'open -a Skim';
$pdflatex = 'pdflatex -synctex=1 -interaction=nonstopmode';
# -- Custom update command --
$pdf_update_method = 4;
$pdf_update_command = 'file=%S; [ "${file:0:1}" == "/" ] || file="${PWD}/${file}"; \
/usr/bin/osascript << EOF
set theFile to POSIX file "${file}" as alias
tell application "Skim"
activate
set theDocs to get documents whose path is (get POSIX path of theFile)
if (count of theDocs) > 0 then revert theDocs
open theFile
end tell
EOF';
# -- End of custom update command --
@generated_exts = (@generated_exts, 'synctex.gz');