GNU Emacs无法实时编译TeX文件

大家好,我想使用Emacs来写LaTeX文件,安装好AUCTex,想要用Skim这个阅读器来实时编译预览TeX文件,我在.emacs文件中配置了这些项:

(use-package tex :ensure auctex)
(require 'tex)
(require 'tex-site)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-save-query nil)
(setq TeX-engine 'xetex)
(setq TeX-PDF-mode t)
'(TeX-master 'dwim)
 '(TeX-source-correlate-start-server t)
 '(TeX-view-program-selection '((output-pdf "Skim")))

Skim里边也在Preferences > Sync中做了相应的设置。 但是这些配置都没有生效,我在键入"C-c C-c"之后还需要指定"XeLaTeX"来完成编译,它无法自动在文件变更后自动保存然后编译并预览,键入“C-c C-v”之后也并非以Skim预览。请问大家有没有相关的解决方案,谢谢🙏

  1. 需要指定 “XeLaTeX” 编译,可以设置 TeX-command-default 试试 C-c C-a
  2. 自动保存编译需要给 after-save-hook 添加相关逻辑
  3. 并非以 Skim 预览:
(setq TeX-view-program-list '(("Preview.app" "open -a Preview.app %o")
                              ("Skim" "open -a Skim.app %o")
                              ("displayline" "displayline -b %n %o %b")
                              ("open" "open %o"))
      TeX-view-program-selection '((output-dvi "open")
                                   (output-pdf "displayline")
                                   (output-html "open")))

另外你这段代码格式都不对

2 个赞

@Voleking 谢谢您的回复,我今天试着写了下after-save-hook的逻辑,现在可以做到保存后自动编译了。但是似乎还是不能够在文件内容变更后自动保存。 上面最后的那段代码是在Emacscustomize-variable中设置生成的,所以格式和通常见到的不太一样。

这是我更新后的.emacs代码,在最后的TeX-view后面不知道要怎么追加pdf的名字,这样编译后就可以自动打开预览了:

