latexmk 监控文件变更,自动编译

我使用 Org-mode 做笔记,有时有生成 PDF 的需要。原来是使用 C-c C-e 调用 org-export-dispatch 然后 l o 打开PDF。

这个流程中最大的问题是,编译 PDF 时,Emacs 会卡住,要等执行结束。虽然可以让编译异部进行,但是生成后不会主动告知文件已生成。

问了下 AI,才知道原来可以使用 latexmk 监控 tex 文件,如果有变更,则自动编译。

我在笔记的头部增加了“#+AUTO_GENERATE_TEX: t”,文件保存时自动生成 Tex 文件,让 latexmk 自动编译 PDF 即可,编译完成后发送一个通知,文件已生成。

(with-eval-after-load 'org
  (add-to-list 'org-options-keywords "AUTO_GENERATE_TEX:")
  
  (defun my/org-auto-export-to-latex ()
    (let* ((keywords (org-collect-keywords '("AUTO_GENERATE_TEX")))
           (val (cl-second (car keywords))))
      (when (string-equal (and val (downcase val)) "t")
	(let* ((base-path (file-name-sans-extension (buffer-file-name)))
               (tex-file (concat base-path ".tex"))
               (generated-file (org-export-to-file 'latex tex-file nil nil nil nil)))
          
          (if (and generated-file (file-exists-p generated-file))
              (progn
		(my/org-latex-auto-manage)
		(message "Tex 文件 %s 己生成!" tex-file))
            )))))

  (add-hook 'after-save-hook #'my/org-auto-export-to-latex)

  (defun my/org-latex-auto-manage ()
    "检测关键字并启动后台 latexmk,编译结果通过 macOS 通知。"
    (when-let* ((tex-file (concat (file-name-sans-extension (buffer-file-name)) ".tex"))
		(file-name (file-name-nondirectory tex-file))
		(process-name (concat "latexmk-" file-name))
		(file-dir (file-name-directory (buffer-file-name))))   
      (unless (get-process process-name)
        (let ((default-directory file-dir))
	  (start-process process-name "*latexmk-out*"
			 "latexmk" "-pvc" "-pdf" "-view=none" "-interaction=nonstopmode" file-name))
        (message "已开启针对 %s 的后台实时监控" file-name)))))

.latexmkrc

# 使用 XeLaTeX
$pdflatex = 'xelatex -interaction=nonstopmode -synctex=1 %S %D';

$pvc_view_file_mode = 0; 

# 设置文件修改检查的频率(秒)
$sleep_time = 2;

# 增加连续编译的缓冲
$pvc_timeout = 2;

$success_cmd = 'terminal-notifier -title "LaTeX 编译成功" -message "PDF已更新"';

$failure_cmd = 'terminal-notifier -title "LaTeX 编译失败" -message "请检查错误日志" -sound "Basso"';

pdf-tools 有个问题,编译生成期间,会报文件损坏的问题。不让 PDF 处于前台显示则没有这个问题。

3 个赞

这个不错,以前也不知道这个方式。

别绑定到 after-save-hook 上,太激进了。我用了 Emacs 的自动保存,会有点卡顿,保存过于频繁。

绑到 run-with-idle-timer 上,比较好。

latexmk -xelatex -pvc yourfatexfile