(use-package tex :ensure auctex)
(require 'tex)
(require 'tex-site)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-save-query nil)
(setq TeX-engine 'xetex)
(setq TeX-PDF-mode t)
(setq TeX-view-program-list '(("Preview.app" "open -a Preview.app %o")
                              ("Skim" "open -a Skim.app %o")
                              ("displayline" "displayline -b %n %o %b")
                              ("open" "open %o"))
      TeX-view-program-selection '((output-dvi "open")
                                   (output-pdf "displayline")
                                   (output-html "open")))

(defun auto-compile-after-save()
  "Used in `after-save-hook'."
  (when (and (memq this-command '(save-buffer save-some-buffer))
             (string-equal (file-name-extension (buffer-file-name)) "tex"))
    (server-start)
    (let ((TeX-command-extra-options "-shell-escape -synctex=1 -interaction=nonstopmode"))
      (TeX-command "XeLaTeX" 'TeX-master-file nil))
    (TeX-view )))

(add-hook 'after-save-hook 'auto-compile-after-save)

但我认为自动保存是一个更加重头的问题,不知道该怎么解决呢?

自动保存可以参考 manateelazycat/auto-save.

C-h v TeX-view-program-list 中提到的 TeX-expand-list-builtin 中说明了展开的 pdf 文件名称 (也就是上文中的 %o) 是如何被替换的.

(虽然实时预览听起来很不错, 但是根据机器的性能, 可能不会像想象的那么丝滑. 依靠 emacs 的 pretty-symbol 和图片插入应该可以做到差不多的效果吧. 可以看看论坛里的一些相关的帖子.

1 个赞

直接用 TeX-command-run-all 就好

(add-hook 'LaTeX-mode
          (defun init-latex-mode ()
            "Stuff to do when opening `LaTeX-mode' files."
            (add-save-hook 'after-save-hook
                           (lambda ()
                             (TeX-command-run-all nil))
                             nil t)))

TeX-engine 需要 setq-default

(setq-default TeX-engine 'xetex)

或者在每个 .tex 文件里单独设置

\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% TeX-engine: xetex
%%% End:

自动保存可以看相关插件,除了上面 auto-save,也可以看看 GitHub - bbatsov/super-save: Save Emacs buffers when they lose focus

但是加了自动保存结合上面的自动 View 的逻辑之后,会不断切换到 skim,打断编辑

1 个赞

@li-yiyang @Voleking 谢谢两位大佬的回复,

  1. auto-save工作得非常好,不过我一时半会还是没大弄懂%o在这个地方要怎么用,感觉我还是得多理解理解。所以我按照 @Voleking 说得直接用 TeX-command-run-all
  2. super-save我也试了下,似乎它不工作,我按照GitHub上readme配置得,所以现在只好先注释掉。
  3. 今天折腾了一晚上,可以让它自动保存并hook进行编译了,它确实会打断书写,所以我开了个新的进程先杀死正在卡顿的编译进程然后再去执行compile。现在有一个问题是,它总是起LaTeX的进程而不是我设定的XeLaTeX,所以编译总是失败然后卡在那里。我设置了TeX-engine的值为XeTeX,以及TeX-command的值为XeLaTeX,但都不工作,按照我的理解,TeX-command-run-all应该调用的是TeX-command-list里预设的某个值,这个值由TeX-command引用,它不工作的话是不是我理解错了。
  4. 我在.tex的文件末尾设置标注
%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% TeX-engine: xetex
%%% End:

也没有生效,编译启动的进程依然是LaTeX

下面是我当前的.emacs相关代码,请大佬们再帮忙看看:

(use-package tex :ensure auctex)
(require 'tex)
(require 'tex-site)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-save-query nil)
(setq-default TeX-engine 'xetex)
(setq-default TeX-PDF-mode t)

(add-to-list 'load-path "~/.emacs.d/auto-save") ; add auto-save to your load-path
(require 'auto-save)
(auto-save-enable)
(setq auto-save-idle 10)
(setq auto-save-silent t)   ; quietly save
(setq auto-save-delete-trailing-whitespace t)  ; automatically delete spaces at the end of the line when saving
(setq compilation-ask-about-save nil)

;;(require 'super-save)
;;(super-save-mode +1)
;;(setq super-save-auto-save-when-idle t)
;;(setq auto-save-default nil)

(setq TeX-view-program-list '(("Preview.app" "open -a Preview.app %o")
                              ("Skim" "open -a Skim.app %o")
                              ("displayline" "displayline -b %n %o %b")
                              ("open" "open %o"))
      TeX-view-program-selection '((output-dvi "open")
                                   (output-pdf "Skim")
                                   (output-html "open")))

(defun auto-compile-after-save()
  "Used in `after-save-hook'."
  (add-hook 'after-save-hook
            (lambda ()
              (start-process-shell-command "kill" nil "pkill -9 -f tex")
              (let ((TeX-command-extra-options "-shell-escape -synctex=1 -interaction=nonstopmode"))
                (TeX-command-run-all nil))
              nil t)))

(add-hook 'LaTeX-mode-hook 'auto-compile-after-save)

谢谢大家!

虽然 C-c C-c TeX-command-master/TeX-command-run-all TeX-command-defaultLaTeX,但实际上会根据 engine 调整执行命令

具体解释: C-h v TeX-command-list 可以看到执行 LaTeX Command 对应的内容

 ("LaTeX" "%`%l%(mode)%' %T" TeX-run-TeX nil (LaTeX-mode docTeX-mode) :help
  "Run LaTeX")

会根据 TeX-expand-list-builtinTeX-engine-alist-builtin 转换成实际的命令,其中部分展开:

"%l" -> (TeX-style-check LaTeX-command-style) -> "%(PDF)%(latex) %(file-line-error) %(extraopts) %(output-dir) %S%(PDFout)"
%(latex) -> (nth 3 (TeX-engine-in-engine-alist TeX-engine)) -> "xelatex"

上述中间部分代码可以复制到 tex 文件,然后 C-x C-e 执行

PS:

  1. 根据 TeX-expand-list-builtinTeX-interactive-modenil 时自动会添加 " -interaction=nonstopmode",因此就无需加入到 TeX-command-extra-options 了。
  2. 根据 TeX-engine-alist-builtin,改了 engine 之后再改变量 TeX-command LaTeX-command ConTeXt-engine 可能就没用

anyway,M-x TeX-recenter-output-buffer 可以查看编译命令和日志,然后 debug

可以参考下 .emacs.d/lisp/lang-tex.el at 2b67950de358a954afec05c106f2936beffab03c · tshu-w/.emacs.d · GitHub

1 个赞

浏览用系统自带的evince不是很好吗?

谢谢佬的仓库支援,折腾了一周末,现在可以做到自动保存和不打断书写的编译了。 我之前装了一些他人写得starterkit,结果导致环境很混乱。现在全部丢掉后才会有报错,发现前面的问题,无法使用xelatex编译的原因是我在文档末尾的注释里写得是XeTeX,现在才知道,这是区分大小写的。 从您的repo里摘抄了几条语句,联合查询Google和GPT学到了很多。 感觉还有很多知识需要学习啊!接下来还得搞定编译后自动激活Skim展示,目前它只是编译好了PDF文件。 最后再附上我现在的.emacs.d/lisp/init-tex.el的核心内容:

(use-package tex
  :straight auctex
  :defer t
  :config
  (setq-default TeX-master nil
                TeX-PDF-mode t
                TeX-engine 'xetex)
  (setq TeX-parse-self t
        TeX-save-query nil
        TeX-source-currelate-start-server t
        TeX-view-program-list '(("Preview.app" "open -a Preview.app %o")
                                ("Skim" "open -a Skim.app %o")
                                ("displayline" "displayline -b %n %o %b")
                                ("open" "open %o"))
        TeX-view-program-selection '((output-dvi "open")
                                     (output-pdf "Skim")
                                     (output-html "open"))
        ;; Don't insert line-break at inline math
        LaTeX-fill-break-at-separators nil)
  (defun TeX-auto-compile()
    (let* ((master (TeX-master-file))
           (process (and (stringp master) (TeX-process master))))
      (when (and (processp process)
                 (eq (process-status process) 'run))
        (delete-process process))
      (add-hook 'after-save-hook
                (lambda()
                  (let ((TeX-command-extra-options "-shell-escape -synctex=1 -interaction=nonstopmode"))
                    (TeX-command-run-all nil))
                  nil t))))
  (add-hook 'LaTeX-mode-hook 'TeX-auto-compile))
(provide 'init-tex)

哦哦,我其实不是很了解Emacs,所以它自带的evince也就不知道啦,我是Emacs小白,刚开始用这个工具。之前用得都是vimtex,当时用得是Skim联动。感觉vimtex实时编译保存很好用,所以在Emacs上想要重搬这套。 所以,一是不了解Emacs,入门阶段;二是对Skim更加熟练一些。我还是要多向大佬们学习学习,如果evince效果更好的话我也是会用的。

我是在Debian系统里。Emacs里用auctex插件,编译tex用快捷键C-c C-c组合键,浏览编译效果用C-c C-v快捷键。可以设置成evince做默认浏览器。evince是Linux系统自带的PDF浏览器,编译方式要设置成xelatex。我的Emacs中auctex插件的相关设置你可以参考一下 .emacs.d/lisp/init-latex.el at master · yinxiuqu/.emacs.d · GitHub 此外,如果你想一边写tex代码,一边实时预览效果,可以用preview-latex.el,要做如下设置:(load “preview-latex.el” nil t t),按快捷键就可实时显示或取消预览效果,快捷键好象是C-c C-p C-p,或者你可参考一下官网https://www.gnu.org/software/auctex/manual/preview-latex.pdf 我的设置文件中似乎有这个设置。

1 个赞

谢谢您的回复,我了解了。我是macOS,所以用得是Skimpreview-latex这个插件我也看过,不过我搜索到的内容显示它只能预览图片(?)和数学公式。我最开始的时候曾经试过它的效果,确实很强大,不过我想得是全文预览。所以我就寻找其他的解决方案了。

删除 process 的逻辑要放到 后面的 lambda 中去,否则只会每次在 LaTeX-mode-hook 的时候执行

1 个赞

嗯嗯,确实是的,大意了哈哈,谢谢您的提醒!